A2 Optimized WP - Version 3.0.0

Version Description

  • Fresh new UI
  • Front-end and Back-end benchmarks
  • Compare your performance against A2 Hosting's Turbo and Managed WordPress plans
  • Find new recommendations on areas where you could further improve your performance
Download this release

Release Info

Developer a2hosting
Plugin Icon 128x128 A2 Optimized WP
Version 3.0.0
Comparing to
See all releases

Code changes from version 2.1.5.1 to 3.0.0

Files changed (53) hide show
  1. A2_Optimized_CLI.php +0 -264
  2. A2_Optimized_Optimizations.php +0 -901
  3. A2_Optimized_OptionsManager.php +0 -3270
  4. A2_Optimized_Plugin.php +0 -859
  5. A2_Optimized_Server_Info.php +0 -80
  6. LICENSE.txt +339 -0
  7. a2-optimized.php +115 -131
  8. advanced-cache.php +2 -2
  9. app/class-activator.php +26 -0
  10. app/class-deactivator.php +43 -0
  11. app/class-uninstaller.php +26 -0
  12. app/controllers/admin/class-admin-settings.php +398 -0
  13. app/controllers/admin/class-base-controller.php +35 -0
  14. app/models/admin/class-admin-settings.php +655 -0
  15. app/models/admin/class-base-model.php +44 -0
  16. app/models/class-settings.php +132 -0
  17. app/templates/admin/errors/admin-notice.php +5 -0
  18. app/templates/admin/errors/requirements-error.php +14 -0
  19. app/templates/admin/page-settings/page-settings-fields.php +1 -0
  20. app/templates/admin/page-settings/page-settings.php +893 -0
  21. app/views/admin/class-admin-settings.php +206 -0
  22. assets/bootstrap/config.json +19 -1
  23. assets/bootstrap/css/bootstrap-theme.css +582 -581
  24. assets/bootstrap/css/bootstrap.css +1202 -0
  25. assets/bootstrap/css/bootstrap.min.css +1 -1
  26. assets/bootstrap/js/bootstrap.js +167 -1
  27. assets/css/admin/a2-optimized.css +972 -0
  28. assets/css/admin/a2-optimized.css.map +1 -0
  29. assets/css/admin/animate.min.css +7 -0
  30. assets/{index.php → css/admin/index.php} +0 -0
  31. assets/css/style.css +0 -148
  32. assets/images/a2-exclusive.png +0 -0
  33. assets/images/a2optimized.png +0 -0
  34. assets/images/admin/a2opt-logo-2022-2x.png +0 -0
  35. assets/images/admin/a2opt-logo-2022.png +0 -0
  36. assets/images/admin/index.php +2 -0
  37. assets/images/admin/wave-danger.png +0 -0
  38. assets/images/admin/wave-empty.png +0 -0
  39. assets/images/admin/wave-success.png +0 -0
  40. assets/images/admin/wave-warn.png +0 -0
  41. assets/images/background-both.png +0 -0
  42. assets/images/background-left.png +0 -0
  43. assets/images/background-right.png +0 -0
  44. assets/images/brankic1979-icon-set.png +0 -0
  45. assets/images/icons.png +0 -0
  46. assets/images/image001.jpg +0 -0
  47. assets/images/spinner.gif +0 -0
  48. assets/js/admin/a2-optimized.js +854 -0
  49. assets/js/admin/axios.js +1603 -0
  50. assets/js/admin/chart.min.js +13 -0
  51. assets/js/admin/circles.min.js +7 -0
  52. assets/js/admin/index.php +2 -0
  53. assets/js/admin/vue.js +4084 -0
A2_Optimized_CLI.php DELETED
@@ -1,264 +0,0 @@
1
- <?php
2
- /**
3
- * Interact with A2 Optimized
4
- */
5
-
6
- if ( ! defined( 'ABSPATH' ) ) {
7
- exit;
8
- }
9
-
10
- class A2_Optimized_CLI {
11
- /**
12
- * Clear the page cache.
13
- *
14
- * ## OPTIONS
15
- *
16
- * [--ids=<id>]
17
- * : Clear the cache for given post ID(s). Separate multiple IDs with commas.
18
- *
19
- * [--urls=<url>]
20
- * : Clear the cache for the given URL(s). Separate multiple URLs with commas.
21
- *
22
- * [--sites=<site>]
23
- * : Clear the cache for the given blog ID(s). Separate multiple blog IDs with commas.
24
- *
25
- * ## EXAMPLES
26
- *
27
- * # Clear all pages cache.
28
- * $ wp a2-optimized clear
29
- * Success: Site cache cleared.
30
- *
31
- * # Clear the page cache for post IDs 1, 2, and 3.
32
- * $ wp a2-optimized clear --ids=1,2,3
33
- * Success: Pages cache cleared.
34
- *
35
- * # Clear the page cache for a particular URL.
36
- * $ wp a2-optimized clear --urls=https://www.example.com/about-us/
37
- * Success: Page cache cleared.
38
- *
39
- * # Clear all pages cache for sites with blog IDs 1, 2, and 3.
40
- * $ wp a2-optimized clear --sites=1,2,3
41
- * Success: Sites cache cleared.
42
- *
43
- * @alias clear
44
- */
45
-
46
- public function clear($args, $assoc_args) {
47
- $assoc_args = wp_parse_args(
48
- $assoc_args,
49
- array(
50
- 'ids' => '',
51
- 'urls' => '',
52
- 'sites' => '',
53
- )
54
- );
55
-
56
- if ( empty( $assoc_args['ids'] ) && empty( $assoc_args['urls'] ) && empty( $assoc_args['sites'] ) ) {
57
- A2_Optimized_Cache::clear_complete_cache();
58
-
59
- return WP_CLI::success( ( is_multisite() ) ? esc_html__( 'Network cache cleared.', 'a2-optimized-wp' ) : esc_html__( 'Site cache cleared.', 'a2-optimized-wp' ) );
60
- }
61
-
62
- if ( ! empty( $assoc_args['ids'] ) || ! empty( $assoc_args['urls'] ) ) {
63
- array_map( 'A2_Optimized_Cache::clear_page_cache_by_post_id', explode( ',', $assoc_args['ids'] ) );
64
- array_map( 'A2_Optimized_Cache::clear_page_cache_by_url', explode( ',', $assoc_args['urls'] ) );
65
-
66
- $separators = substr_count( $assoc_args['ids'], ',' ) + substr_count( $assoc_args['urls'], ',' );
67
-
68
- if ( $separators > 0 ) {
69
- return WP_CLI::success( esc_html__( 'Pages cache cleared.', 'a2-optimized-wp' ) );
70
- } else {
71
- return WP_CLI::success( esc_html__( 'Page cache cleared.', 'a2-optimized-wp' ) );
72
- }
73
- }
74
-
75
- if ( ! empty( $assoc_args['sites'] ) ) {
76
- array_map( 'A2_Optimized_Cache::clear_site_cache_by_blog_id', explode( ',', $assoc_args['sites'] ) );
77
-
78
- $separators = substr_count( $assoc_args['sites'], ',' );
79
-
80
- if ( $separators > 0 ) {
81
- return WP_CLI::success( esc_html__( 'Sites cache cleared.', 'a2-optimized-wp' ) );
82
- } else {
83
- return WP_CLI::success( esc_html__( 'Site cache cleared.', 'a2-optimized-wp' ) );
84
- }
85
- }
86
- }
87
-
88
- /**
89
- * Enables various parts of the A2 Optimized plugin
90
- *
91
- * ## OPTIONS
92
- *
93
- * [module]
94
- * Enable the specified module:
95
- * - page_cache - Page Caching
96
- * - object_cache - Object Caching
97
- * - gzip - GZip compression
98
- * - html_min - HTML Minification
99
- * - cssjs_min - CSS/JS Minification
100
- * - xmlrpc - Block XML-RPC requests
101
- * - htaccess - Deny access to .htaccess
102
- * - lock_plugins - Block editing of Plugins and Themes
103
- *
104
- * ## EXAMPLES
105
- *
106
- * # Enable Page Caching
107
- * $ wp a2-optimized enable page_cache
108
- * Success: Site Page Cache enabled.
109
- *
110
- */
111
-
112
- public function enable($args, $assoc_args) {
113
- $options_manager = new A2_Optimized_OptionsManager;
114
- $to_enable = $args[0];
115
-
116
- $site_type = 'Site';
117
- if (is_multisite()) {
118
- $site_type = 'Network';
119
- }
120
-
121
- switch ($to_enable) {
122
- case 'page_cache':
123
- $options_manager->enable_a2_page_cache();
124
-
125
- return WP_CLI::success(esc_html__( $site_type . ' Page Cache enabled.', 'a2-optimized-wp' ));
126
- break;
127
- case 'object_cache':
128
- $options_manager->enable_a2_object_cache();
129
-
130
- return WP_CLI::success(esc_html__( $site_type . ' Object Cache enabled.', 'a2-optimized-wp' ));
131
- break;
132
- case 'gzip':
133
- $options_manager->enable_a2_page_cache_gzip();
134
-
135
- return WP_CLI::success(esc_html__( $site_type . ' GZIP enabled.', 'a2-optimized-wp' ));
136
- break;
137
- case 'html_min':
138
- $options_manager->enable_a2_page_cache_minify_html();
139
-
140
- return WP_CLI::success(esc_html__( $site_type . ' HTML Minify enabled.', 'a2-optimized-wp' ));
141
- break;
142
- case 'cssjs_min':
143
- $options_manager->enable_a2_page_cache_minify_jscss();
144
-
145
- return WP_CLI::success(esc_html__( $site_type . ' JS/CSS Minify enabled.', 'a2-optimized-wp' ));
146
- break;
147
- case 'xmlrpc':
148
- $options_manager->enable_xmlrpc_requests();
149
-
150
- return WP_CLI::success(esc_html__( $site_type . ' XML-RPC Request Blocking enabled.', 'a2-optimized-wp' ));
151
- break;
152
- case 'htaccess':
153
- $options_manager->set_deny_direct(true);
154
- $options_manager->write_htaccess();
155
-
156
- return WP_CLI::success(esc_html__( $site_type . ' Deny Direct Access to .htaccess enabled.', 'a2-optimized-wp' ));
157
- break;
158
- case 'lock_plugins':
159
- $options_manager->set_lockdown(true);
160
- $options_manager->write_wp_config();
161
-
162
- return WP_CLI::success(esc_html__( $site_type . ' Lock editing of Plugins and Themes enabled.', 'a2-optimized-wp' ));
163
- break;
164
- }
165
- }
166
-
167
- /**
168
- * Disables various parts of the A2 Optimized plugin
169
- *
170
- * ## OPTIONS
171
- *
172
- * [module]
173
- * Disable the specified module:
174
- * - page_cache - Page Caching
175
- * - object_cache - Object Caching
176
- * - gzip - GZip compression
177
- * - html_min - HTML Minification
178
- * - cssjs_min - CSS/JS Minification
179
- * - xmlrpc - Block XML-RPC requests
180
- * - htaccess - Deny access to .htaccess
181
- * - lock_plugins - Block editing of Plugins and Themes
182
- *
183
- * ## EXAMPLES
184
- *
185
- * # Disable Page Caching
186
- * $ wp a2-optimized disable page_cache
187
- * Success: Site Page Cache disabled.
188
- *
189
- */
190
-
191
- public function disable($args, $assoc_args) {
192
- $options_manager = new A2_Optimized_OptionsManager;
193
-
194
- $to_disable = $args[0];
195
-
196
- $site_type = 'Site';
197
- if (is_multisite()) {
198
- $site_type = 'Network';
199
- }
200
- switch ($to_disable) {
201
- case 'page_cache':
202
- $options_manager->disable_a2_page_cache();
203
-
204
- return WP_CLI::success(esc_html__( $site_type . ' Page Cache disabled.', 'a2-optimized-wp' ));
205
- break;
206
- case 'object_cache':
207
- $options_manager->disable_a2_object_cache();
208
-
209
- return WP_CLI::success(esc_html__( $site_type . ' Object Cache disabled.', 'a2-optimized-wp' ));
210
- break;
211
- case 'gzip':
212
- $options_manager->disable_a2_page_cache_gzip();
213
-
214
- return WP_CLI::success(esc_html__( $site_type . ' GZIP disabled.', 'a2-optimized-wp' ));
215
- break;
216
- case 'html_min':
217
- $options_manager->disable_a2_page_cache_minify_html();
218
-
219
- return WP_CLI::success(esc_html__( $site_type . ' HTML Minify disabled.', 'a2-optimized-wp' ));
220
- break;
221
- case 'cssjs_min':
222
- $options_manager->disable_a2_page_cache_minify_jscss();
223
-
224
- return WP_CLI::success(esc_html__( $site_type . ' JS/CSS Minify disabled.', 'a2-optimized-wp' ));
225
- break;
226
- case 'xmlrpc':
227
- $options_manager->disable_xmlrpc_requests();
228
-
229
- return WP_CLI::success(esc_html__( $site_type . ' XML-RPC Request Blocking disabled.', 'a2-optimized-wp' ));
230
- break;
231
- case 'htaccess':
232
- $options_manager->set_deny_direct(false);
233
- $options_manager->write_htaccess();
234
-
235
- return WP_CLI::success(esc_html__( $site_type . ' Deny Direct Access to .htaccess disabled.', 'a2-optimized-wp' ));
236
- break;
237
- case 'lock_plugins':
238
- $options_manager->set_lockdown(false);
239
- $options_manager->write_wp_config();
240
-
241
- return WP_CLI::success(esc_html__( $site_type . ' Lock editing of Plugins and Themes disabled.', 'a2-optimized-wp' ));
242
- break;
243
- }
244
- }
245
-
246
- public function memcached_server($args, $assoc_args) {
247
- $server_address = $args[0];
248
-
249
- $site_type = 'Site';
250
- if (is_multisite()) {
251
- $site_type = 'Network';
252
- }
253
-
254
- update_option('a2_optimized_memcached_server', $server_address);
255
-
256
- $options_manager = new A2_Optimized_OptionsManager;
257
- $options_manager->write_wp_config();
258
-
259
- return WP_CLI::success(esc_html__( $site_type . ' Memcached server updated.', 'a2-optimized-wp' ));
260
- }
261
- }
262
-
263
- // add WP-CLI command
264
- WP_CLI::add_command( 'a2-optimized', 'A2_Optimized_CLI' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
A2_Optimized_Optimizations.php DELETED
@@ -1,901 +0,0 @@
1
- <?php
2
-
3
- /*
4
- Author: Benjamin Cool
5
- Author URI: https://www.a2hosting.com/
6
- License: GPLv2 or Later
7
- */
8
-
9
- // Prevent direct access to this file
10
- if (! defined('WPINC')) {
11
- die;
12
- }
13
-
14
- require_once 'A2_Optimized_Server_Info.php';
15
-
16
- class A2_Optimized_Optimizations {
17
- private $thisclass;
18
- public $server_info;
19
-
20
- public function __construct($thisclass) {
21
- $this->thisclass = $thisclass;
22
- $w3tc = $thisclass->get_w3tc_config();
23
- $this->check_server_gzip();
24
- $this->server_info = new A2_Optimized_Server_Info($w3tc);
25
- }
26
-
27
- /**
28
- * Checks if gzip test has been run to see if server is serving gzip, if not we run it.
29
- * Expires after one week to reduce number of curl calls to server
30
- */
31
- public function check_server_gzip() {
32
- $checked_gzip = get_transient('a2_checked_gzip');
33
- if (false === $checked_gzip) {
34
- $w3tc = $this->thisclass->get_w3tc_config();
35
- if (is_array($w3tc)) {
36
- $previous_setting = $w3tc['browsercache.html.compression'];
37
- $this->thisclass->disable_w3tc_gzip();
38
- if ($previous_setting && is_object($this->server_info)) {
39
- if (!$this->server_info->gzip || !$this->server_info->cf || !$this->server_info->br) {
40
- $this->thisclass->enable_w3tc_gzip();
41
- }
42
- }
43
- }
44
- set_transient('a2_checked_gzip', true, WEEK_IN_SECONDS);
45
- }
46
- }
47
-
48
- public function get_optimizations() {
49
- $public_opts = $this->get_public_optimizations();
50
- $private_opts = $this->get_private_optimizations();
51
-
52
- if (!is_plugin_active('a2-w3-total-cache/a2-w3-total-cache.php')) {
53
- unset($private_opts['memcached']);
54
- }
55
-
56
- return array_merge($public_opts, $private_opts);
57
- }
58
-
59
- protected function get_public_optimizations() {
60
- $thisclass = $this->thisclass;
61
- $thisclass->server_info = $this->server_info;
62
-
63
- $a2_object_cache_additional_info = '';
64
-
65
- if (get_option('a2_optimized_memcached_invalid')) {
66
- $a2_object_cache_additional_info = '<p><strong>Please confirm your server settings before enabling Object Caching.</strong><br />' . get_option('a2_optimized_memcached_invalid') . '</p>';
67
- }
68
-
69
- if (is_plugin_active('a2-w3-total-cache/a2-w3-total-cache.php')) {
70
- /* W3 Total Cache Caching */
71
- $optimizations = [
72
- 'page_cache' => [
73
- 'slug' => 'page_cache',
74
- 'name' => 'Page Caching with W3 Total Cache',
75
- 'plugin' => 'W3 Total Cache',
76
- 'configured' => false,
77
- 'description' => 'Utilize W3 Total Cache to make the site faster by caching pages as static content. Cache: a copy of rendered dynamic pages will be saved by the server so that the next user does not need to wait for the server to generate another copy.',
78
- 'is_configured' => function (&$item) use (&$thisclass) {
79
- $w3tc = $thisclass->get_w3tc_config();
80
- if ($w3tc['pgcache.enabled']) {
81
- $item['configured'] = true;
82
- $permalink_structure = get_option('permalink_structure');
83
- $vars = [];
84
- if ($w3tc['pgcache.engine'] == 'apc') {
85
- if ($permalink_structure == '') {
86
- $vars['pgcache.engine'] = 'file';
87
- } else {
88
- $vars['pgcache.engine'] = 'file_generic';
89
- }
90
- } else {
91
- if ($permalink_structure == '' && $w3tc['pgcache.engine'] != 'file') {
92
- $vars['pgcache.engine'] = 'file';
93
- } elseif ($permalink_structure != '' && $w3tc['pgcache.engine'] == 'file') {
94
- $vars['pgcache.engine'] = 'file_generic';
95
- }
96
- }
97
-
98
- if (count($vars) != 0) {
99
- $thisclass->update_w3tc($vars);
100
- }
101
-
102
- $thisclass->set_install_status('page_cache', true);
103
- } else {
104
- $thisclass->set_install_status('page_cache', false);
105
- }
106
- },
107
- 'kb' => 'http://www.a2hosting.com/kb/installable-applications/optimization-and-configuration/wordpress2/optimizing-wordpress-with-w3-total-cache-and-gtmetrix',
108
- 'disable' => function () use (&$thisclass) {
109
- $thisclass->disable_w3tc_page_cache();
110
- },
111
- 'enable' => function () use (&$thisclass) {
112
- $thisclass->enable_w3tc_page_cache();
113
- }
114
- ],
115
- 'db_cache' => [
116
- 'slug' => 'db_cache',
117
- 'name' => 'DB Caching with W3 Total Cache',
118
- 'plugin' => 'W3 Total Cache',
119
- 'configured' => false,
120
- 'description' => 'Speed up the site by storing the responses of common database queries in a cache.',
121
- 'is_configured' => function (&$item) use (&$thisclass) {
122
- $w3tc = $thisclass->get_w3tc_config();
123
- if ($w3tc['dbcache.enabled']) {
124
- $vars = [];
125
- $item['configured'] = true;
126
- if (class_exists('W3_Config')) {
127
- if (class_exists('WooCommerce')) {
128
- if (array_search('_wc_session_', $w3tc['dbcache.reject.sql']) === false) {
129
- $vars['dbcache.reject.sql'] = $w3tc['dbcache.reject.sql'];
130
- $vars['dbcache.reject.sql'][] = '_wc_session_';
131
- }
132
- }
133
- }
134
- if (count($vars) != 0) {
135
- $thisclass->update_w3tc($vars);
136
- }
137
-
138
- $thisclass->set_install_status('db_cache', true);
139
- } else {
140
- $thisclass->set_install_status('db_cache', false);
141
- }
142
- },
143
- 'kb' => 'http://www.a2hosting.com/kb/installable-applications/optimization-and-configuration/wordpress2/optimizing-wordpress-with-w3-total-cache-and-gtmetrix',
144
- 'disable' => function () use (&$thisclass) {
145
- $thisclass->disable_w3tc_db_cache();
146
- },
147
- 'enable' => function () use (&$thisclass) {
148
- $thisclass->enable_w3tc_db_cache();
149
- }
150
- ],
151
- 'object_cache' => [
152
- 'slug' => 'object_cache',
153
- 'name' => 'Object Caching with W3 Total Cache',
154
- 'plugin' => 'W3 Total Cache',
155
- 'configured' => false,
156
- 'description' => 'Store a copy of widgets and menu bars in cache to reduce the time it takes to render pages.',
157
- 'is_configured' => function (&$item) use (&$thisclass) {
158
- $w3tc = $thisclass->get_w3tc_config();
159
- if ($w3tc['objectcache.enabled']) {
160
- $item['configured'] = true;
161
- $thisclass->set_install_status('object_cache', true);
162
- } else {
163
- $thisclass->set_install_status('object_cache', false);
164
- }
165
- },
166
- 'kb' => 'http://www.a2hosting.com/kb/installable-applications/optimization-and-configuration/wordpress2/optimizing-wordpress-with-w3-total-cache-and-gtmetrix',
167
- 'disable' => function () use (&$thisclass) {
168
- $thisclass->disable_w3tc_object_cache();
169
- },
170
- 'enable' => function () use (&$thisclass) {
171
- $thisclass->enable_w3tc_object_cache();
172
- }
173
- ],
174
- 'browser_cache' => [
175
- 'slug' => 'browser_cache',
176
- 'name' => 'Browser Caching with W3 Total Cache',
177
- 'plugin' => 'W3 Total Cache',
178
- 'configured' => false,
179
- 'description' => 'Add Rules to the web server to tell the visitor&apos;s browser to store a copy of static files to reduce the load time pages requested after the first page is loaded.',
180
- 'is_configured' => function (&$item) use (&$thisclass) {
181
- $w3tc = $thisclass->get_w3tc_config();
182
- if ($w3tc['browsercache.enabled']) {
183
- $item['configured'] = true;
184
- $thisclass->set_install_status('browser_cache', true);
185
- } else {
186
- $thisclass->set_install_status('browser_cache', false);
187
- }
188
- },
189
- 'kb' => 'http://www.a2hosting.com/kb/installable-applications/optimization-and-configuration/wordpress2/optimizing-wordpress-with-w3-total-cache-and-gtmetrix',
190
- 'disable' => function () use (&$thisclass) {
191
- $thisclass->disable_w3tc_browser_cache();
192
- },
193
- 'enable' => function () use (&$thisclass) {
194
- $thisclass->enable_w3tc_browser_cache();
195
- }
196
- ],
197
- 'minify' => [
198
- 'name' => 'Minify HTML Pages',
199
- 'slug' => 'minify',
200
- 'plugin' => 'W3 Total Cache',
201
- 'optional' => false,
202
- 'configured' => false,
203
- 'kb' => 'http://www.a2hosting.com/kb/installable-applications/optimization-and-configuration/wordpress2/optimizing-wordpress-with-w3-total-cache-and-gtmetrix',
204
- 'description' => 'Removes extra spaces,tabs and line breaks in the HTML to reduce the size of the files sent to the user.',
205
- 'is_configured' => function (&$item) use (&$thisclass) {
206
- $w3tc = $thisclass->get_w3tc_config();
207
- if ($w3tc['minify.enabled'] && $w3tc['minify.html.enable']) {
208
- $item['configured'] = true;
209
- $thisclass->set_install_status('minify-html', true);
210
- } else {
211
- $thisclass->set_install_status('minify-html', false);
212
- }
213
- },
214
- 'enable' => function () use (&$thisclass) {
215
- $thisclass->enable_html_minify();
216
- },
217
- 'disable' => function () use (&$thisclass) {
218
- $thisclass->disable_html_minify();
219
- }
220
- ],
221
- 'css_minify' => [
222
- 'name' => 'Minify CSS Files',
223
- 'slug' => 'css_minify',
224
- 'plugin' => 'W3 Total Cache',
225
- 'configured' => false,
226
- 'kb' => 'http://www.a2hosting.com/kb/installable-applications/optimization-and-configuration/wordpress2/optimizing-wordpress-with-w3-total-cache-and-gtmetrix',
227
- 'description' => 'Makes your site faster by condensing css files into a single downloadable file and by removing extra space in CSS files to make them smaller.',
228
- 'is_configured' => function (&$item) use (&$thisclass) {
229
- $w3tc = $thisclass->get_w3tc_config();
230
- if ($w3tc['minify.css.enable']) {
231
- $item['configured'] = true;
232
- $thisclass->set_install_status('minify-css', true);
233
- } else {
234
- $thisclass->set_install_status('minify-css', false);
235
- }
236
- },
237
- 'enable' => function () use (&$thisclass) {
238
- $thisclass->update_w3tc([
239
- 'minify.css.enable' => true,
240
- 'minify.enabled' => true,
241
- 'minify.auto' => 0,
242
- 'minify.engine' => 'file'
243
- ]);
244
- },
245
- 'disable' => function () use (&$thisclass) {
246
- $thisclass->update_w3tc([
247
- 'minify.css.enable' => false,
248
- 'minify.auto' => 0
249
- ]);
250
- }
251
- ],
252
- 'js_minify' => [
253
- 'name' => 'Minify JS Files',
254
- 'slug' => 'js_minify',
255
- 'plugin' => 'W3 Total Cache',
256
- 'configured' => false,
257
- 'kb' => 'http://www.a2hosting.com/kb/installable-applications/optimization-and-configuration/wordpress2/optimizing-wordpress-with-w3-total-cache-and-gtmetrix',
258
- 'description' => 'Makes your site faster by condensing JavaScript files into a single downloadable file and by removing extra space in JavaScript files to make them smaller.',
259
- 'is_configured' => function (&$item) use (&$thisclass) {
260
- $w3tc = $thisclass->get_w3tc_config();
261
- if ($w3tc['minify.js.enable']) {
262
- $item['configured'] = true;
263
- $thisclass->set_install_status('minify-js', true);
264
- } else {
265
- $thisclass->set_install_status('minify-js', false);
266
- }
267
- },
268
- 'enable' => function () use (&$thisclass) {
269
- $thisclass->update_w3tc([
270
- 'minify.js.enable' => true,
271
- 'minify.enabled' => true,
272
- 'minify.auto' => 0,
273
- 'minify.engine' => 'file'
274
- ]);
275
- },
276
- 'disable' => function () use (&$thisclass) {
277
- $thisclass->update_w3tc([
278
- 'minify.js.enable' => false,
279
- 'minify.auto' => 0
280
- ]);
281
- }
282
- ],
283
- 'gzip' => [
284
- 'name' => 'Gzip Compression Enabled',
285
- 'slug' => 'gzip',
286
- 'plugin' => 'W3 Total Cache',
287
- 'configured' => false,
288
- 'description' => 'Makes your site significantly faster by compressing all text files to make them smaller.',
289
- 'is_configured' => function (&$item) use (&$thisclass) {
290
- $w3tc = $thisclass->get_w3tc_config();
291
- if ($w3tc['browsercache.html.compression'] || $thisclass->server_info->cf || $thisclass->server_info->gzip || $thisclass->server_info->br) {
292
- $item['configured'] = true;
293
- $thisclass->set_install_status('gzip', true);
294
- } else {
295
- $thisclass->set_install_status('gzip', false);
296
- }
297
- },
298
- 'enable' => function () use (&$thisclass) {
299
- $thisclass->enable_w3tc_gzip();
300
- },
301
- 'disable' => function () use (&$thisclass) {
302
- $thisclass->disable_w3tc_gzip();
303
- },
304
- 'remove_link' => true
305
- ]
306
- ];
307
- } else {
308
- /* Internal Caching */
309
- $optimizations = [
310
- 'a2_page_cache' => [
311
- 'slug' => 'a2_page_cache',
312
- 'name' => 'Page Caching',
313
- 'plugin' => 'A2 Optimized',
314
- 'configured' => false,
315
- 'description' => 'Enable Disk Cache to make the site faster by caching pages as static content. Cache: a copy of rendered dynamic pages will be saved by the server so that the next user does not need to wait for the server to generate another copy.<br /><a href="admin.php?a2-page=cache_settings&page=A2_Optimized_Plugin_admin">Advanced Settings</a>',
316
- 'is_configured' => function (&$item) use (&$thisclass) {
317
- if (get_option('a2_cache_enabled') == 1 && file_exists( WP_CONTENT_DIR . '/advanced-cache.php')) {
318
- $item['configured'] = true;
319
-
320
- $thisclass->set_install_status('a2_page_cache', true);
321
- } else {
322
- $thisclass->set_install_status('a2_page_cache', false);
323
- }
324
- },
325
- 'disable' => function () use (&$thisclass) {
326
- $thisclass->disable_a2_page_cache();
327
- },
328
- 'enable' => function () use (&$thisclass) {
329
- $thisclass->enable_a2_page_cache();
330
- }
331
- ],
332
- 'a2_page_cache_gzip' => [
333
- 'slug' => 'a2_page_cache_gzip',
334
- 'name' => 'Gzip Compression Enabled',
335
- 'plugin' => 'A2 Optimized',
336
- 'configured' => false,
337
- 'description' => 'Makes your site significantly faster by compressing all text files to make them smaller.',
338
- 'is_configured' => function (&$item) use (&$thisclass) {
339
- if (A2_Optimized_Cache_Engine::$settings['compress_cache']) {
340
- $item['configured'] = true;
341
-
342
- $thisclass->set_install_status('a2_page_cache_gzip', true);
343
- } else {
344
- $thisclass->set_install_status('a2_page_cache_gzip', false);
345
- }
346
- },
347
- 'disable' => function () use (&$thisclass) {
348
- $thisclass->disable_a2_page_cache_gzip();
349
- },
350
- 'enable' => function () use (&$thisclass) {
351
- $thisclass->enable_a2_page_cache_gzip();
352
- },
353
- 'remove_link' => true
354
- ],
355
- 'a2_object_cache' => [
356
- 'slug' => 'a2_object_cache',
357
- 'name' => 'Memcache Object Caching',
358
- 'plugin' => 'A2 Optimized',
359
- 'configured' => false,
360
- 'description' => '
361
- <ul>
362
- <li>Extremely fast and powerful caching system.</li>
363
- <li>Store frequently used database queries and WordPress objects in an in-memory object cache.</li>
364
- <li>Object caching is a key-value store for small chunks of arbitrary data (strings, objects) from results of database calls, API calls, or page rendering.</li>
365
- <li>Take advantage of A2 Hosting&apos;s one-click memcached configuration for WordPress.</li>
366
- </ul>
367
- <strong>A supported object cache server and the corresponding PHP extension are required.</strong><br /><a href="admin.php?a2-page=cache_settings&page=A2_Optimized_Plugin_admin">Configure Object Cache Settings</a>
368
- ' . $a2_object_cache_additional_info,
369
- 'is_configured' => function (&$item) use (&$thisclass) {
370
- if (get_option('a2_object_cache_enabled') == 1 && file_exists( WP_CONTENT_DIR . '/object-cache.php')) {
371
- $item['configured'] = true;
372
-
373
- $thisclass->set_install_status('a2_object_cache', true);
374
- } else {
375
- $thisclass->set_install_status('a2_object_cache', false);
376
- }
377
- },
378
- 'disable' => function () use (&$thisclass) {
379
- $thisclass->disable_a2_object_cache();
380
- },
381
- 'enable' => function () use (&$thisclass) {
382
- $thisclass->enable_a2_object_cache();
383
- }
384
- ],
385
- 'a2_page_cache_minify_html' => [
386
- 'slug' => 'a2_page_cache_minify_html',
387
- 'name' => 'Minify HTML Pages',
388
- 'plugin' => 'A2 Optimized',
389
- 'configured' => false,
390
- 'description' => 'Removes extra spaces, tabs and line breaks in the HTML to reduce the size of the files sent to the user.',
391
- 'is_configured' => function (&$item) use (&$thisclass) {
392
- if (A2_Optimized_Cache_Engine::$settings['minify_html']) {
393
- $item['configured'] = true;
394
-
395
- $thisclass->set_install_status('a2_page_cache_minify_html', true);
396
- } else {
397
- $thisclass->set_install_status('a2_page_cache_minify_html', false);
398
- }
399
- },
400
- 'disable' => function () use (&$thisclass) {
401
- $thisclass->disable_a2_page_cache_minify_html();
402
- },
403
- 'enable' => function () use (&$thisclass) {
404
- $thisclass->enable_a2_page_cache_minify_html();
405
- },
406
- 'remove_link' => true
407
- ],
408
- 'a2_page_cache_minify_jscss' => [
409
- 'slug' => 'a2_page_cache_minify_jscss',
410
- 'name' => 'Minify Inline CSS and Javascript',
411
- 'plugin' => 'A2 Optimized',
412
- 'configured' => false,
413
- 'optional' => true,
414
- 'description' => 'Removes extra spaces, tabs and line breaks in inline CSS and Javascript to reduce the size of the files sent to the user. <strong>Note:</strong> This may cause issues with some page builders or other Javascript heavy front end plugins/themes.',
415
- 'is_configured' => function (&$item) use (&$thisclass) {
416
- if (A2_Optimized_Cache_Engine::$settings['minify_inline_css_js']) {
417
- $item['configured'] = true;
418
-
419
- $thisclass->set_install_status('a2_page_cache_minify_jscss', true);
420
- } else {
421
- $thisclass->set_install_status('a2_page_cache_minify_jscss', false);
422
- }
423
- },
424
- 'disable' => function () use (&$thisclass) {
425
- $thisclass->disable_a2_page_cache_minify_jscss();
426
- },
427
- 'enable' => function () use (&$thisclass) {
428
- $thisclass->enable_a2_page_cache_minify_jscss();
429
- },
430
- 'remove_link' => true
431
- ]
432
- ];
433
- }
434
-
435
- /* Common optimizations */
436
- $common_optimizations = [
437
- 'a2-db-optimizations' => [
438
- 'name' => 'Schedule Automatic Database Optimizations',
439
- 'slug' => 'a2-db-optimizations',
440
- 'plugin' => 'A2 Optimized',
441
- 'configured' => false,
442
- 'description' => 'If enabled, will periodically clean the MySQL database of expired transients, trashed comments, spam comments, and optimize all tables. You may also select to remove post revisions and trashed posts from the Database Optimization Settings.<br />
443
- <a href="admin.php?a2-page=cache_settings&page=A2_Optimized_Plugin_admin">Configure Database Optimization Settings</a>',
444
- 'is_configured' => function (&$item) use (&$thisclass) {
445
- $toggles = get_option('a2_db_optimizations');
446
- if (isset($toggles['cron_active']) && $toggles['cron_active']) {
447
- $item['configured'] = true;
448
- $thisclass->set_install_status('a2-db-optimizations', true);
449
- } else {
450
- $thisclass->set_install_status('a2-db-optimizations', false);
451
- }
452
- },
453
- 'enable' => function () use (&$thisclass) {
454
- A2_Optimized_DBOptimizations::set('cron_active', true);
455
- },
456
- 'disable' => function () use (&$thisclass) {
457
- A2_Optimized_DBOptimizations::set('cron_active', false);
458
- },
459
- ],
460
- 'woo-cart-fragments' => [
461
- 'name' => 'Dequeue WooCommerce Cart Fragments AJAX calls',
462
- 'slug' => 'woo-cart-fragments',
463
- 'plugin' => 'A2 Optimized',
464
- 'optional' => true,
465
- 'configured' => false,
466
- 'description' => 'Disable WooCommerce Cart Fragments on your homepage. Also enables "redirect to cart page" option in WooCommerce',
467
- 'is_configured' => function (&$item) use (&$thisclass) {
468
- if (get_option('a2_wc_cart_fragments')) {
469
- $item['configured'] = true;
470
- $thisclass->set_install_status('woo-cart-fragments', true);
471
- } else {
472
- $thisclass->set_install_status('woo-cart-fragments', false);
473
- }
474
- },
475
- 'enable' => function () use (&$thisclass) {
476
- $thisclass->enable_woo_cart_fragments();
477
- },
478
- 'disable' => function () use (&$thisclass) {
479
- $thisclass->disable_woo_cart_fragments();
480
- },
481
- ],
482
- 'xmlrpc-requests' => [
483
- 'name' => 'Block Unauthorized XML-RPC Requests',
484
- 'slug' => 'xmlrpc-requests',
485
- 'plugin' => 'A2 Optimized',
486
- 'optional' => true,
487
- 'configured' => false,
488
- 'description' => '
489
- <p>Completely Disable XML-RPC services</p>
490
- ',
491
- 'is_configured' => function (&$item) use (&$thisclass) {
492
- if (get_option('a2_block_xmlrpc')) {
493
- $item['configured'] = true;
494
- $thisclass->set_install_status('xmlrpc-requests', true);
495
- } else {
496
- $thisclass->set_install_status('xmlrpc-requests', false);
497
- }
498
- },
499
- 'enable' => function () use (&$thisclass) {
500
- $thisclass->enable_xmlrpc_requests();
501
- },
502
- 'disable' => function () use (&$thisclass) {
503
- $thisclass->disable_xmlrpc_requests();
504
- },
505
- ],
506
- 'regenerate-salts' => [
507
- 'name' => 'Regenerate wp-config salts',
508
- 'slug' => 'regenerate-salts',
509
- 'plugin' => 'A2 Optimized',
510
- 'optional' => true,
511
- 'configured' => false,
512
- 'is_configured' => function (&$item) use (&$thisclass) {
513
- if (get_option('a2_updated_regenerate-salts')) {
514
- $last_updated = strtotime(get_option('a2_updated_regenerate-salts'));
515
- if ($last_updated > strtotime('-3 Months')) {
516
- $item['configured'] = true;
517
- }
518
- }
519
- },
520
- 'description' => "<p>Generate new salt values for wp-config.php</p><p>WordPress salts and security keys help secure your site's login process and the cookies that WordPress uses to authenticate users. There are security benefits to periodically changing your salts to make it even harder for malicious actors to access them. You may need to clear your browser cookies after activating this option.</p><p><strong>This will log out all users including yourself</strong></p>",
521
- 'last_updated' => true,
522
- 'update' => true,
523
- 'enable' => function () use (&$thisclass) {
524
- $thisclass->regenerate_wpconfig_salts();
525
- },
526
- ],
527
- 'htaccess' => [
528
- 'name' => 'Deny Direct Access to Configuration Files and Comment Form',
529
- 'slug' => 'htaccess',
530
- 'plugin' => 'A2 Optimized',
531
- 'optional' => true,
532
- 'configured' => false,
533
- 'kb' => 'http://www.a2hosting.com/kb/installable-applications/optimization-and-configuration/wordpress2/optimizing-wordpress-with-the-a2-optimized-plugin',
534
- 'description' => 'Protects your configuration files by generating a Forbidden error to web users and bots when trying to access WordPress configuration files. <br> Also prevents POST requests to the site not originating from a user on the site. <br> <span class="danger" >note</span>: if you are using a plugin to allow remote posts and comments, disable this option.',
535
- 'is_configured' => function (&$item) use (&$thisclass) {
536
- $htaccess = file_get_contents(ABSPATH . '.htaccess');
537
- if (strpos($htaccess, '# BEGIN WordPress Hardening') === false) {
538
- if ($thisclass->get_deny_direct() == true) {
539
- $thisclass->set_deny_direct(false);
540
- }
541
- //make sure the basic a2-optimized rules are present
542
- $thisclass->set_install_status('htaccess-deny-direct-access', false);
543
- } else {
544
- if ($thisclass->get_deny_direct() == true) {
545
- $item['configured'] = true;
546
- }
547
- }
548
- },
549
- 'enable' => function () use (&$thisclass) {
550
- $thisclass->set_deny_direct(true);
551
- $thisclass->write_htaccess();
552
- },
553
- 'disable' => function () use (&$thisclass) {
554
- $thisclass->set_deny_direct(false);
555
- $thisclass->write_htaccess();
556
- }
557
- ],
558
- 'lock' => [
559
- 'name' => 'Lock Editing of Plugins and Themes from the WP Admin',
560
- 'slug' => 'lock',
561
- 'plugin' => 'A2 Optimized',
562
- 'configured' => false,
563
- 'kb' => 'http://www.a2hosting.com/kb/installable-applications/optimization-and-configuration/wordpress2/optimizing-wordpress-with-the-a2-optimized-plugin',
564
- 'description' => 'Prevents exploits that use the built in editing capabilities of the WP Admin',
565
- 'is_configured' => function (&$item) use (&$thisclass) {
566
- $wpconfig = file_get_contents(ABSPATH . 'wp-config.php');
567
- if (strpos($wpconfig, '// BEGIN A2 CONFIG') === false) {
568
- if ($thisclass->get_lockdown() == true) {
569
- $thisclass->get_lockdown(false);
570
- }
571
- $thisclass->set_install_status('lock-editing', false);
572
- } else {
573
- if ($thisclass->get_lockdown() == true) {
574
- $item['configured'] = true;
575
- }
576
- }
577
- },
578
- 'enable' => function () use (&$thisclass) {
579
- $thisclass->set_lockdown(true);
580
- $thisclass->write_wp_config();
581
- },
582
- 'disable' => function () use (&$thisclass) {
583
- $thisclass->set_lockdown(false);
584
- $thisclass->write_wp_config();
585
- }
586
- ],
587
- 'wp-login' => [
588
- 'name' => 'Login URL Change',
589
- 'slug' => 'wp-login',
590
- 'premium' => true,
591
- 'plugin' => 'Rename wp-login.php',
592
- 'configured' => false,
593
- 'kb' => 'http://www.a2hosting.com/kb/security/application-security/wordpress-security#a-namemethodRenameLoginPageaMethod-3.3A-Change-the-WordPress-login-URL',
594
- 'description' => '
595
- <p>Change the URL of your login page to make it harder for bots to find it to brute force attack.</p>
596
- ',
597
- 'is_configured' => function () {
598
- return false;
599
- }
600
- ],
601
- 'captcha' => [
602
- 'name' => 'reCAPTCHA on comments and login',
603
- 'plugin' => 'reCAPTCHA',
604
- 'slug' => 'captcha',
605
- 'premium' => true,
606
- 'configured' => false,
607
- 'description' => 'Decreases spam and increases site security by adding a CAPTCHA to comment forms and the login screen. Without a CAPTCHA, bots will easily be able to post comments to you blog or brute force login to your admin panel. You may override the default settings and use your own Site Key and select a theme.',
608
- 'is_configured' => function () {
609
- return false;
610
- }
611
- ],
612
- 'images' => [
613
- 'name' => 'Compress Images on Upload',
614
- 'plugin' => 'Image Optimizer',
615
- 'slug' => 'images',
616
- 'premium' => true,
617
- 'configured' => false,
618
- 'description' => 'Makes your site faster by compressing images to make them smaller.',
619
- 'is_configured' => function () {
620
- return false;
621
- }
622
- ],
623
- 'turbo' => [
624
- 'name' => 'Turbo Web Hosting',
625
- 'slug' => 'turbo',
626
- 'configured' => false,
627
- 'premium' => true,
628
- 'description' => '
629
- <ul>
630
- <li>Turbo Web Hosting servers compile .htaccess files to make speed improvements. Any changes to .htaccess files are immediately re-compiled.</li>
631
- <li>Turbo Web Hosting servers have their own PHP API that provides speed improvements over FastCGI and PHP-FPM (FastCGI Process Manager). </li>
632
- <li>To serve static files, Turbo Web Hosting servers do not need to create a worker process as the user. Servers only create a worker process for PHP scripts, which results in faster performance.</li>
633
- <li>PHP OpCode Caching is enabled by default. Accounts are allocated 256 MB of memory toward OpCode caching.</li>
634
- <li>Turbo Web Hosting servers have a built-in caching engine for Full Page Cache and Edge Side Includes.</li>
635
- </ul>
636
- ',
637
- 'is_configured' => function () {
638
- return false;
639
- }
640
- ]
641
- ];
642
-
643
- $optimizations = array_merge($optimizations, $common_optimizations);
644
-
645
- $optimizations = $this->apply_optimization_filter($optimizations);
646
-
647
- return $optimizations;
648
- }
649
-
650
- /*
651
- * Changes to optimizations based on various factors
652
- */
653
- public function apply_optimization_filter($optimizations) {
654
- if (get_template() == 'Divi') {
655
- $optimizations['minify']['optional'] = true;
656
- $optimizations['css_minify']['optional'] = true;
657
- $optimizations['js_minify']['optional'] = true;
658
- }
659
-
660
- if (is_plugin_active('litespeed-cache/litespeed-cache.php')) {
661
- $optimizations['a2_object_cache']['name'] = 'Object Caching with Memcached or Redis';
662
- if (get_option('litespeed.conf.object') == 1) {
663
- $optimizations['a2_object_cache']['configured'] = true;
664
- $optimizations['a2_object_cache']['description'] .= '<br /><strong>This feature is provided by the LiteSpeed Cache plugin.</strong></p>';
665
- unset($optimizations['a2_object_cache']['disable']);
666
- }
667
- if (class_exists('A2_Optimized_Private_Optimizations')) {
668
- $a2opt_priv = new A2_Optimized_Private_Optimizations();
669
-
670
- if (method_exists($a2opt_priv, 'get_redis_socket')) {
671
- $file_path = $a2opt_priv->get_redis_socket();
672
- }
673
- }
674
- }
675
- if (get_option('a2_optimized_memcached_invalid')) {
676
- unset($optimizations['a2_object_cache']['enable']);
677
- }
678
-
679
- return $optimizations;
680
- }
681
-
682
- protected function get_private_optimizations() {
683
- if (class_exists('A2_Optimized_Private_Optimizations')) {
684
- $a2opt_priv = new A2_Optimized_Private_Optimizations();
685
-
686
- return $a2opt_priv->get_optimizations($this->thisclass);
687
- } else {
688
- return [];
689
- }
690
- }
691
-
692
- public function get_advanced() {
693
- $public_opts = $this->get_public_advanced();
694
- $private_opts = $this->get_private_advanced();
695
-
696
- return array_merge($public_opts, $private_opts);
697
- }
698
-
699
- protected function get_public_advanced() {
700
- $thisclass = $this->thisclass;
701
-
702
- return [
703
- 'gtmetrix' => [
704
- 'slug' => 'gtmetrix',
705
- 'name' => 'GTmetrix',
706
- 'plugin' => 'GTmetrix',
707
- 'plugin_slug' => 'gtmetrix-for-wordpress',
708
- 'file' => 'gtmetrix-for-wordpress/gtmetrix-for-wordpress.php',
709
- 'configured' => false,
710
- 'partially_configured' => false,
711
- 'required_options' => ['gfw_options' => ['authorized']],
712
- 'description' => '
713
- <p>
714
- Plugin that actively keeps track of your WP install and sends you alerts if your site falls below certain criteria.
715
- The GTMetrix plugin requires an account with <a href="http://gtmetrix.com/" >gtmetrix.com</a>
716
- </p>
717
- <p>
718
- <b>Use this plugin only if your site is experiencing issues with slow load times.</b><br><b style="color:red">The GTMetrix plugin will slow down your site.</b>
719
- </p>
720
- ',
721
- 'not_configured_links' => [],
722
- 'configured_links' => [
723
- 'Configure GTmetrix' => 'admin.php?page=gfw_settings',
724
- 'GTmetrix Tests' => 'admin.php?page=gfw_tests',
725
- ],
726
- 'partially_configured_links' => [
727
- 'Configure GTmetrix' => 'admin.php?page=gfw_settings',
728
- 'GTmetrix Tests' => 'admin.php?page=gfw_tests',
729
- ],
730
- 'partially_configured_message' => 'Click &quot;Configure GTmetrix&quot; to enter your GTmetrix Account Email and GTmetrix API Key.',
731
- 'kb' => 'http://www.a2hosting.com/kb/installable-applications/optimization-and-configuration/wordpress2/optimizing-wordpress-with-w3-total-cache-and-gtmetrix',
732
- 'is_configured' => function (&$item) use (&$thisclass) {
733
- $gfw_options = get_option('gfw_options');
734
- if (is_plugin_active($item['file']) && isset($gfw_options['authorized']) && $gfw_options['authorized'] == 1) {
735
- $item['configured'] = true;
736
- $thisclass->set_install_status('gtmetrix', true);
737
- } elseif (is_plugin_active($item['file'])) {
738
- $item['partially_configured'] = true;
739
- } else {
740
- $thisclass->set_install_status('gtmetrix', false);
741
- }
742
- },
743
- 'enable' => function ($slug) use (&$thisclass) {
744
- $item = $thisclass->get_advanced_optimizations();
745
- $item = $item[$slug];
746
- if (!isset($thisclass->plugin_list[$item['file']])) {
747
- $thisclass->install_plugin($item['plugin_slug']);
748
- }
749
- if (!is_plugin_active($item['file'])) {
750
- $thisclass->activate_plugin($item['file']);
751
- }
752
- },
753
- 'disable' => function ($slug) use (&$thisclass) {
754
- $item = $thisclass->get_advanced_optimizations();
755
- $item = $item[$slug];
756
- $thisclass->deactivate_plugin($item['file']);
757
- }
758
- ],
759
- 'cloudflare' => [
760
- 'slug' => 'cloudflare',
761
- 'name' => 'CloudFlare',
762
- 'premium' => true,
763
- 'description' => '
764
- <p>
765
- CloudFlare is a free global CDN and DNS provider that can speed up and protect any site online.
766
- </p>
767
-
768
- <dl style="padding-left:20px">
769
- <dt>CloudFlare CDN</dt>
770
- <dd>Distribute your content around the world so it&apos;s closer to your visitors (speeding up your site).</dd>
771
- <dt>CloudFlare optimizer</dt>
772
- <dd>Web pages with ad servers and third party widgets load snappy on both mobile and computers.</dd>
773
- <dt>CloudFlare security</dt>
774
- <dd>Protect your website from a range of online threats from spammers to SQL injection to DDOS.</dd>
775
- <dt>CloudFlare analytics</dt>
776
- <dd>Get insight into all of your website&apos;s traffic including threats and search engine crawlers.</dd>
777
- </dl>
778
- <div class="alert alert-info">
779
- Host with A2 Hosting to take advantage of one click CloudFlare configuration.
780
- </div>
781
- ',
782
- 'configured' => $this->server_info->cf,
783
- 'is_configured' => function () {
784
- return false;
785
- },
786
- 'not_configured_links' => ['Host with A2' => 'https://www.a2hosting.com/wordpress-hosting?utm_source=A2%20Optimized&utm_medium=Referral&utm_campaign=A2%20Optimized']
787
- ]
788
- ];
789
- }
790
-
791
- protected function get_private_advanced() {
792
- if (class_exists('A2_Optimized_Private_Optimizations')) {
793
- $a2opt_priv = new A2_Optimized_Private_Optimizations();
794
-
795
- return $a2opt_priv->get_advanced($this->thisclass);
796
- } else {
797
- return [];
798
- }
799
- }
800
-
801
- public function get_warnings() {
802
- $public_opts = $this->get_public_warnings();
803
- $private_opts = $this->get_private_warnings();
804
-
805
- return array_merge($public_opts, $private_opts);
806
- }
807
-
808
- protected function get_public_warnings() {
809
- return [
810
- 'Bad WP Options' => [
811
- 'posts_per_page' => [
812
- 'title' => 'Recent Post Limit',
813
- 'description' => 'The number of recent posts per page is set greater than five. This could be slowing down page loads.',
814
- 'type' => 'numeric',
815
- 'threshold_type' => '>',
816
- 'threshold' => 5,
817
- 'config_url' => admin_url() . 'options-reading.php'
818
- ],
819
- 'posts_per_rss' => [
820
- 'title' => 'RSS Post Limit',
821
- 'description' => 'The number of posts from external feeds is set greater than 5. This could be slowing down page loads.',
822
- 'type' => 'numeric',
823
- 'threshold_type' => '>',
824
- 'threshold' => 5,
825
- 'config_url' => admin_url() . 'options-reading.php'
826
- ],
827
- 'show_on_front' => [
828
- 'title' => 'Recent Posts showing on home page',
829
- 'description' => 'Speed up your home page by selecting a static page to display.',
830
- 'type' => 'text',
831
- 'threshold_type' => '=',
832
- 'threshold' => 'posts',
833
- 'config_url' => admin_url() . 'options-reading.php'
834
- ],
835
- 'permalink_structure' => [
836
- 'title' => 'Permalink Structure',
837
- 'description' => 'To fully optimize page caching with "Disk Enhanced" mode:<br>you must set a permalink structure other than "Default".',
838
- 'type' => 'text',
839
- 'threshold_type' => '=',
840
- 'threshold' => '',
841
- 'config_url' => admin_url() . 'options-permalink.php'
842
- ]
843
- ],
844
- 'Advanced Warnings' => [
845
- 'themes' => [
846
- 'is_warning' => function () {
847
- $theme_count = 0;
848
- $themes = wp_get_themes();
849
- foreach ($themes as $theme_name => $theme) {
850
- if (substr($theme_name, 0, 6) != 'twenty') {
851
- // We don't want default themes to count towards our warning total
852
- $theme_count++;
853
- }
854
- }
855
- switch ($theme_count) {
856
- case 1:
857
- return false;
858
- case 2:
859
- $theme = wp_get_theme();
860
- if ($theme->get('Template') != '') {
861
- return false;
862
- }
863
- }
864
-
865
- return true;
866
- },
867
- 'title' => 'Unused Themes',
868
- 'description' => 'One or more unused non-default themes are installed. Unused non-default themes should be deleted. For more information read the Wordpress.org Codex on <a target="_blank" href="http://codex.wordpress.org/WordPress_Housekeeping#Theme_Housekeeping">WordPress Housekeeping</a>',
869
- 'config_url' => admin_url() . 'themes.php'
870
- ],
871
- 'a2_hosting' => [
872
- 'title' => 'Not Hosted with A2 Hosting',
873
- 'description' => 'Get faster page load times and more optimizations when you <a href="https://www.a2hosting.com/wordpress-hosting?utm_source=A2%20Optimized&utm_medium=Referral&utm_campaign=A2%20Optimized" target="_blank">host with A2 Hosting</a>.',
874
- 'is_warning' => function () {
875
- if (is_dir('/opt/a2-optimized')) {
876
- return false;
877
- }
878
-
879
- return true;
880
- },
881
- 'config_url' => 'https://www.a2hosting.com/wordpress-hosting?utm_source=A2%20Optimized&utm_medium=Referral&utm_campaign=A2%20Optimized'
882
- ]
883
- ],
884
- 'Bad Plugins' => [
885
- 'wp-super-cache',
886
- 'wp-file-cache',
887
- 'wp-db-backup',
888
- ]
889
- ];
890
- }
891
-
892
- protected function get_private_warnings() {
893
- if (class_exists('A2_Optimized_Private_Optimizations')) {
894
- $a2opt_priv = new A2_Optimized_Private_Optimizations();
895
-
896
- return $a2opt_priv->get_warnings($this->thisclass);
897
- } else {
898
- return [];
899
- }
900
- }
901
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
A2_Optimized_OptionsManager.php DELETED
@@ -1,3270 +0,0 @@
1
- <?php
2
-
3
- /*
4
- Author: Benjamin Cool, Andrew Jones
5
- Author URI: https://www.a2hosting.com/
6
- License: GPLv2 or Later
7
- */
8
-
9
- // Prevent direct access to this file
10
- if (! defined('WPINC')) {
11
- die;
12
- }
13
-
14
- if (is_admin()) {
15
- require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
16
- class A2_Plugin_Installer_Skin extends Plugin_Installer_Skin {
17
- public function error($error) {
18
- }
19
- }
20
- }
21
-
22
- if (file_exists('/opt/a2-optimized/wordpress/Optimizations.php')) {
23
- require_once '/opt/a2-optimized/wordpress/Optimizations.php';
24
- }
25
- require_once 'A2_Optimized_Optimizations.php';
26
- require_once 'A2_Optimized_SiteHealth.php';
27
-
28
- class A2_Optimized_OptionsManager {
29
- public $plugin_dir;
30
- private $optimizations;
31
- private $advanced_optimizations;
32
- private $advanced_optimization_status;
33
- private $optimization_count;
34
- private $advanced_optimization_count;
35
- private $plugin_list;
36
- private $install_status;
37
- private $salts_array;
38
- private $new_salts;
39
-
40
- public function __construct() {
41
- }
42
-
43
- /**
44
- * Get the current version of w3tc
45
- *
46
- */
47
- private function get_current_w3tc_version() {
48
- $version = get_transient('a2_w3tc_current_version');
49
- if (!$version) {
50
- $response = wp_remote_get('https://wp-plugins.a2hosting.com/wp-json/wp/v2/update_notice?notice_plugin=3&per_page=1');
51
- if (is_array($response)) {
52
- $body = json_decode($response['body']); // use the content
53
- foreach ($body as $item) {
54
- $version = $item->title->rendered;
55
- set_transient('a2_w3tc_current_version', $version, 3600 * 12);
56
- }
57
- } else {
58
- $version = null;
59
- set_transient('a2_w3tc_current_version', $version, 3600);
60
- }
61
- }
62
-
63
- return $version;
64
- }
65
-
66
- /**
67
- * Get the array of w3tc plugin default settings
68
- *
69
- * @return array
70
- */
71
- public function get_w3tc_defaults() {
72
- return [
73
- 'pgcache.check.domain' => true,
74
- 'pgcache.prime.post.enabled' => true,
75
- 'pgcache.reject.logged' => true,
76
- 'pgcache.reject.request_head' => true,
77
- 'pgcache.purge.front_page' => true,
78
- 'pgcache.purge.home' => true,
79
- 'pgcache.purge.post' => true,
80
- 'pgcache.purge.comments' => true,
81
- 'pgcache.purge.author' => true,
82
- 'pgcache.purge.terms' => true,
83
- 'pgcache.purge.archive.daily' => true,
84
- 'pgcache.purge.archive.monthly' => true,
85
- 'pgcache.purge.archive.yearly' => true,
86
- 'pgcache.purge.feed.blog' => true,
87
- 'pgcache.purge.feed.comments' => true,
88
- 'pgcache.purge.feed.author' => true,
89
- 'pgcache.purge.feed.terms' => true,
90
- 'pgcache.cache.feed' => true,
91
- 'pgcache.debug' => false,
92
- 'pgcache.purge.postpages_limit' => 0,//purge all pages that list posts
93
- 'pgcache.purge.feed.types' => [
94
- 0 => 'rdf',
95
- 1 => 'rss',
96
- 2 => 'rss2',
97
- 3 => 'atom'
98
- ],
99
- 'pgcache.compatibility' => true,
100
- 'minify.debug' => false,
101
- 'dbcache.debug' => false,
102
- 'objectcache.debug' => false,
103
-
104
- 'mobile.enabled' => true,
105
-
106
- 'minify.auto' => false,
107
- 'minify.html.engine' => 'html',
108
- 'minify.html.inline.css' => true,
109
- 'minify.html.inline.js' => true,
110
-
111
- 'minify.js.engine' => 'js',
112
- 'minify.css.engine' => 'css',
113
-
114
- 'minify.js.header.embed_type' => 'nb-js',
115
- 'minify.js.body.embed_type' => 'nb-js',
116
- 'minify.js.footer.embed_type' => 'nb-js',
117
-
118
- 'minify.lifetime' => 14400,
119
- 'minify.file.gc' => 144000,
120
-
121
- 'dbcache.lifetime' => 3600,
122
- 'dbcache.file.gc' => 7200,
123
-
124
- 'objectcache.lifetime' => 3600,
125
- 'objectcache.file.gc' => 7200,
126
-
127
- 'browsercache.cssjs.last_modified' => true,
128
- 'browsercache.cssjs.expires' => true,
129
- 'browsercache.cssjs.lifetime' => 31536000,
130
- 'browsercache.cssjs.nocookies' => false,
131
- 'browsercache.cssjs.cache.control' => true,
132
- 'browsercache.cssjs.cache.policy' => 'cache_maxage',
133
- 'browsercache.cssjs.etag' => true,
134
- 'browsercache.cssjs.w3tc' => true,
135
- 'browsercache.cssjs.replace' => true,
136
- 'browsercache.html.last_modified' => true,
137
- 'browsercache.html.expires' => true,
138
- 'browsercache.html.lifetime' => 30,
139
- 'browsercache.html.cache.control' => true,
140
- 'browsercache.html.cache.policy' => 'cache_maxage',
141
- 'browsercache.html.etag' => true,
142
- 'browsercache.html.w3tc' => true,
143
- 'browsercache.html.replace' => true,
144
- 'browsercache.other.last_modified' => true,
145
- 'browsercache.other.expires' => true,
146
- 'browsercache.other.lifetime' => 31536000,
147
- 'browsercache.other.nocookies' => false,
148
- 'browsercache.other.cache.control' => true,
149
- 'browsercache.other.cache.policy' => 'cache_maxage',
150
- 'browsercache.other.etag' => true,
151
- 'browsercache.other.w3tc' => true,
152
- 'browsercache.other.replace' => true,
153
-
154
- 'config.check' => true,
155
-
156
- 'varnish.enabled' => false
157
- ];
158
- }
159
-
160
- /**
161
- * Enable w3tc cache plugin
162
- *
163
- */
164
- public function enable_w3_total_cache() {
165
- $file = 'a2-w3-total-cache/a2-w3-total-cache.php';
166
- $slug = 'a2-w3-total-cache';
167
- $this->install_plugin($slug);
168
- $this->activate_plugin($file);
169
- $this->hit_the_w3tc_page();
170
- }
171
-
172
- /**
173
- * Get all plugins for this theme
174
- *
175
- */
176
- public function get_plugins() {
177
- if (isset($this->plugin_list)) {
178
- return $this->plugin_list;
179
- } else {
180
- return get_plugins();
181
- }
182
- }
183
-
184
- /**
185
- * Enable browser cache for w3tc
186
- *
187
- * @param string $slug The plugin path
188
- * @para boolean $activate - Activate plugin after installl
189
- *
190
- */
191
- public function install_plugin($slug, $activate = false) {
192
- require_once ABSPATH . 'wp-admin/includes/plugin.php';
193
- require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
194
- $api = plugins_api('plugin_information', ['slug' => $slug]);
195
- $response = true;
196
-
197
- $found = false;
198
-
199
- if ($slug == 'a2-w3-total-cache') {
200
- $file = 'a2-w3-total-cache/a2-w3-total-cache.php';
201
- }
202
-
203
- $plugins = $this->get_plugins();
204
-
205
- foreach ($plugins as $file => $plugin) {
206
- if ($plugin['Name'] == $api->name) {
207
- $found = true;
208
- }
209
- }
210
-
211
- if (!$found) {
212
- ob_start();
213
- $upgrader = new Plugin_Upgrader(new A2_Plugin_Installer_Skin(compact('title', 'url', 'nonce', 'plugin', 'api')));
214
-
215
- if ($slug == 'a2-w3-total-cache') {
216
- $api->download_link = 'https://wp-plugins.a2hosting.com/wp-content/uploads/rkv-repo/a2-w3-total-cache.zip';
217
- }
218
-
219
- if ($slug == 'a2-warp-imagick') {
220
- $api->download_link = 'https://wp-plugins.a2hosting.com/wp-content/uploads/rkv-repo/warp-imagick.zip';
221
- }
222
-
223
- $response = $upgrader->install($api->download_link);
224
- ob_end_clean();
225
- $this->plugin_list = get_plugins();
226
- }
227
-
228
- if ($activate) {
229
- $plugins = $this->get_plugins();
230
- foreach ($plugins as $file => $plugin) {
231
- if ($plugin['Name'] == $api->name) {
232
- $this->activate_plugin($file);
233
- }
234
- }
235
- }
236
-
237
- $this->clear_w3_total_cache();
238
-
239
- return $response;
240
- }
241
-
242
- public function activate_plugin($file) {
243
- require_once ABSPATH . 'wp-admin/includes/plugin.php';
244
- activate_plugin($file);
245
- $this->clear_w3_total_cache();
246
- }
247
-
248
- public function clear_w3_total_cache() {
249
- if (is_plugin_active('a2-w3-total-cache/a2-w3-total-cache.php')) {
250
- //TODO: add clear cache
251
- }
252
- }
253
-
254
- /**
255
- * Curl call the w3tc page
256
- *
257
- */
258
- public function hit_the_w3tc_page() {
259
- $disregarded_cookies = [
260
- 'PHPSESSID',
261
- ];
262
-
263
- $cookie = '';
264
- foreach ($_COOKIE as $name => $val) {
265
- if (!in_array($name, $disregarded_cookies)) {
266
- $cookie .= "{$name}={$val};";
267
- }
268
- }
269
- rtrim($cookie, ';');
270
- $ch = curl_init();
271
- curl_setopt($ch, CURLOPT_URL, get_admin_url() . 'admin.php?page=w3tc_general&nonce=' . wp_create_nonce('w3tc'));
272
- curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6');
273
- curl_setopt($ch, CURLOPT_TIMEOUT, 60);
274
- curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
275
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
276
- curl_setopt($ch, CURLOPT_COOKIE, $cookie);
277
- curl_setopt($ch, CURLOPT_REFERER, get_admin_url());
278
- $result = curl_exec($ch);
279
- curl_close($ch);
280
- }
281
-
282
- public function refresh_w3tc() {
283
- $this->hit_the_w3tc_page();
284
- }
285
-
286
- /**
287
- * Get configs for w3tc
288
- *
289
- *@return array|false
290
- */
291
- public function get_w3tc_config() {
292
- if (class_exists('W3_ConfigData')) {
293
- $config_writer = new W3_ConfigWriter(0, false);
294
-
295
- return W3_ConfigData::get_array_from_file($config_writer->get_config_filename());
296
- } else {
297
- return false;
298
- }
299
- }
300
-
301
- /**
302
- * Enable plguin cache for w3tc
303
- *
304
- */
305
- public function enable_w3tc_cache() {
306
- $permalink_structure = get_option('permalink_structure');
307
- $vars = [];
308
- if ($permalink_structure == '') {
309
- $vars['pgcache.engine'] = 'file';
310
- } else {
311
- $vars['pgcache.engine'] = 'file_generic';
312
- }
313
- $vars['dbcache.engine'] = 'file';
314
- $vars['objectcache.engine'] = 'file';
315
-
316
- $vars['objectcache.enabled'] = true;
317
- $vars['dbcache.enabled'] = true;
318
- $vars['pgcache.enabled'] = true;
319
- $vars['pgcache.compatibility'] = true;
320
- $vars['pgcache.cache.ssl'] = true;
321
- $vars['browsercache.enabled'] = true;
322
-
323
- $this->update_w3tc($vars);
324
- }
325
-
326
- /**
327
- * Enable page cache for w3tc
328
- *
329
- */
330
- public function enable_w3tc_page_cache() {
331
- $permalink_structure = get_option('permalink_structure');
332
- $vars = [];
333
- if ($permalink_structure == '') {
334
- $vars['pgcache.engine'] = 'file';
335
- } else {
336
- $vars['pgcache.engine'] = 'file_generic';
337
- }
338
-
339
- $vars['pgcache.enabled'] = true;
340
- $vars['pgcache.cache.ssl'] = true;
341
- $vars['pgcache.compatibility'] = true;
342
-
343
- $this->update_w3tc($vars);
344
- }
345
-
346
- /**
347
- * Enable database cache for w3tc
348
- *
349
- */
350
- public function enable_w3tc_db_cache() {
351
- $vars = [];
352
-
353
- $vars['dbcache.engine'] = 'file';
354
- $vars['dbcache.enabled'] = true;
355
-
356
- $this->update_w3tc($vars);
357
- }
358
-
359
- /**
360
- * Enable plugin object cache for w3tc
361
- *
362
- */
363
- public function enable_w3tc_object_cache() {
364
- $vars = [];
365
-
366
- $vars['objectcache.engine'] = 'file';
367
- $vars['objectcache.enabled'] = true;
368
-
369
- $this->update_w3tc($vars);
370
- }
371
-
372
- /**
373
- * Enable browser cache for w3tc
374
- *
375
- */
376
- public function enable_w3tc_browser_cache() {
377
- $vars = [];
378
-
379
- $vars['browsercache.enabled'] = true;
380
-
381
- $this->update_w3tc($vars);
382
- }
383
-
384
- /**
385
- * Enable gzip for w3tc
386
- *
387
- */
388
- public function enable_w3tc_gzip() {
389
- $vars = [];
390
-
391
- $vars['browsercache.other.compression'] = true;
392
- $vars['browsercache.html.compression'] = true;
393
- $vars['browsercache.cssjs.compression'] = true;
394
-
395
- $this->update_w3tc($vars);
396
- }
397
-
398
- /**
399
- * Disable gzip for w3tc
400
- *
401
- */
402
- public function disable_w3tc_gzip() {
403
- $vars = [];
404
-
405
- $vars['browsercache.other.compression'] = false;
406
- $vars['browsercache.html.compression'] = false;
407
- $vars['browsercache.cssjs.compression'] = false;
408
-
409
- $this->update_w3tc($vars);
410
- }
411
-
412
- /**
413
- * Enable built-in page cache
414
- *
415
- */
416
- public function enable_a2_page_cache() {
417
- A2_Optimized_Cache_Disk::setup();
418
- A2_Optimized_Cache::update_backend();
419
-
420
- update_option('a2_cache_enabled', 1);
421
- }
422
-
423
- /**
424
- * Disable built-in page cache
425
- *
426
- */
427
- public function disable_a2_page_cache() {
428
- A2_Optimized_Cache_Disk::clean();
429
- A2_Optimized_Cache::update_backend();
430
-
431
- update_option('a2_cache_enabled', 0);
432
- }
433
-
434
- /**
435
- * Enable memcached object cache
436
- *
437
- */
438
- public function enable_a2_object_cache() {
439
- if (get_option('a2_optimized_memcached_invalid')) {
440
- // Object cache server did not validate. exit.
441
- return false;
442
- }
443
- if (is_plugin_active('litespeed-cache/litespeed-cache.php')) {
444
- // Litespeed cache plugin is active, use that
445
- return $this->enable_lscache_object_cache();
446
- } else {
447
- // Try to enable A2 memcached object caching
448
- if (get_option('a2_optimized_memcached_server') == false) {
449
- // Second check for object cache server
450
- return false;
451
- }
452
- copy( A2OPT_DIR . '/object-cache.php', WP_CONTENT_DIR . '/object-cache.php' );
453
-
454
- update_option('a2_object_cache_enabled', 1);
455
- $this->write_wp_config();
456
- }
457
- }
458
-
459
- /**
460
- * Enable litespeed object cache
461
- *
462
- */
463
- public function enable_lscache_object_cache() {
464
- $object_cache_type = 'memcached';
465
-
466
- if (get_option('a2_optimized_objectcache_type')) {
467
- $object_cache_type = get_option('a2_optimized_objectcache_type');
468
- }
469
-
470
- /* Set type of object cache */
471
- if ($object_cache_type == 'memcached') {
472
- $server_host = get_option('a2_optimized_memcached_server');
473
- update_option('litespeed.conf.object-kind', 0);
474
- }
475
- if ($object_cache_type == 'redis') {
476
- $server_host = get_option('a2_optimized_redis_server');
477
- update_option('litespeed.conf.object-kind', 1);
478
- }
479
-
480
- update_option('litespeed.conf.object', 1); // Enable object cache
481
- update_option('litespeed.conf.object-host', $server_host); // Server host
482
- update_option('litespeed.conf.object-port', '0'); // Port is 0 for socket connections
483
-
484
- update_option('a2_object_cache_enabled', 1); // Flag that we have this enabled
485
- }
486
-
487
- /* Is redis supported */
488
- private function is_redis_supported() {
489
- if (class_exists('A2_Optimized_Private_Optimizations') && is_plugin_active('litespeed-cache/litespeed-cache.php')) {
490
- $a2opt_priv = new A2_Optimized_Private_Optimizations();
491
-
492
- return $a2opt_priv->is_redis_supported();
493
- }
494
- update_option('a2_optimized_objectcache_type', 'memcached');
495
-
496
- return false;
497
- }
498
-
499
- /**
500
- * Disable memcached object cache
501
- *
502
- */
503
- public function disable_a2_object_cache() {
504
- @unlink( WP_CONTENT_DIR . '/object-cache.php' );
505
-
506
- $this->write_wp_config();
507
-
508
- update_option('a2_object_cache_enabled', 0);
509
- }
510
-
511
- /**
512
- * Enable built-in page cache gzip
513
- *
514
- */
515
- public function enable_a2_page_cache_gzip() {
516
- $cache_settings = A2_Optimized_Cache::get_settings();
517
-
518
- $cache_settings['compress_cache'] = 1;
519
-
520
- update_option('a2opt-cache', $cache_settings);
521
- update_option('a2_cache_enabled', 1);
522
-
523
- // Rebuild cache settings file
524
- A2_Optimized_Cache_Disk::create_settings_file( $cache_settings );
525
- }
526
-
527
- /**
528
- * Disable built-in page cache gzip
529
- *
530
- */
531
- public function disable_a2_page_cache_gzip() {
532
- $cache_settings = A2_Optimized_Cache::get_settings();
533
-
534
- $cache_settings['compress_cache'] = 0;
535
-
536
- update_option('a2opt-cache', $cache_settings);
537
-
538
- // Rebuild cache settings file
539
- A2_Optimized_Cache_Disk::create_settings_file( $cache_settings );
540
- }
541
-
542
- /**
543
- * Enable built-in page cache html minification
544
- *
545
- */
546
- public function enable_a2_page_cache_minify_html() {
547
- $cache_settings = A2_Optimized_Cache::get_settings();
548
-
549
- $cache_settings['minify_html'] = 1;
550
-
551
- update_option('a2opt-cache', $cache_settings);
552
- update_option('a2_cache_enabled', 1);
553
-
554
- // Rebuild cache settings file
555
- A2_Optimized_Cache_Disk::create_settings_file( $cache_settings );
556
- }
557
-
558
- /**
559
- * Disable built-in page cache html minification
560
- *
561
- */
562
- public function disable_a2_page_cache_minify_html() {
563
- $cache_settings = A2_Optimized_Cache::get_settings();
564
-
565
- $cache_settings['minify_html'] = 0;
566
- $cache_settings['minify_inline_css_js'] = 0; // Need to disable css/js as well
567
-
568
- update_option('a2opt-cache', $cache_settings);
569
-
570
- // Rebuild cache settings file
571
- A2_Optimized_Cache_Disk::create_settings_file( $cache_settings );
572
- }
573
-
574
- /**
575
- * Enable built-in page cache css/js minification
576
- *
577
- */
578
- public function enable_a2_page_cache_minify_jscss() {
579
- $cache_settings = A2_Optimized_Cache::get_settings();
580
-
581
- $cache_settings['minify_html'] = 1; // need html to be enabled as well
582
- $cache_settings['minify_inline_css_js'] = 1;
583
-
584
- update_option('a2opt-cache', $cache_settings);
585
- update_option('a2_cache_enabled', 1);
586
-
587
- // Rebuild cache settings file
588
- A2_Optimized_Cache_Disk::create_settings_file( $cache_settings );
589
- }
590
-
591
- /**
592
- * Disable built-in page cache css/js minification
593
- *
594
- */
595
- public function disable_a2_page_cache_minify_jscss() {
596
- $cache_settings = A2_Optimized_Cache::get_settings();
597
-
598
- $cache_settings['minify_inline_css_js'] = 0;
599
-
600
- update_option('a2opt-cache', $cache_settings);
601
-
602
- // Rebuild cache settings file
603
- A2_Optimized_Cache_Disk::create_settings_file( $cache_settings );
604
- }
605
-
606
- /**
607
- * Enable WooCommerce Cart Fragment Dequeuing
608
- *
609
- */
610
- public function enable_woo_cart_fragments() {
611
- update_option('a2_wc_cart_fragments', 1);
612
- update_option('woocommerce_cart_redirect_after_add', 'yes'); // Recommended WooCommerce setting when disabling cart fragments
613
- }
614
-
615
- /**
616
- * Disable WooCommerce Cart Fragment Dequeuing
617
- *
618
- */
619
- public function disable_woo_cart_fragments() {
620
- delete_option('a2_wc_cart_fragments');
621
- delete_option('woocommerce_cart_redirect_after_add');
622
- }
623
-
624
- /**
625
- * Enable Blocking of XML-RPC Requests
626
- *
627
- */
628
- public function enable_xmlrpc_requests() {
629
- update_option('a2_block_xmlrpc', 1);
630
- }
631
-
632
- /**
633
- * Disable Blocking of XML-RPC Requests
634
- *
635
- */
636
- public function disable_xmlrpc_requests() {
637
- delete_option('a2_block_xmlrpc');
638
- }
639
-
640
- /**
641
- * Regenerate wp-config.php salts
642
- *
643
- */
644
- public function regenerate_wpconfig_salts() {
645
- $this->salts_array = [
646
- "define('AUTH_KEY',",
647
- 'SECURE_AUTH_KEY',
648
- 'LOGGED_IN_KEY',
649
- 'NONCE_KEY',
650
- "define('AUTH_SALT',",
651
- 'SECURE_AUTH_SALT',
652
- 'LOGGED_IN_SALT',
653
- 'NONCE_SALT',
654
- ];
655
-
656
- $returned_salts = file_get_contents('https://api.wordpress.org/secret-key/1.1/salt/');
657
- $this->new_salts = explode("\n", $returned_salts);
658
-
659
- update_option('a2_updated_regenerate-salts', date('F jS, Y'));
660
-
661
- return $this->writeSalts($this->salts_array, $this->new_salts);
662
- }
663
-
664
- public function regenerate_wpconfig_desc() {
665
- $output = '<p>Generate new salt values for wp-config.php<br /><strong>This will log out all users including yourself</strong><br />Last regenerated:</p>';
666
-
667
- return $output;
668
- }
669
-
670
- private function writeSalts($salts_array, $new_salts) {
671
- $config_file = $this->config_file_path();
672
-
673
- $tmp_config_file = ABSPATH . 'wp-config-tmp.php';
674
-
675
- foreach ($salts_array as $salt_key => $salt_value) {
676
- $readin_config = fopen($config_file, 'r');
677
- $writing_config = fopen($tmp_config_file, 'w');
678
-
679
- $replaced = false;
680
- while (!feof($readin_config)) {
681
- $line = fgets($readin_config);
682
- if (stristr($line, $salt_value)) {
683
- $line = $new_salts[$salt_key] . "\n";
684
- $replaced = true;
685
- }
686
- fputs($writing_config, $line);
687
- }
688
-
689
- fclose($readin_config);
690
- fclose($writing_config);
691
-
692
- if ($replaced) {
693
- rename($tmp_config_file, $config_file);
694
- } else {
695
- unlink($tmp_config_file);
696
- }
697
- }
698
- }
699
-
700
- private function config_file_path() {
701
- $salts_file_name = 'wp-config';
702
- $config_file = ABSPATH . $salts_file_name . '.php';
703
- $config_file_up = ABSPATH . '../' . $salts_file_name . '.php';
704
-
705
- if (file_exists($config_file) && is_writable($config_file)) {
706
- return $config_file;
707
- } elseif (file_exists($config_file_up) && is_writable($config_file_up) && !file_exists(dirname(ABSPATH) . '/wp-settings.php')) {
708
- return $config_file_up;
709
- }
710
-
711
- return false;
712
- }
713
-
714
- /**
715
- * Update w3tc plugin
716
- * @param array $vars Variables to set in config with the config writer
717
- *
718
- */
719
- public function update_w3tc($vars) {
720
- $vars = array_merge($this->get_w3tc_defaults(), $vars);
721
-
722
- /* Make sure we're running a compatible version of W3 Total Cache */
723
- if ($this->is_valid_w3tc_installed() && class_exists('W3_ConfigData')) {
724
- $config_writer = new W3_ConfigWriter(0, false);
725
- foreach ($vars as $name => $val) {
726
- $config_writer->set($name, $val);
727
- }
728
- $config_writer->set('common.instance_id', mt_rand());
729
- $config_writer->save();
730
- $this->refresh_w3tc();
731
- }
732
- }
733
-
734
- /**
735
- * Disable plugin cache for w3tc
736
- *
737
- */
738
- public function disable_w3tc_cache() {
739
- $this->update_w3tc([
740
- 'pgcache.enabled' => false,
741
- 'dbcache.enabled' => false,
742
- 'objectcache.enabled' => false,
743
- 'browsercache.enabled' => false,
744
- ]);
745
- }
746
-
747
- /**
748
- * Disable page cache for w3tc
749
- *
750
- */
751
- public function disable_w3tc_page_cache() {
752
- $vars = [];
753
- $vars['pgcache.enabled'] = false;
754
- $this->update_w3tc($vars);
755
- }
756
-
757
- /**
758
- * Disable database cache for w3tc
759
- *
760
- */
761
- public function disable_w3tc_db_cache() {
762
- $vars = [];
763
- $vars['dbcache.enabled'] = false;
764
- $this->update_w3tc($vars);
765
- }
766
-
767
- /**
768
- * Disable object cache for w3tc
769
- *
770
- */
771
- public function disable_w3tc_object_cache() {
772
- $vars = [];
773
- $vars['objectcache.enabled'] = false;
774
- $this->update_w3tc($vars);
775
- }
776
-
777
- /**
778
- * Disable browser cache for w3tc
779
- *
780
- */
781
- public function disable_w3tc_browser_cache() {
782
- $vars = [];
783
- $vars['browsercache.enabled'] = false;
784
- $this->update_w3tc($vars);
785
- }
786
-
787
- /**
788
- * Disable html minification
789
- *
790
- */
791
- public function disable_html_minify() {
792
- $this->update_w3tc([
793
- 'minify.html.enable' => false,
794
- 'minify.html.enabled' => false,
795
- 'minify.auto' => false
796
- ]);
797
- }
798
-
799
- /**
800
- * Enable html minification
801
- *
802
- */
803
- public function enable_html_minify() {
804
- $this->update_w3tc([
805
- 'minify.html.enable' => true,
806
- 'minify.enabled' => true,
807
- 'minify.auto' => false,
808
- 'minify.engine' => 'file'
809
- ]);
810
- }
811
-
812
- public function curl_save_w3tc($cookie, $url) {
813
- $post = 'w3tc_save_options=Save all settings&_wpnonce=' . wp_create_nonce('w3tc') . '&_wp_http_referer=%2Fwp-admin%2Fadmin.php%3Fpage%3Dw3tc_general%26&w3tc_note%3Dconfig_save';
814
-
815
- $ch = curl_init();
816
- curl_setopt($ch, CURLOPT_URL, get_admin_url() . $url);
817
- curl_setopt($ch, CURLOPT_HEADER, true);
818
- curl_setopt($ch, CURLOPT_POST, 1);
819
- curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
820
- curl_setopt($ch, CURLOPT_COOKIE, $cookie);
821
- curl_setopt($ch, CURLOPT_REFERER, get_admin_url() . $url);
822
- //curl_setopt($ch, CURLOPT_NOBODY, TRUE); // remove body
823
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
824
- $head = curl_exec($ch);
825
- curl_close($ch);
826
- }
827
-
828
- public function get_optimizations() {
829
- return $this->optimizations;
830
- }
831
-
832
- /**
833
- * Creates HTML for the Administration page to set options for this plugin.
834
- * Override this method to create a customized page.
835
- * @return void
836
- */
837
- public function settingsPage() {
838
- if (!current_user_can('manage_options')) {
839
- wp_die(__('You do not have sufficient permissions to access A2 Optimized.', 'a2-optimized'));
840
- }
841
-
842
- $thisclass = $this;
843
-
844
- //$thisdir = rtrim(__DIR__, '/');
845
-
846
- wp_enqueue_style('bootstrap', plugins_url('/assets/bootstrap/css/bootstrap.css', __FILE__), '', $thisclass->getVersion());
847
- wp_enqueue_style('bootstrap-theme', plugins_url('/assets/bootstrap/css/bootstrap-theme.css', __FILE__), '', $thisclass->getVersion());
848
- wp_enqueue_script('bootstrap-theme', plugins_url('/assets/bootstrap/js/bootstrap.js', __FILE__), ['jquery'], $thisclass->getVersion());
849
-
850
- $image_dir = plugins_url('/assets/images', __FILE__);
851
-
852
- $ini_error_reporting = ini_get('error_reporting');
853
-
854
- if (isset($_GET['a2-page'])) {
855
- if (isset($_GET['step'])) {
856
- $step = sanitize_text_field($_GET['step']);
857
- } else {
858
- $step = 1;
859
- }
860
-
861
- // Show wizard here...
862
- if ($_GET['a2-page'] == 'newuser_wizard') {
863
- $this->newuser_wizard_html($step);
864
- }
865
- if ($_GET['a2-page'] == 'upgrade_wizard') {
866
- $this->upgrade_wizard_html($step);
867
- }
868
- if ($_GET['a2-page'] == 'w3tc_migration_wizard') {
869
- $this->w3tc_migration_wizard_html($step);
870
- }
871
- if ($_GET['a2-page'] == 'w3tcfixed_confirm') {
872
- update_option('a2opt_w3tcfixed_confirm', true);
873
- $this->settings_page_html();
874
- }
875
- if ($_GET['a2-page'] == 'recaptcha_settings') {
876
- $this->recaptcha_settings_html();
877
- }
878
- if ($_GET['a2-page'] == 'recaptcha_settings_save') {
879
- $this->recaptcha_settings_save();
880
- $this->settings_page_html();
881
- }
882
- if ($_GET['a2-page'] == 'cache_settings') {
883
- $this->cache_settings_html();
884
- }
885
- if ($_GET['a2-page'] == 'cache_settings_save') {
886
- $this->cache_settings_save();
887
- $this->settings_page_html();
888
- }
889
- if ($_GET['a2-page'] == 'site_health') {
890
- $this->site_health_page_html();
891
- }
892
- if ($_GET['a2-page'] == 'site_health_save') {
893
- $this->site_health_save();
894
- $this->site_health_page_html();
895
- }
896
- if ($_GET['a2-page'] == 'site_health_remove') {
897
- $this->site_health_remove();
898
- $this->site_health_page_html();
899
- }
900
-
901
- if ($_GET['a2-page'] == 'dismiss_notice') {
902
- $allowed_notices = [
903
- 'a2_login_bookmark',
904
- 'a2_notice_incompatible_plugins',
905
- 'a2_notice_w3totalcache',
906
- 'a2_notice_editinglocked',
907
- 'a2_notice_editingnotlocked',
908
- 'a2_notice_wordfence_waf',
909
- 'a2_notice_configpage',
910
- 'a2_notice_diviminify',
911
- ];
912
- if (isset($_GET['a2-option']) && in_array($_GET['a2-option'], $allowed_notices)) {
913
- if ($_GET['a2-option'] == 'a2_login_bookmark') {
914
- update_option('a2_login_bookmark', get_option('a2_login_page'));
915
- } else {
916
- $a2_option = sanitize_text_field($_GET['a2-option']);
917
- update_option($a2_option, '1');
918
- }
919
- }
920
- $this->settings_page_html();
921
- }
922
- if ($_GET['a2-page'] == 'enable-rwl') {
923
- if ($_GET['enable'] == '1') {
924
- if (!isset($this->plugin_list['easy-hide-login/wp-hide-login.php'])) {
925
- $this->install_plugin('easy-hide-login');
926
- }
927
- $this->activate_plugin('easy-hide-login/wp-hide-login.php');
928
-
929
- if (get_option('a2_login_page') === false) {
930
- if (get_option('wpseh_l01gnhdlwp') === false) {
931
- $length = 4;
932
- $rwl_page = $this->getRandomString($length);
933
- update_option('a2_login_page', $rwl_page);
934
- update_option('wpseh_l01gnhdlwp', $rwl_page);
935
- } else {
936
- update_option('a2_login_page', get_option('wpseh_l01gnhdlwp'));
937
- }
938
- } else {
939
- update_option('wpseh_l01gnhdlwp', get_option('a2_login_page'));
940
- }
941
- delete_option('rwl_redirect');
942
- }
943
-
944
- update_option('a2_managed_changelogin', 1);
945
- $this->settings_page_html();
946
- }
947
- } else {
948
- $this->settings_page_html();
949
- }
950
- }
951
-
952
- /**
953
- * Settings page for A2Optimized
954
- *
955
- */
956
- private function settings_page_html() {
957
- $thisclass = $this;
958
- $w3tc = $this->get_w3tc_config();
959
- $opts = new A2_Optimized_Optimizations($thisclass);
960
- $optimization_count = 0;
961
- $this->get_plugin_status();
962
- $this->optimization_status = '';
963
- $image_dir = plugins_url('/assets/images', __FILE__);
964
-
965
- do_action('a2_notices');
966
-
967
- $optionMetaData = $this->getOptionMetaData();
968
-
969
- $optimization_status = '';
970
-
971
- foreach ($this->advanced_optimizations as $shortname => &$item) {
972
- $this->advanced_optimization_status .= $this->get_optimization_status($item, $opts->server_info);
973
- if ($item['configured']) {
974
- $this->advanced_optimization_count++;
975
- }
976
- }
977
-
978
- $this->divi_extra_info = '';
979
- if (get_template() == 'Divi' && ($w3tc['minify.html.enable'] || $w3tc['minify.css.enable'] || $w3tc['minify.js.enable'])) {
980
- $this->divi_extra_info = "<div class='alert alert-info'><p>We see that this site has the Divi theme activated. The following button will apply our recommended settings.</p><p><a href='" . admin_url('admin.php?page=A2_Optimized_Plugin_admin&apply_divi_settings=true') . "' class='button-secondary'>Optimize for Divi</a></p></div>";
981
- }
982
-
983
- $this->optimization_alert = '';
984
-
985
- if (is_plugin_active('w3-total-cache/w3-total-cache.php')) {
986
- $this->optimization_alert = "<div class='alert alert-info'>";
987
- $this->optimization_alert .= '<p>We noticed you have W3 Total Cache already installed. We are not able to fully support this version of W3 Total Cache with A2 Optimized. To get the best options for optimizing your WordPress site, we will help you disable this W3 Total Cache plugin version and install an A2 Hosting supported version of W3 Total Cache in its place.</p>';
988
- $this->optimization_alert .= "<p><a href='" . admin_url('admin.php?a2-page=upgrade_wizard&page=A2_Optimized_Plugin_admin') . "' class='btn btn-success'>Disable W3 Total Cache</a></p>";
989
- $this->optimization_alert .= '</div>';
990
- }
991
- if (is_plugin_active('w3-total-cache-fixed/w3-total-cache-fixed.php')) {
992
- $w3tc_fixed_info = get_plugin_data('w3-total-cache-fixed/w3-total-cache-fixed.php');
993
- if (version_compare($w3tc_fixed_info['Version'], '0.9.5.0') >= 0) {
994
- $this->optimization_alert = "<div class='alert alert-info'>";
995
- $this->optimization_alert .= '<p>We noticed you have W3 Total Cache already installed. We are not able to fully support this version of W3 Total Cache with A2 Optimized. To get the best options for optimizing your WordPress site, we will help you disable this W3 Total Cache plugin version and install an A2 Hosting supported version of W3 Total Cache in its place.</p>';
996
- $this->optimization_alert .= "<p><a href='" . admin_url('admin.php?a2-page=upgrade_wizard&page=A2_Optimized_Plugin_admin') . "' class='btn btn-success'>Disable W3 Total Cache Fixed</a></p>";
997
- $this->optimization_alert .= '</div>';
998
- } elseif (get_option('a2opt_w3tcfixed_confirm') === false) {
999
- $this->optimization_alert = "<div class='alert alert-info'>";
1000
- $this->optimization_alert .= '<p>Please note that you have W3 Total Cache Fixed v0.9.4.x plugin installed. We cannot guarantee our optimizations will be fully supported with this version. To ensure the best compatibility for your WordPress site, please disable the W3 Total Cache Fixed plugin by clicking the button below and install our supported W3 Total Cache plugin, which is based on W3 Total Cache Fixed.</p>';
1001
- $this->optimization_alert .= "<p><a href='" . admin_url('admin.php?a2-page=upgrade_wizard&page=A2_Optimized_Plugin_admin') . "' class='btn btn-success'>Disable W3 Total Cache Fixed</a></p>";
1002
- $this->optimization_alert .= '<p>If you would like to keep your currently installed W3 Total Cache Fixed plugin, you may click the button below to dismiss this dialog and enable the optimization options below.</p>';
1003
- $this->optimization_alert .= "<p><a href='" . admin_url('admin.php?a2-page=w3tcfixed_confirm&page=A2_Optimized_Plugin_admin') . "' class='btn btn-warning'>I accept the risks</a></p>";
1004
- $this->optimization_alert .= '</div>';
1005
- }
1006
- }
1007
- if (is_plugin_active('a2-w3-total-cache/a2-w3-total-cache.php')) {
1008
- $this->optimization_alert = "<div class='alert alert-info'>";
1009
- $this->optimization_alert .= '<p>We noticed you are using W3 Total Cache. The version you have installed is outdated and may cause issues with future versions of WordPress. However, A2 Optimized now comes with our own built-in caching engine. To get the best options for optimizing your WordPress site, we will help you disable the W3 Total Cache plugin version and install and configure A2 Optimized caching in place.</p>';
1010
- $this->optimization_alert .= "<p><a href='" . admin_url('admin.php?a2-page=w3tc_migration_wizard&page=A2_Optimized_Plugin_admin') . "' class='btn btn-success'>Upgrade your caching</a></p>";
1011
- $this->optimization_alert .= '</div>';
1012
- }
1013
-
1014
- $this->optimization_count = 0;
1015
- $optimization_number = count($this->optimizations);
1016
- $optimization_circle = '';
1017
-
1018
- $a2_cache_enabled = get_option('a2_cache_enabled');
1019
-
1020
- foreach ($this->optimizations as $shortname => &$item) {
1021
- $this->optimization_status .= $this->get_optimization_status($item, $opts->server_info);
1022
- if ($item['configured'] && !array_key_exists('optional', $item)) {
1023
- $this->optimization_count++;
1024
- }
1025
- if ((array_key_exists('plugin', $item) && $item['plugin'] == 'W3 Total Cache') || (array_key_exists('optional', $item) && $item['optional'] == true)) {
1026
- // W3 Total Cache items don't count anymore
1027
- // Optional items don't count towards total
1028
- $optimization_number = $optimization_number - 1;
1029
- }
1030
- }
1031
- if ($this->optimization_count >= $optimization_number) {
1032
- $optimization_alert = '<div class="alert alert-success">Your site has been fully optimized!</div>';
1033
- } elseif ($this->optimization_count > 2) {
1034
- $optimization_alert = '<div class="alert alert-success">Your site has been partially optimized!</div>';
1035
- } elseif (!$this->optimizations['a2_page_cache']['configured']) {
1036
- $optimization_alert = '<div class="alert alert-danger">Your site is NOT optimized!</div>';
1037
- } else {
1038
- $optimization_alert = '<div class="alert alert-danger">Your site is NOT optimized!</div>';
1039
- }
1040
-
1041
- if ($optimization_number > 0) {
1042
- $optimization_circle = <<<HTML
1043
- <span class="badge badge-success">{$this->optimization_count}/{$optimization_number}</span>
1044
- HTML;
1045
- }
1046
-
1047
- $kb_search_box = $this->kb_searchbox_html();
1048
-
1049
- list($warnings, $num_warnings) = $this->warnings();
1050
-
1051
- $advanced_circle = '';
1052
-
1053
- $save_alert = '';
1054
-
1055
- if (isset($_GET['save_settings']) && $_GET['save_settings']) {
1056
- $save_alert = '<div class="alert alert-success">Settings Saved</div>';
1057
- }
1058
-
1059
- if (isset($_GET['msg']) && $_GET['msg'] == 'token') {
1060
- $save_alert = '<div class="alert alert-danger">Session timed out, please try to configure your optimization again.</div>';
1061
- }
1062
-
1063
- $warning_circle = '';
1064
- if ($num_warnings > 0) {
1065
- $warning_circle = <<<HTML
1066
- <span class="badge badge-warning">{$num_warnings}</span>
1067
- HTML;
1068
- }
1069
-
1070
- $settingsGroup = get_class($this) . '-settings-group';
1071
- $description = $this->get_plugin_description();
1072
-
1073
- if ($this->is_a2()) {
1074
- $feedback = <<<HTML
1075
- <div style="margin:10px 0;" class="alert alert-success">
1076
- We want to hear from you! Please share your thoughts and feedback in our <a href="https://my.a2hosting.com/?m=a2_suggestionbox" target="_blank">Suggestion Box!</a>
1077
- </div>
1078
- HTML;
1079
- } else {
1080
- $feedback = <<<HTML
1081
- <div style="margin:10px 0;" class="alert alert-success">
1082
- We want to hear from you! Please share your thoughts and feedback in our wordpress.org <a href="https://wordpress.org/support/plugin/a2-optimized-wp/" target="_blank">support forum!</a>
1083
- </div>
1084
- HTML;
1085
- }
1086
-
1087
- echo <<<HTML
1088
-
1089
-
1090
- <section id="a2opt-content-general">
1091
- <div class="wrap">
1092
- <div>
1093
- <div>
1094
- <div>
1095
- <div style="float:left;clear:both">
1096
- <img src="{$image_dir}/a2optimized.png" style="margin-top:20px" />
1097
- </div>
1098
- <div style="float:right;">
1099
- {$kb_search_box}
1100
- </div>
1101
- </div>
1102
- <div style="clear:both;"></div>
1103
- </div>
1104
- <div >
1105
-
1106
- <div style="margin:20px 0;">
1107
- {$optimization_alert}
1108
- {$save_alert}
1109
- </div>
1110
- </div>
1111
- </div>
1112
-
1113
-
1114
- <ul class="nav nav-tabs" roll="tablist">
1115
- <li role="tab" aria-controls="optimization-status" id="li-optimization-status" ><a onclick='document.location.hash="#optimization-status-tab"' href="#optimization-status" data-toggle="tab">Optimization Status {$optimization_circle}</a></li>
1116
- <li role="tab" aria-controls="optimization-warnings" id="li-optimization-warnings" ><a onclick='document.location.hash="#optimization-warnings-tab"' href="#optimization-warnings" data-toggle="tab">Warnings {$warning_circle}</a></li>
1117
- <li role="tab" aria-controls="optimization-advanced" id="li-optimization-advanced" ><a onclick='document.location.hash="#optimization-advanced-tab"' href="#optimization-advanced" data-toggle="tab">Advanced Optimizations {$advanced_circle}</a></li>
1118
- <li role="tab" aria-controls="optimization-about" id="li-optimization-about" ><a onclick='document.location.hash="#optimization-about-tab"' href="#optimization-about" data-toggle="tab">About A2 Optimized</a></li>
1119
- </ul>
1120
-
1121
-
1122
-
1123
-
1124
- <div class="tab-content">
1125
- <div role="tabpanel" aria-labelledby="li-optimization-status" id="optimization-status" class="tab-pane">
1126
- <h1>Optimization Status</h1>
1127
- {$this->optimization_alert}
1128
- {$this->divi_extra_info}
1129
- <div >
1130
- {$this->optimization_status}
1131
- </div>
1132
- </div>
1133
- <div role="tabpanel" aria-labelledby="li-optimization-warnings" id="optimization-warnings" class="tab-pane">
1134
- <h1>Warnings</h1>
1135
- {$warnings}
1136
- </div>
1137
-
1138
- <div role="tabpanel" aria-labelledby="li-optimization-advanced" id="optimization-advanced" class="tab-pane">
1139
- <h1>Advanced Optimizations</h1>
1140
- {$this->advanced_optimization_status}
1141
- </div>
1142
-
1143
- <div role="tabpanel" aria-labelledby="li-optimization-about" id="optimization-about" class="tab-pane">
1144
- <div style="margin:20px 0;">
1145
- <h2>About A2 Optimized</h2>
1146
- <p>A2 Optimized was developed by A2 Hosting to make it faster and easier to configure the caching of all aspects of a WordPress site.</p>
1147
- <p>This free plugin comes with many of the popular Optimizations that come with WordPress hosted at A2 Hosting.</p>
1148
- <p>To get the full advantage of A2 Optimized, host your site at <a href='https://www.a2hosting.com/wordpress-hosting?utm_source=A2%20Optimized&utm_medium=Referral&utm_campaign=A2%20Optimized' target='_blank'>A2 Hosting</a></p>
1149
-
1150
- </div>
1151
- <div style="margin:20px 0;">
1152
- <h2>Additional Plugins Installed on A2 Hosting</h2>
1153
- <p><strong>Easy Hide Login</strong><br />
1154
- Changes the location of the WordPress login page</p>
1155
- <p><strong>Image Optimizer</strong><br />
1156
- Compress and optimize images on upload</p>
1157
- </div>
1158
- <div style="margin:20px 0;">
1159
- <h2>Free Optimizations</h2>
1160
- <dt>Page Caching</dt>
1161
- <dd>
1162
- <ul>
1163
- <li>Page Caching stores full copies of pages on the disk so that PHP code and database queries can be skipped by the web server.</li>
1164
- </ul>
1165
- </dd>
1166
-
1167
- <dt>Minify HTML Pages</dt>
1168
- <dd>
1169
- <ul>
1170
- <li style="list-style-position: inside">Auto Configure W3 Total Cache to remove excess white space and comments from HTML pages to compress their size.</li>
1171
- <li>Smaller html pages download faster.</li>
1172
- </ul>
1173
- </dd>
1174
- <dt>Minify inline CSS rules</dt>
1175
- <dd>
1176
- <ul>
1177
- <li>Can provide significant speed imporvements for page loads.</li>
1178
- </ul>
1179
- </dd>
1180
- <dt>Minify inline JS</dt>
1181
- <dd>
1182
- <ul>
1183
- <li>Can provide significant speed improvements for page loads.</li>
1184
- </ul>
1185
- </dd>
1186
- <dt>Gzip Compression Enabled</dt>
1187
- <dd>
1188
- <ul>
1189
- <li>Turns on gzip compression.</li>
1190
- <li>Ensures that files are compressed before sending them to the visitor's browser.</li>
1191
- <li>Can provide significant speed improvements for page loads.</li>
1192
- <li>Reduces bandwidth required to serve web pages.</li>
1193
- </ul>
1194
- </dd>
1195
- <dt>Deny Direct Access to Configuration Files and Comment Form</dt>
1196
- <dd>
1197
- <ul>
1198
- <li>Enables WordPress hardening rules in .htaccess to prevent browser access to certain files.</li>
1199
- <li>Prevents bots from submitting to comment forms.</li>
1200
- <li>Turn this off if you use systems that post to the comment form without visiting the page.</li>
1201
- </ul>
1202
- </dd>
1203
- <dt>Lock Editing of Plugins and Themes from the WP Admin</dt>
1204
- <dd>
1205
- <ul>
1206
- <li>Turns off the file editor in the wp-admin.</li>
1207
- <li>Prevents plugins and themes from being tampered with from the wp-admin.</li>
1208
- </ul>
1209
- </dd>
1210
- </div>
1211
- <div style="margin:20px 0;">
1212
- <h2>A2 Hosting Exclusive Optimizations</h2>
1213
- <p>
1214
- These one-click optimizations are only available while hosted at A2 Hosting.
1215
- </p>
1216
- <dt>Login URL Change</dt>
1217
- <dd>
1218
- <ul>
1219
- <li>Move the login page from the default wp-login.php to a random URL.</li>
1220
- <li>Prevents bots from automatically brute-force attacking wp-login.php</li>
1221
- </ul>
1222
- </dd>
1223
- <dt>reCAPTCHA on comments and login</dt>
1224
- <dd>
1225
- <ul>
1226
- <li>Provides google reCAPTCHA on both the Login form and comments.</li>
1227
- <li>Prevents bots from automatically brute-force attacking wp-login.php</li>
1228
- <li>Prevents bots from automatically spamming comments.</li>
1229
- </ul>
1230
- </dd>
1231
- <dt>Compress Images on Upload</dt>
1232
- <dd>
1233
- <ul>
1234
- <li>Enables and configures Image Optimizer.</li>
1235
- <li>Compresses images that are uploaded to save bandwidth.</li>
1236
- <li>Improves page load times: especially on sites with many images.</li>
1237
- </ul>
1238
- </dd>
1239
- <dt>Turbo Web Hosting</dt>
1240
- <dd>
1241
- <ul>
1242
- <li>Take advantage of A2 Hosting's Turbo Web Hosting platform.</li>
1243
- <li>Faster serving of static files.</li>
1244
- <li>Pre-compiled .htaccess files on the web server for imporved performance.</li>
1245
- <li>PHP OpCode cache enabled by default</li>
1246
- <li>Custom PHP engine that is faster than Fast-CGI and FPM</li>
1247
- </ul>
1248
- </dd>
1249
- <dt>Memcached Database and Object Cache</dt>
1250
- <dd>
1251
- <ul>
1252
- <li>Database and Object cache in memory instead of on disk.</li>
1253
- <li>More secure and faster Memcached using Unix socket files.</li>
1254
- <li>Significant improvement in page load times, especially on pages that can not use full page cache such as wp-admin</li>
1255
- </ul>
1256
- </dd>
1257
- </div>
1258
- </div>
1259
- </div>
1260
-
1261
- $feedback
1262
-
1263
- </div>
1264
-
1265
- <div style="clear:both;padding:10px;"></div>
1266
- </section>
1267
-
1268
-
1269
- <script>
1270
- if(document.location.hash != ""){
1271
- switch(document.location.hash.replace("#","")){
1272
- case 'optimization-status-tab':
1273
- document.getElementById("li-optimization-status").setAttribute("class","active");
1274
- document.getElementById("optimization-status").setAttribute("class","tab-pane active");
1275
- break;
1276
- case 'optimization-warnings-tab':
1277
- document.getElementById("li-optimization-warnings").setAttribute("class","active");
1278
- document.getElementById("optimization-warnings").setAttribute("class","tab-pane active");
1279
- break;
1280
- case "optimization-plugins-tab":
1281
- document.getElementById("li-optimization-plugins").setAttribute("class","active");
1282
- document.getElementById("optimization-plugins").setAttribute("class","tab-pane active");
1283
- break;
1284
- case "optimization-advanced-tab":
1285
- document.getElementById("li-optimization-advanced").setAttribute("class","active");
1286
- document.getElementById("optimization-advanced").setAttribute("class","tab-pane active");
1287
- break;
1288
- case "optimization-about-tab":
1289
- document.getElementById("li-optimization-about").setAttribute("class","active");
1290
- document.getElementById("optimization-about").setAttribute("class","tab-pane active");
1291
- break;
1292
- default:
1293
- document.getElementById("li-optimization-status").setAttribute("class","active");
1294
- document.getElementById("optimization-status").setAttribute("class","tab-pane active");
1295
- }
1296
- }
1297
- else{
1298
- document.getElementById("li-optimization-status").setAttribute("class","active");
1299
- document.getElementById("optimization-status").setAttribute("class","tab-pane active");
1300
- }
1301
- </script>
1302
-
1303
- HTML;
1304
- }
1305
-
1306
- /**
1307
- * Wizard to migrate from the W3TC plugin
1308
- * @param integer $setup_step The step to begin install process
1309
- *
1310
- */
1311
- private function w3tc_migration_wizard_html($setup_step = 1) {
1312
- $image_dir = plugins_url('/assets/images', __FILE__);
1313
- $kb_search_box = $this->kb_searchbox_html();
1314
- $w3tc_settings = $this->get_w3tc_config();
1315
- $migrated_settings = [];
1316
- $migrated_settings['page_cache'] = [
1317
- 'name' => 'Enable Page Caching',
1318
- 'w3tc_value' => $w3tc_settings['pgcache.enabled']
1319
- ];
1320
- $migrated_settings['excluded_cookies'] = [
1321
- 'name' => 'Do not cache requests that have these cookies',
1322
- 'w3tc_value' => $w3tc_settings['pgcache.reject.cookie']
1323
- ];
1324
- $migrated_settings['object_cache'] = [
1325
- 'name' => 'Enable Memcached Object Caching',
1326
- 'w3tc_value' => $w3tc_settings['objectcache.enabled']
1327
- ];
1328
- $migrated_settings['memcached_server'] = [
1329
- 'name' => 'Memcached Servers',
1330
- 'w3tc_value' => $w3tc_settings['objectcache.memcached.servers']
1331
- ];
1332
- $migrated_settings['clear_site_cache_on_saved_post'] = [
1333
- 'name' => 'Clear cache when saving post',
1334
- 'w3tc_value' => $w3tc_settings['pgcache.purge.post']
1335
- ];
1336
- $migrated_settings['clear_site_cache_on_saved_comment'] = [
1337
- 'name' => 'Clear cache when a new comment is added',
1338
- 'w3tc_value' => $w3tc_settings['pgcache.purge.comments']
1339
- ];
1340
- $migrated_settings['compress_cache'] = [
1341
- 'name' => 'GZIP compress cached pages',
1342
- 'w3tc_value' => $w3tc_settings['browsercache.html.compression']
1343
- ];
1344
- $migrated_settings['minify_html'] = [
1345
- 'name' => 'HTML Minification',
1346
- 'w3tc_value' => $w3tc_settings['minify.html.enable']
1347
- ];
1348
- $migrated_settings['minify_inline_css_js'] = [
1349
- 'name' => 'Javascript and CSS Minification',
1350
- 'w3tc_value' => $w3tc_settings['minify.js.enable']
1351
- ];
1352
-
1353
- if ($setup_step == 1) {
1354
- echo <<<HTML
1355
- <section id="a2opt-content-general">
1356
- <div class="wrap">
1357
- <div>
1358
- <div>
1359
- <div>
1360
- <div style="float:left;clear:both">
1361
- <img src="{$image_dir}/a2optimized.png" style="margin-top:20px" />
1362
- </div>
1363
- <div style="float:right;">
1364
- {$kb_search_box}
1365
- </div>
1366
- </div>
1367
- <div style="clear:both;"></div>
1368
- </div>
1369
- </div>
1370
- <div class="tab-content">
1371
- <h3>A2 W3 Total Cache plugin settings</h3>
1372
- <p class='loading-spinner'><img src='{$image_dir}/spinner.gif' style='height: auto; width: 50px;' /></p>
1373
- HTML;
1374
-
1375
- $step_output = '<p>We have detected the following W3 Total Cache settings and will migrate them to the A2 Optimized caching engine.</p><ul>';
1376
-
1377
- foreach ($migrated_settings as $k => $item) {
1378
- $value = 'No';
1379
- if ($item['w3tc_value']) {
1380
- $value = 'Yes';
1381
- }
1382
- if (is_array($item['w3tc_value'])) {
1383
- $value = json_encode($item['w3tc_value']);
1384
- }
1385
- if ($k == 'memcached_server') {
1386
- if (is_array($item['w3tc_value'])) {
1387
- $value = $item['w3tc_value'][0];
1388
- } else {
1389
- $value = 'Not set';
1390
- }
1391
- }
1392
- if ($k == 'excluded_cookies') {
1393
- if (is_array($item['w3tc_value'])) {
1394
- // /^(comment_author|woocommerce_items_in_cart|wp_woocommerce_session)_?/
1395
- //$value = "/^(" . $item['w3tc_value'] . ")_?/";
1396
- $value = implode(', ', $item['w3tc_value']);
1397
- } else {
1398
- $value = 'Not set';
1399
- }
1400
- }
1401
-
1402
- $step_output .= '<li><strong>' . $item['name'] . '</strong>: ' . $value . '</li>';
1403
- }
1404
-
1405
- $step_output .= "</ul><p>Next we will need to deactivate the W3 Total Cache plugin.</p><p><a href='" . admin_url('admin.php?a2-page=w3tc_migration_wizard&page=A2_Optimized_Plugin_admin&step=2') . "' class='btn btn-success'>Deactivate</a></p>";
1406
- echo <<<HTML
1407
- <div>
1408
- {$step_output}
1409
- </div>
1410
- </div>
1411
- </div>
1412
-
1413
- <div style="clear:both;padding:10px;"></div>
1414
- </section>
1415
- <style>
1416
- .loading-spinner { display: none; }
1417
- </style>
1418
- HTML;
1419
- }
1420
-
1421
- if ($setup_step == 2) {
1422
- $admin_url = admin_url('admin.php?page=A2_Optimized_Plugin_admin');
1423
-
1424
- $a2_cache_settings = A2_Optimized_Cache::get_settings();
1425
- if ($migrated_settings['excluded_cookies']['w3tc_value'] && is_array($migrated_settings['excluded_cookies']['w3tc_value'])) {
1426
- $a2_cache_settings['excluded_cookies'] = implode(',', $migrated_settings['excluded_cookies']['w3tc_value']);
1427
- }
1428
- if ($migrated_settings['clear_site_cache_on_saved_post']['w3tc_value']) {
1429
- $a2_cache_settings['clear_site_cache_on_saved_post'] = 1;
1430
- }
1431
- if ($migrated_settings['clear_site_cache_on_saved_comment']['w3tc_value']) {
1432
- $a2_cache_settings['clear_site_cache_on_saved_comment'] = 1;
1433
- }
1434
- if ($migrated_settings['compress_cache']['w3tc_value']) {
1435
- $a2_cache_settings['compress_cache'] = 1;
1436
- }
1437
- if ($migrated_settings['minify_html']['w3tc_value']) {
1438
- $a2_cache_settings['minify_html'] = 1;
1439
- }
1440
- if ($migrated_settings['minify_inline_css_js']['w3tc_value']) {
1441
- $a2_cache_settings['minify_inline_css_js'] = 1;
1442
- }
1443
-
1444
- $a2_cache_settings = A2_Optimized_Cache::validate_settings($a2_cache_settings);
1445
- update_option('a2opt-cache', $a2_cache_settings);
1446
- A2_Optimized_Cache_Disk::create_settings_file( $a2_cache_settings );
1447
-
1448
- $this->deactivate_plugin('a2-w3-total-cache/a2-w3-total-cache.php');
1449
-
1450
- if ($migrated_settings['page_cache']['w3tc_value']) {
1451
- $this->enable_a2_page_cache();
1452
- }
1453
- if ($migrated_settings['object_cache']['w3tc_value'] && is_array($migrated_settings['memcached_server']['w3tc_value'])) {
1454
- $memcached_server = $migrated_settings['memcached_server']['w3tc_value'][0];
1455
- if (substr($memcached_server, 0, 14) == '/opt/memcached') {
1456
- $memcached_server = 'unix://' . $memcached_server;
1457
- }
1458
- update_option('a2_optimized_memcached_server', $memcached_server);
1459
- $this->enable_a2_object_cache();
1460
- }
1461
-
1462
- echo <<<HTML
1463
- <section id="a2opt-content-general">
1464
- <div class="wrap">
1465
- <div>
1466
- <div>
1467
- <div>
1468
- <div style="float:left;clear:both">
1469
- <img src="{$image_dir}/a2optimized.png" style="margin-top:20px" />
1470
- </div>
1471
- <div style="float:right;">
1472
- {$kb_search_box}
1473
- </div>
1474
- </div>
1475
- <div style="clear:both;"></div>
1476
- </div>
1477
- </div>
1478
- <div class="tab-content">
1479
- <h3>Congratulations!</h3>
1480
- <div>
1481
- <p>You are now migrated from W3 Total Cache. You can now return to your A2 Optimized Dashboard.</p>
1482
- <p><a href='{$admin_url}' class='btn btn-success'>A2 Optimized Dashboard</a></p>
1483
- </div>
1484
- </div>
1485
- </div>
1486
-
1487
- <div style="clear:both;padding:10px;"></div>
1488
- </section>
1489
-
1490
- HTML;
1491
- }
1492
- }
1493
-
1494
- /**
1495
- * Wizard to install the W3TC plugin
1496
- * @param integer $setup_step The step to begin install process
1497
- *
1498
- */
1499
- private function newuser_wizard_html($setup_step = 1) {
1500
- $image_dir = plugins_url('/assets/images', __FILE__);
1501
- $kb_search_box = $this->kb_searchbox_html();
1502
-
1503
- if ($setup_step == 1) {
1504
- echo <<<HTML
1505
- <section id="a2opt-content-general">
1506
- <div class="wrap">
1507
- <div>
1508
- <div>
1509
- <div>
1510
- <div style="float:left;clear:both">
1511
- <img src="{$image_dir}/a2optimized.png" style="margin-top:20px" />
1512
- </div>
1513
- <div style="float:right;">
1514
- {$kb_search_box}
1515
- </div>
1516
- </div>
1517
- <div style="clear:both;"></div>
1518
- </div>
1519
- </div>
1520
- <div class="tab-content">
1521
- <h3>Downloading A2 W3 Total Cache plugin</h3>
1522
- <p class='loading-spinner'><img src='{$image_dir}/spinner.gif' style='height: auto; width: 50px;' /></p>
1523
- HTML;
1524
-
1525
- if ($this->is_plugin_installed('a2-w3-total-cache/a2-w3-total-cache.php')) {
1526
- $plugin_install_output = "<p>W3 Total Cache has now been successfully downloaded. Next we will activate the plugin.</p><p><a href='" . admin_url('admin.php?a2-page=newuser_wizard&page=A2_Optimized_Plugin_admin&step=2') . "' class='btn btn-success'>Activate</a></p>";
1527
- } else {
1528
- $plugin_install = $this->install_plugin('a2-w3-total-cache');
1529
- if ($plugin_install) {
1530
- $plugin_install_output = "<p>W3 Total Cache has now been successfully downloaded. Next we will activate the plugin.</p><p><a href='" . admin_url('admin.php?a2-page=newuser_wizard&page=A2_Optimized_Plugin_admin&step=2') . "' class='btn btn-success'>Activate</a></p>";
1531
- } else {
1532
- $plugin_install_output = "<p class='text-danger'>We couldn’t install the new plugin to your site. This is usually caused by permission issues or low disk space. You may need to contact your web host for more information.</p><p>You may also download the zip archive of the plugin below and attempt to install it manually.</p><p><a href='https://wp-plugins.a2hosting.com/wp-content/uploads/rkv-repo/a2-w3-total-cache.zip' class='btn btn-info' target='_blank'>Download ZIP</a>";
1533
- }
1534
- }
1535
- echo <<<HTML
1536
- <div>
1537
- {$plugin_install_output}
1538
- </div>
1539
- </div>
1540
- </div>
1541
-
1542
- <div style="clear:both;padding:10px;"></div>
1543
- </section>
1544
- <style>
1545
- .loading-spinner { display: none; }
1546
- </style>
1547
- HTML;
1548
- }
1549
-
1550
- if ($setup_step == 2) {
1551
- $this->activate_plugin('a2-w3-total-cache/a2-w3-total-cache.php');
1552
- $admin_url = admin_url('admin.php?page=A2_Optimized_Plugin_admin');
1553
-
1554
- echo <<<HTML
1555
- <section id="a2opt-content-general">
1556
- <div class="wrap">
1557
- <div>
1558
- <div>
1559
- <div>
1560
- <div style="float:left;clear:both">
1561
- <img src="{$image_dir}/a2optimized.png" style="margin-top:20px" />
1562
- </div>
1563
- <div style="float:right;">
1564
- {$kb_search_box}
1565
- </div>
1566
- </div>
1567
- <div style="clear:both;"></div>
1568
- </div>
1569
- </div>
1570
- <div class="tab-content">
1571
- <h3>Congratulations!</h3>
1572
- <div>
1573
- <p>W3 Total Cache is now installed. Let’s get started with the configuration.</p>
1574
- <p><a href='{$admin_url}' class='btn btn-success'>Start Configuration</a></p>
1575
- </div>
1576
- </div>
1577
- </div>
1578
-
1579
- <div style="clear:both;padding:10px;"></div>
1580
- </section>
1581
-
1582
- HTML;
1583
- }
1584
- }
1585
-
1586
- /**
1587
- * Wizard to upgrade the W3TC plugin installation
1588
- *
1589
- * @param integer $setup_step The step to begin install process
1590
- *
1591
- */
1592
- private function upgrade_wizard_html($setup_step = 1) {
1593
- $image_dir = plugins_url('/assets/images', __FILE__);
1594
- $kb_search_box = $this->kb_searchbox_html();
1595
- $admin_url = admin_url('admin.php?a2-page=newuser_wizard&page=A2_Optimized_Plugin_admin&step=1');
1596
-
1597
- if ($setup_step == 1) {
1598
- echo <<<HTML
1599
- <section id="a2opt-content-general">
1600
- <div class="wrap">
1601
- <div>
1602
- <div>
1603
- <div>
1604
- <div style="float:left;clear:both">
1605
- <img src="{$image_dir}/a2optimized.png" style="margin-top:20px" />
1606
- </div>
1607
- <div style="float:right;">
1608
- {$kb_search_box}
1609
- </div>
1610
- </div>
1611
- <div style="clear:both;"></div>
1612
- </div>
1613
- </div>
1614
- <div class="tab-content">
1615
- <h3>Disabling incompatible W3 Total Cache plugin</h3>
1616
- <p class='loading-spinner'><img src='{$image_dir}/spinner.gif' style='height: auto; width: 50px;' /></p>
1617
- HTML;
1618
- $this->deactivate_plugin('w3-total-cache/w3-total-cache.php');
1619
- $this->deactivate_plugin('w3-total-cache-fixed/w3-total-cache-fixed.php');
1620
- $plugin_install_output = "<p>W3 Total Cache has been disabled. We will now download a supported version of W3 Total Cache to your site.</p><p><a href='" . $admin_url . "' class='btn btn-success'>Install supported W3 Total Cache</a></p>";
1621
-
1622
- echo <<<HTML
1623
- <div>
1624
- {$plugin_install_output}
1625
- </div>
1626
- </div>
1627
- </div>
1628
-
1629
- <div style="clear:both;padding:10px;"></div>
1630
- </section>
1631
- <style>
1632
- .loading-spinner { display: none; }
1633
- </style>
1634
- HTML;
1635
- }
1636
- }
1637
-
1638
- /**
1639
- * reCaptcha Settings Page
1640
- *
1641
- */
1642
- private function recaptcha_settings_html() {
1643
- $image_dir = plugins_url('/assets/images', __FILE__);
1644
- $kb_search_box = $this->kb_searchbox_html();
1645
- $admin_url = admin_url('admin.php?a2-page=recaptcha_settings_save&page=A2_Optimized_Plugin_admin&save_settings=1');
1646
-
1647
- $a2_recaptcha_usecustom = get_option('a2_recaptcha_usecustom');
1648
- $a2_recaptcha_sitekey = esc_textarea(get_option('a2_recaptcha_sitekey'));
1649
- $a2_recaptcha_secretkey = esc_textarea(get_option('a2_recaptcha_secretkey'));
1650
- $a2_recaptcha_theme = get_option('a2_recaptcha_theme');
1651
-
1652
- $dark_selected = '';
1653
- if ($a2_recaptcha_theme == 'dark') {
1654
- $dark_selected = 'selected';
1655
- }
1656
- $custom_selected = '';
1657
- if ($a2_recaptcha_usecustom) {
1658
- $custom_selected = 'checked';
1659
- }
1660
-
1661
- echo <<<HTML
1662
- <section id="a2opt-content-general">
1663
- <div class="wrap">
1664
- <div>
1665
- <div>
1666
- <div>
1667
- <div style="float:left;clear:both">
1668
- <img src="{$image_dir}/a2optimized.png" style="margin-top:20px" />
1669
- </div>
1670
- <div style="float:right;">
1671
- {$kb_search_box}
1672
- </div>
1673
- </div>
1674
- <div style="clear:both;"></div>
1675
- </div>
1676
- </div>
1677
- <div class="tab-content">
1678
- <h1>reCaptcha Settings</h1>
1679
- <div>
1680
- <form action="{$admin_url}" method="POST">
1681
- <div class="form-group">
1682
- <label>
1683
- <input type="checkbox" name="a2_recaptcha_usecustom" value="1" {$custom_selected}>
1684
- Use my settings below for reCaptcha
1685
- </label>
1686
- </div>
1687
- <div class="form-group">
1688
- <label for="a2_recaptcha_sitekey">Site Key</label>
1689
- <input type="text" class="form-control" id="a2_recaptcha_sitekey" name="a2_recaptcha_sitekey" value="{$a2_recaptcha_sitekey}" placeholder="Site Key">
1690
- </div>
1691
- <div class="form-group">
1692
- <label for="a2_recaptcha_secretkey">Secret Key</label>
1693
- <input type="text" class="form-control" id="a2_recaptcha_secretkey" name="a2_recaptcha_secretkey" value="{$a2_recaptcha_secretkey}" placeholder="Secret Key">
1694
- </div>
1695
- <div class="form-group">
1696
- <label for="exampleInputEmail1">Theme</label>
1697
- <select class="form-control" id="a2_recaptcha_theme" name="a2_recaptcha_theme">
1698
- <option value="light" >Light</option>
1699
- <option value="dark" {$dark_selected}>Dark</option>
1700
- </select>
1701
- </div>
1702
- <button type="submit" class="btn btn-success">Save Settings</button>
1703
- </form>
1704
- </div>
1705
- </div>
1706
-
1707
- </div>
1708
-
1709
- <div style="clear:both;padding:10px;"></div>
1710
- </section>
1711
- HTML;
1712
- }
1713
-
1714
- /**
1715
- * Save reCaptcha Settings
1716
- *
1717
- */
1718
- private function recaptcha_settings_save() {
1719
- update_option('a2_recaptcha_usecustom', sanitize_text_field($_POST['a2_recaptcha_usecustom']));
1720
- update_option('a2_recaptcha_sitekey', sanitize_text_field($_POST['a2_recaptcha_sitekey']));
1721
- update_option('a2_recaptcha_secretkey', sanitize_text_field($_POST['a2_recaptcha_secretkey']));
1722
- update_option('a2_recaptcha_theme', sanitize_text_field($_POST['a2_recaptcha_theme']));
1723
- }
1724
-
1725
- /**
1726
- * Cache Settings Page
1727
- *
1728
- */
1729
- private function cache_settings_html() {
1730
- $image_dir = plugins_url('/assets/images', __FILE__);
1731
- $kb_search_box = $this->kb_searchbox_html();
1732
- $admin_url = 'options.php';
1733
- $db_optimization_settings = get_option('a2_db_optimizations'); ?>
1734
- <section id="a2opt-content-general">
1735
- <div class="wrap">
1736
- <div>
1737
- <div>
1738
- <div>
1739
- <div style="float:left;clear:both">
1740
- <img src="<?php echo $image_dir; ?>/a2optimized.png" style="margin-top:20px" />
1741
- </div>
1742
- <div style="float:right;">
1743
- <?php echo $kb_search_box; ?>
1744
- </div>
1745
- </div>
1746
- <div style="clear:both;"></div>
1747
- </div>
1748
- </div>
1749
- <div class="tab-content">
1750
- <?php if (isset($_REQUEST['settings-updated']) && $_REQUEST['settings-updated'] == 'true') { ?>
1751
- <div class="notice notice-success is-dismissible"><p>Settings Saved</p></div>
1752
- <?php } ?>
1753
- <?php if (get_option('a2_optimized_memcached_invalid')) { ?>
1754
- <div class="notice notice-error"><p>There is an issue with your Memcached settings<br /><?php echo get_option('a2_optimized_memcached_invalid'); ?></p></div>
1755
- <?php } ?>
1756
- <h3>Advanced A2 Optimized Settings</h3>
1757
- <div>
1758
- <form method="post" action="<?php echo $admin_url; ?>">
1759
- <?php settings_fields( 'a2opt-cache' ); ?>
1760
- <table class="form-table">
1761
- <tr valign="top">
1762
- <th scope="row">
1763
- <?php esc_html_e( 'Cache Behavior', 'a2-optimized-wp' ); ?>
1764
- </th>
1765
- <td>
1766
- <fieldset>
1767
- <p class="subheading"><?php esc_html_e( 'Expiration', 'a2opt-cache' ); ?></p>
1768
- <label for="cache_expires" class="checkbox--form-control">
1769
- <input name="a2opt-cache[cache_expires]" type="checkbox" id="cache_expires" value="1" <?php checked( '1', A2_Optimized_Cache_Engine::$settings['cache_expires'] ); ?> />
1770
- </label>
1771
- <label for="cache_expiry_time">
1772
- <?php
1773
- printf(
1774
- // translators: %s: Number of hours.
1775
- esc_html__( 'Cached pages expire %s hours after being created.', 'a2-optimized-wp' ),
1776
- '<input name="a2opt-cache[cache_expiry_time]" type="number" id="cache_expiry_time" value="' . A2_Optimized_Cache_Engine::$settings['cache_expiry_time'] . '" class="small-text">'
1777
- ); ?>
1778
- </label>
1779
-
1780
- <br />
1781
-
1782
- <p class="subheading"><?php esc_html_e( 'Clearing', 'a2-optimized-wp' ); ?></p>
1783
- <label for="clear_site_cache_on_saved_post">
1784
- <input name="a2opt-cache[clear_site_cache_on_saved_post]" type="checkbox" id="clear_site_cache_on_saved_post" value="1" <?php checked( '1', A2_Optimized_Cache_Engine::$settings['clear_site_cache_on_saved_post'] ); ?> />
1785
- <?php esc_html_e( 'Clear the site cache if any post type has been published, updated, or trashed (instead of only the page and/or associated cache).', 'a2-optimized-wp' ); ?>
1786
- </label>
1787
-
1788
- <br />
1789
-
1790
- <label for="clear_site_cache_on_saved_comment">
1791
- <input name="a2opt-cache[clear_site_cache_on_saved_comment]" type="checkbox" id="clear_site_cache_on_saved_comment" value="1" <?php checked( '1', A2_Optimized_Cache_Engine::$settings['clear_site_cache_on_saved_comment'] ); ?> />
1792
- <?php esc_html_e( 'Clear the site cache if a comment has been posted, updated, spammed, or trashed (instead of only the page cache).', 'a2-optimzied-wp' ); ?>
1793
- </label>
1794
-
1795
- <br />
1796
-
1797
- <label for="clear_site_cache_on_changed_plugin">
1798
- <input name="a2opt-cache[clear_site_cache_on_changed_plugin]" type="checkbox" id="clear_site_cache_on_changed_plugin" value="1" <?php checked( '1', A2_Optimized_Cache_Engine::$settings['clear_site_cache_on_changed_plugin'] ); ?> />
1799
- <?php esc_html_e( 'Clear the site cache if a plugin has been activated, updated, or deactivated.', 'a2-optimized-wp' ); ?>
1800
- </label>
1801
-
1802
- <br />
1803
-
1804
- <p class="subheading"><?php esc_html_e( 'Variants', 'a2-optimized-wp' ); ?></p>
1805
-
1806
- <label for="compress_cache">
1807
- <input name="a2opt-cache[compress_cache]" type="checkbox" id="compress_cache" value="1" <?php checked( '1', A2_Optimized_Cache_Engine::$settings['compress_cache'] ); ?> />
1808
- <?php esc_html_e( 'Pre-compress cached pages with Gzip.', 'a2-optimized-wp' ); ?>
1809
- </label>
1810
-
1811
- <br />
1812
-
1813
- <p class="subheading"><?php esc_html_e( 'Minification', 'a2-optimized-wp' ); ?></p>
1814
- <label for="minify_html" class="checkbox--form-control">
1815
- <input name="a2opt-cache[minify_html]" type="checkbox" id="minify_html" value="1" <?php checked( '1', A2_Optimized_Cache_Engine::$settings['minify_html'] ); ?> />
1816
- </label>
1817
- <label for="minify_inline_css_js">
1818
- <?php
1819
- $minify_inline_css_js_options = [
1820
- esc_html__( 'excluding', 'a2-optimized-wp' ) => 0,
1821
- esc_html__( 'including', 'a2-optimized-wp' ) => 1,
1822
- ];
1823
- $minify_inline_css_js = '<select name="a2opt-cache[minify_inline_css_js]" id="minify_inline_css_js">';
1824
- foreach ( $minify_inline_css_js_options as $key => $value ) {
1825
- $minify_inline_css_js .= '<option value="' . esc_attr( $value ) . '"' . selected( $value, A2_Optimized_Cache_Engine::$settings['minify_inline_css_js'], false ) . '>' . $key . '</option>';
1826
- }
1827
- $minify_inline_css_js .= '</select>';
1828
- printf(
1829
- // translators: %s: Form field control for 'excluding' or 'including' inline CSS and JavaScript during HTML minification.
1830
- esc_html__( 'Minify HTML in cached pages %s inline CSS and JavaScript.', 'a2-optimized-wp' ),
1831
- $minify_inline_css_js
1832
- ); ?>
1833
- </label>
1834
- </fieldset>
1835
- </td>
1836
- </tr>
1837
-
1838
- <tr valign="top">
1839
- <th scope="row">
1840
- <?php esc_html_e( 'Cache Exclusions', 'a2-optimized-wp' ); ?>
1841
- </th>
1842
- <td>
1843
- <fieldset>
1844
- <p class="subheading"><?php esc_html_e( 'Post IDs', 'a2-optimized-wp' ); ?></p>
1845
- <label for="excluded_post_ids">
1846
- <input name="a2opt-cache[excluded_post_ids]" type="text" id="excluded_post_ids" value="<?php echo esc_attr( A2_Optimized_Cache_Engine::$settings['excluded_post_ids'] ) ?>" class="regular-text" />
1847
- <p class="description">
1848
- <?php
1849
- // translators: %s: ,
1850
- printf( esc_html__( 'Post IDs separated by a %s that should bypass the cache.', 'a2-optimized-wp' ), '<code class="code--form-control">,</code>' ); ?>
1851
- </p>
1852
- <p><?php esc_html_e( 'Example:', 'a2-optimized-wp' ); ?> <code class="code--form-control">7,33,42</code></p>
1853
- </label>
1854
-
1855
- <br />
1856
-
1857
- <p class="subheading"><?php esc_html_e( 'Page Paths', 'a2-optimized-wp' ); ?></p>
1858
- <label for="excluded_page_paths">
1859
- <input name="a2opt-cache[excluded_page_paths]" type="text" id="excluded_page_paths" value="<?php echo esc_attr( A2_Optimized_Cache_Engine::$settings['excluded_page_paths'] ) ?>" class="regular-text code" />
1860
- <p class="description"><?php esc_html_e( 'A regex matching page paths that should bypass the cache.', 'a2-optimized-wp' ); ?></p>
1861
- <p><?php esc_html_e( 'Example:', 'a2-optimized-wp' ); ?> <code class="code--form-control">/^(\/|\/forums\/)$/</code></p>
1862
- </label>
1863
-
1864
- <br />
1865
-
1866
- <p class="subheading"><?php esc_html_e( 'Query Strings', 'a2-optimized-wp' ); ?></p>
1867
- <label for="excluded_query_strings">
1868
- <input name="a2opt-cache[excluded_query_strings]" type="text" id="excluded_query_strings" value="<?php echo esc_attr( A2_Optimized_Cache_Engine::$settings['excluded_query_strings'] ) ?>" class="regular-text code" />
1869
- <p class="description"><?php esc_html_e( 'A regex matching query strings that should bypass the cache.', 'a2-optimized-wp' ); ?></p>
1870
- <p><?php esc_html_e( 'Example:', 'a2-optimized-wp' ); ?> <code class="code--form-control">/^nocache$/</code></p>
1871
- <p><?php esc_html_e( 'Default if unset:', 'a2-optimized-wp' ); ?> <code class="code--form-control">/^(?!(fbclid|ref|mc_(cid|eid)|utm_(source|medium|campaign|term|content|expid)|gclid|fb_(action_ids|action_types|source)|age-verified|usqp|cn-reloaded|_ga|_ke)).+$/</code></p>
1872
- </label>
1873
-
1874
- <br />
1875
-
1876
- <p class="subheading"><?php esc_html_e( 'Cookies', 'a2-optimized-wp' ); ?></p>
1877
- <label for="excluded_cookies">
1878
- <input name="a2opt-cache[excluded_cookies]" type="text" id="excluded_cookies" value="<?php echo esc_attr( A2_Optimized_Cache_Engine::$settings['excluded_cookies'] ) ?>" class="regular-text code" />
1879
- <p class="description"><?php esc_html_e( 'A regex matching cookies that should bypass the cache.', 'a2-optimized-wp' ); ?></p>
1880
- <p><?php esc_html_e( 'Example:', 'a2-optimized-wp' ); ?> <code class="code--form-control">/^(comment_author|woocommerce_items_in_cart|wp_woocommerce_session)_?/</code></p>
1881
- <p><?php esc_html_e( 'Default if unset:', 'a2-optimized-wp' ); ?> <code class="code--form-control">/^(wp-postpass|wordpress_logged_in|comment_author)_/</code></p>
1882
- </label>
1883
- </fieldset>
1884
- </td>
1885
- </tr>
1886
- <tr valign="top">
1887
- <th scope="row">
1888
- <?php esc_html_e( 'Object Cache', 'a2-optimized-wp' ); ?>
1889
- </th>
1890
- <td>
1891
- <fieldset>
1892
- <?php if ($this->is_redis_supported()) { ?>
1893
- <p class="subheading"><?php esc_html_e( 'Object Cache Type', 'a2-optimized-wp' ); ?></p>
1894
- <label for="object_cache_server">
1895
- <?php
1896
- $object_cache_options = [
1897
- esc_html__( 'Memcached', 'a2-optimized-wp' ) => 'memcached',
1898
- esc_html__( 'Redis', 'a2-optimized-wp' ) => 'redis',
1899
- ];?>
1900
- <select name="a2_optimized_objectcache_type" id="objet_cache_server">
1901
- <option value="memcached" <?php if (get_option('a2_optimized_objectcache_type') == 'memcached') {
1902
- echo 'selected';
1903
- } ?>>Memcached</option>
1904
- <option value="redis" <?php if (get_option('a2_optimized_objectcache_type') == 'redis') {
1905
- echo 'selected';
1906
- } ?>>Redis</option>
1907
- </select>
1908
- <p class="description">
1909
- <?php
1910
- // translators: %s: ,
1911
- printf( esc_html__( 'Redis or Memcached', 'a2-optimized-wp' ), '<code class="code--form-control">,</code>' ); ?>
1912
- </p>
1913
- </label>
1914
-
1915
- <p class="subheading"><?php esc_html_e( 'Redis Server', 'a2-optimized-wp' ); ?></p>
1916
- <label for="redis_server">
1917
- <input name="a2_optimized_redis_server" type="text" id="redis_server" value="<?php echo esc_attr( get_option('a2_optimized_redis_server') ) ?>" class="regular-text" />
1918
- <p class="description">
1919
- <?php
1920
- // translators: %s: ,
1921
- printf( esc_html__( 'Address and port of the redis server for object caching', 'a2-optimized-wp' ), '<code class="code--form-control">,</code>' ); ?>
1922
- </p>
1923
- </label>
1924
- <?php } ?>
1925
- <p class="subheading"><?php esc_html_e( 'Memcached Server', 'a2-optimized-wp' ); ?></p>
1926
- <label for="memcached_server">
1927
- <input name="a2_optimized_memcached_server" type="text" id="memcached_server" value="<?php echo esc_attr( get_option('a2_optimized_memcached_server') ) ?>" class="regular-text" />
1928
- <p class="description">
1929
- <?php
1930
- // translators: %s: ,
1931
- printf( esc_html__( 'Address and port of the memcached server for object caching', 'a2-optimized-wp' ), '<code class="code--form-control">,</code>' ); ?>
1932
- </p>
1933
- </label>
1934
- </fieldset>
1935
- </td>
1936
- </tr>
1937
-
1938
- <tr valign="top">
1939
- <th scope="row">
1940
- <?php esc_html_e( 'Database Optimizations', 'a2-optimized-wp'); ?>
1941
- </th>
1942
- <td>
1943
- <fieldset>
1944
- <label for="remove_revision_posts">
1945
- <input name="a2_db_optimizations[remove_revision_posts]" type="checkbox" id="remove_revision_posts" value="1" <?php checked( '1', $db_optimization_settings['remove_revision_posts'] ); ?> />
1946
- <?php esc_html_e( 'Delete all history of post revisions', 'a2-optimized-wp' ); ?>
1947
- </label>
1948
-
1949
- <br />
1950
-
1951
- <label for="remove_trashed_posts">
1952
- <input name="a2_db_optimizations[remove_trashed_posts]" type="checkbox" id="remove_trashed_posts" value="1" <?php checked( '1', $db_optimization_settings['remove_trashed_posts'] ); ?> />
1953
- <?php esc_html_e( 'Permanently delete all posts in trash', 'a2-optimized-wp' ); ?>
1954
- </label>
1955
-
1956
- <br />
1957
-
1958
- <label for="remove_spam_comments">
1959
- <input name="a2_db_optimizations[remove_spam_comments]" type="checkbox" id="remove_spam_comments" value="1" <?php checked( '1', $db_optimization_settings['remove_spam_comments'] ); ?> />
1960
- <?php esc_html_e( 'Delete all comments marked as spam', 'a2-optimized-wp' ); ?>
1961
- </label>
1962
-
1963
- <br />
1964
-
1965
- <label for="remove_trashed_comments">
1966
- <input name="a2_db_optimizations[remove_trashed_comments]" type="checkbox" id="remove_trashed_comments" value="1" <?php checked( '1', $db_optimization_settings['remove_trashed_comments'] ); ?> />
1967
- <?php esc_html_e( 'Permanently delete all comments in trash', 'a2-optimized-wp' ); ?>
1968
- </label>
1969
-
1970
- <br />
1971
-
1972
- <label for="remove_expired_transients">
1973
- <input name="a2_db_optimizations[remove_expired_transients]" type="checkbox" id="remove_expired_transients" value="1" <?php checked( '1', $db_optimization_settings['remove_expired_transients'] ); ?> />
1974
- <?php esc_html_e( 'Delete temporary data that has expired', 'a2-optimized-wp' ); ?>
1975
- </label>
1976
-
1977
- <br />
1978
-
1979
- <label for="optimize_tables">
1980
- <input name="a2_db_optimizations[optimize_tables]" type="checkbox" id="optimize_tables" value="1" <?php checked( '1', $db_optimization_settings['optimize_tables'] ); ?> />
1981
- <?php esc_html_e( 'Perform optimizations on all database tables', 'a2-optimized-wp' ); ?>
1982
- </label>
1983
-
1984
- </fieldset>
1985
- </td>
1986
- </tr>
1987
-
1988
- </table>
1989
-
1990
- <p class="submit">
1991
- <?php wp_nonce_field( 'a2opt-cache-save', 'a2opt-cache-nonce' ); ?>
1992
- <input type="submit" class="button-secondary" value="<?php esc_html_e( 'Save Changes', 'a2-optimized-wp' ); ?>" />
1993
- <input name="a2opt-cache[clear_site_cache_on_saved_settings]" type="submit" class="button-primary" value="<?php esc_html_e( 'Save Changes and Clear Site Cache', 'a2-optimized-wp' ); ?>" />
1994
- <input name="a2opt-cache[apply_db_optimizations_on_saved_settings]" type="submit" class="button-primary" value="<?php esc_html_e( 'Save Changes and Apply Database Optimizations', 'a2-optimized-wp' ); ?>" />
1995
- </p>
1996
- </form>
1997
- </div>
1998
- </div>
1999
-
2000
- </div>
2001
-
2002
- <div style="clear:both;padding:10px;"></div>
2003
- </section>
2004
- <?php
2005
- }
2006
-
2007
- /**
2008
- * Save Cache Settings
2009
- *
2010
- */
2011
- private function cache_settings_save() {
2012
- if (!current_user_can('manage_options')) {
2013
- die('Cheating eh?');
2014
- }
2015
-
2016
- if (check_admin_referer('a2opt-cache-save', 'a2opt-cache-nonce')) {
2017
- $a2opt_db_optimizations = sanitize_text_field($_REQUEST['a2_db_optimizations']);
2018
- $a2opt_cache = sanitize_text_field($_REQUEST['a2opt-cache']);
2019
- $a2_memcached_server = sanitize_text_field($_REQUEST['a2_optimized_memcached_server']);
2020
- update_option('a2opt-cache', $a2opt_cache);
2021
- update_option('a2_optimized_memcached_server', $a2_memcached_server);
2022
- $this->write_wp_config();
2023
- }
2024
- }
2025
-
2026
- /**
2027
- * Site Health View Page
2028
- *
2029
- */
2030
- private function site_health_page_html() {
2031
- $image_dir = plugins_url('/assets/images', __FILE__);
2032
- if ( ! class_exists( 'WP_Debug_Data' ) ) {
2033
- require_once ABSPATH . 'wp-admin/includes/class-wp-debug-data.php';
2034
- }
2035
-
2036
- $saved_health_items = get_option('a2opt-sitehealth-results');
2037
-
2038
- $current_site_health = null;
2039
-
2040
- if (isset($_REQUEST['view_report'])) {
2041
- foreach ($saved_health_items as $date => $item) {
2042
- if (md5($date) == $_REQUEST['view_report']) {
2043
- $current_site_health = $item;
2044
- $site_health_date = $date;
2045
- }
2046
- }
2047
- }
2048
- if (!$current_site_health) {
2049
- $WP_Debug_Data = new WP_Debug_Data();
2050
- new A2_Optimized_SiteHealth;
2051
- $info = $WP_Debug_Data::debug_data();
2052
- $current_site_health = $WP_Debug_Data::format( $info, 'debug' );
2053
- $site_health_date = date('Y-m-d H:i:s');
2054
- } ?>
2055
- <section id="a2opt-content-general">
2056
- <div class="wrap">
2057
- <div>
2058
- <div>
2059
- <div>
2060
- <div style="float:left;clear:both">
2061
- <img src="<?php echo $image_dir; ?>/a2optimized.png" style="margin-top:20px" />
2062
- </div>
2063
- <div style="float:right;">
2064
- </div>
2065
- </div>
2066
- <div style="clear:both;"></div>
2067
- </div>
2068
- </div>
2069
- <div class="tab-content">
2070
- <?php if (isset($_REQUEST['a2-page']) && $_REQUEST['a2-page'] == 'site_health_save') { ?>
2071
- <div class="notice notice-success is-dismissible"><p>Site Health Record Saved</p></div>
2072
- <?php } ?>
2073
- <?php if (isset($_REQUEST['a2-page']) && $_REQUEST['a2-page'] == 'site_health_remove') { ?>
2074
- <div class="notice notice-info is-dismissible"><p>Site Health Record Removed</p></div>
2075
- <?php } ?>
2076
- <?php if (isset($_REQUEST['view_report']) && isset($_REQUEST['a2-page'])) { ?>
2077
- <h3>Site Health Results from <?php echo $site_health_date; ?></h3>
2078
- <p><a href="admin.php?a2-page=site_health&page=A2_Optimized_Plugin_admin" class="button">Back</a></p>
2079
- <p><a href="admin.php?a2-page=site_health_remove&page=A2_Optimized_Plugin_admin&remove_report=<?php echo md5($site_health_date); ?>" class="button">Remove Report</a></p>
2080
- <?php } else { ?>
2081
- <h3>Site Health Results</h3>
2082
- <p><a href="admin.php?a2-page=site_health_save&page=A2_Optimized_Plugin_admin" class="button">Save current results</a> <a href="site-health.php?tab=debug" class="button">Back to Site Health</a></p>
2083
- <?php } ?>
2084
- <?php if (count($saved_health_items) > 0) { ?>
2085
- <p>
2086
- <strong>Saved reports</strong>
2087
- <ul>
2088
- <?php foreach ($saved_health_items as $date => $item) { ?>
2089
- <li><a href="admin.php?a2-page=site_health&page=A2_Optimized_Plugin_admin&view_report=<?php echo md5($date); ?>"><?php echo $date; ?></a></li>
2090
- <?php } ?>
2091
- </ul>
2092
- </p>
2093
- <?php } ?>
2094
- <div>
2095
- <pre>
2096
- <?php echo $current_site_health; ?>
2097
- </pre>
2098
- </div>
2099
- </div>
2100
-
2101
- </div>
2102
-
2103
- <div style="clear:both;padding:10px;"></div>
2104
- </section>
2105
- <?php
2106
- }
2107
-
2108
- /**
2109
- * Save Site Health Results
2110
- *
2111
- */
2112
- private function site_health_save() {
2113
- if (!current_user_can('manage_options')) {
2114
- die('Cheating eh?');
2115
- }
2116
-
2117
- if ( ! class_exists( 'WP_Debug_Data' ) ) {
2118
- require_once ABSPATH . 'wp-admin/includes/class-wp-debug-data.php';
2119
- }
2120
-
2121
- $existing_health = get_option('a2opt-sitehealth-results');
2122
-
2123
- if (!$existing_health) {
2124
- $existing_health = [];
2125
- }
2126
-
2127
- $WP_Debug_Data = new WP_Debug_Data();
2128
- new A2_Optimized_SiteHealth;
2129
- $info = $WP_Debug_Data::debug_data();
2130
- $current_site_health = $WP_Debug_Data::format( $info, 'debug' );
2131
-
2132
- $existing_health[date('Y-m-d H:i:s')] = $current_site_health;
2133
-
2134
- update_option('a2opt-sitehealth-results', $existing_health);
2135
- }
2136
-
2137
- /**
2138
- * Remove Site Health Results
2139
- *
2140
- */
2141
- private function site_health_remove() {
2142
- if (!current_user_can('manage_options')) {
2143
- die('Cheating eh?');
2144
- }
2145
-
2146
- $existing_health = get_option('a2opt-sitehealth-results');
2147
-
2148
- if (is_array($existing_health)) {
2149
- $index_to_remove = 0;
2150
- foreach ($existing_health as $date => $item) {
2151
- if (md5($date) == $_REQUEST['remove_report']) {
2152
- $index_to_remove = $date;
2153
- }
2154
- }
2155
- if ($index_to_remove !== 0) {
2156
- unset($existing_health[$index_to_remove]);
2157
- update_option('a2opt-sitehealth-results', $existing_health);
2158
- }
2159
- }
2160
- }
2161
-
2162
- /**
2163
- * Knowledge Base Searchbox HMTL
2164
- *
2165
- */
2166
- private function kb_searchbox_html() {
2167
- $help_link = "https://wordpress.org/support/plugin/a2-optimized-wp/";
2168
-
2169
- if (class_exists('A2_Optimized_Private_Optimizations')) {
2170
- $help_link = "https://my.a2hosting.com/submitticket.php?action=support&type=other";
2171
- };
2172
-
2173
- return <<<HTML
2174
- <div class='big-search' style="margin-top:34px" >
2175
- <div class='kb-search' >
2176
- <form method="post" action="https://www.a2hosting.com/" target="_blank" >
2177
- <div class='hiddenFields'>
2178
- <input type="hidden" name="ACT" value="47" />
2179
- <input type="hidden" name="params" value="eyJyZXF1aXJlZCI6ImtleXdvcmRzIn0">
2180
- </div>
2181
- <input type="text" id="kb-search-request" name="keywords" placeholder="Search The A2 Knowledge Base">
2182
- <button class='btn btn-success' type='submit'>Search</button>
2183
- <h3><a href='{$help_link}' target='_blank'>Questions, comments, concerns?</a></h3>
2184
- </form>
2185
- </div>
2186
- </div>
2187
- HTML;
2188
- }
2189
-
2190
- /**
2191
- * Get a2 token from transients
2192
- */
2193
- private function get_a2_token($slug) {
2194
- return get_transient('a2_token-' . $slug);
2195
- }
2196
-
2197
- /**
2198
- * Set a2 token in transients
2199
- */
2200
- private function set_a2_token($slug) {
2201
- $wp_salt = wp_salt('nonce');
2202
- $token = md5(time() . $wp_salt . $slug);
2203
- set_transient('a2_token-' . $slug, $token, 180);
2204
-
2205
- return $token;
2206
- }
2207
-
2208
- /**
2209
- * Get the status of the plugin
2210
- */
2211
- public function get_plugin_status() {
2212
- $thisclass = $this;
2213
-
2214
- $opts = new A2_Optimized_Optimizations($thisclass);
2215
- $this->advanced_optimizations = $opts->get_advanced();
2216
- $this->optimizations = $opts->get_optimizations();
2217
- $this->plugin_list = get_plugins();
2218
-
2219
- $url_token = false;
2220
-
2221
- if (isset($_GET['a2_token'])) {
2222
- $url_token = sanitize_text_field($_GET['a2_token']);
2223
- }
2224
-
2225
- if (isset($_GET['disable_optimization']) && $url_token) {
2226
- $hash = '';
2227
-
2228
- $optimization = sanitize_text_field($_GET['disable_optimization']);
2229
-
2230
- $a2_token = $this->get_a2_token($optimization);
2231
- if ($a2_token && $a2_token == $url_token) {
2232
- if (isset($this->optimizations[$optimization])) {
2233
- $this->optimizations[$optimization]['disable']($optimization);
2234
- }
2235
-
2236
- if (isset($this->advanced_optimizations[$optimization])) {
2237
- $this->advanced_optimizations[$optimization]['disable']($optimization);
2238
- $hash = '#optimization-advanced-tab';
2239
- }
2240
- } else {
2241
- $hash = '&msg=token';
2242
- }
2243
-
2244
- echo <<<JAVASCRIPT
2245
- <script type="text/javascript">
2246
- window.location = 'admin.php?page=A2_Optimized_Plugin_admin{$hash}';
2247
- </script>
2248
- JAVASCRIPT;
2249
- exit();
2250
- }
2251
-
2252
- if (isset($_GET['enable_optimization']) && $url_token) {
2253
- $hash = '';
2254
-
2255
- $optimization = sanitize_text_field($_GET['enable_optimization']);
2256
-
2257
- $a2_token = $this->get_a2_token($optimization);
2258
- if ($a2_token && $a2_token == $url_token) {
2259
- if (isset($this->optimizations[$optimization])) {
2260
- $this->optimizations[$optimization]['enable']($optimization);
2261
- }
2262
-
2263
- if (isset($this->advanced_optimizations[$optimization])) {
2264
- $this->advanced_optimizations[$optimization]['enable']($optimization);
2265
- $hash = '#optimization-advanced-tab';
2266
- }
2267
- } else {
2268
- $hash = '&msg=token';
2269
- }
2270
-
2271
- echo <<<JAVASCRIPT
2272
- <script type="text/javascript">
2273
- window.location = 'admin.php?page=A2_Optimized_Plugin_admin{$hash}';
2274
- </script>
2275
- JAVASCRIPT;
2276
- exit();
2277
- }
2278
-
2279
- if (isset($_GET['apply_divi_settings']) && $url_token) {
2280
- $this->optimizations['minify']['disable']('minify');
2281
- $this->optimizations['css_minify']['disable']('css_minify');
2282
- $this->optimizations['js_minify']['disable']('js_minify');
2283
-
2284
- echo <<<JAVASCRIPT
2285
- <script type="text/javascript">
2286
- window.location = 'admin.php?page=A2_Optimized_Plugin_admin';
2287
- </script>
2288
- JAVASCRIPT;
2289
- exit();
2290
- }
2291
-
2292
- ini_set('disable_functions', '');
2293
-
2294
- require_once ABSPATH . 'wp-admin/includes/plugin.php';
2295
- require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
2296
-
2297
- $plugins_url = plugins_url();
2298
- $plugins_url = explode('/', $plugins_url);
2299
- array_shift($plugins_url);
2300
- array_shift($plugins_url);
2301
- array_shift($plugins_url);
2302
- $this->plugin_dir = ABSPATH . implode('/', $plugins_url);
2303
-
2304
- $this->plugins_url = plugins_url();
2305
-
2306
- validate_active_plugins();
2307
-
2308
- $this->set_install_status('plugins', $this->plugin_list);
2309
- }
2310
-
2311
- /**
2312
- * A wrapper function delegating to WP add_option() but it prefixes the input $optionName
2313
- * to enforce "scoping" the options in the WP options table thereby avoiding name conflicts
2314
- * @param $optionName string defined in settings.php and set as keys of $this->optionMetaData
2315
- * @param $value mixed the new value
2316
- * @return null from delegated call to delete_option()
2317
- */
2318
- public function addOption($optionName, $value) {
2319
- $prefixedOptionName = $this->prefix($optionName); // how it is stored in DB
2320
-
2321
- return add_option($prefixedOptionName, $value);
2322
- }
2323
-
2324
- /**
2325
- * Get the prefixed version input $name suitable for storing in WP options
2326
- * Idempotent: if $optionName is already prefixed, it is not prefixed again, it is returned without change
2327
- * @param $name string option name to prefix. Defined in settings.php and set as keys of $this->optionMetaData
2328
- * @return string
2329
- */
2330
- public function prefix($name) {
2331
- $optionNamePrefix = $this->getOptionNamePrefix();
2332
- if (strpos($name, $optionNamePrefix) === 0) { // 0 but not false
2333
- return $name; // already prefixed
2334
- }
2335
-
2336
- return $optionNamePrefix . $name;
2337
- }
2338
-
2339
- public function getOptionNamePrefix() {
2340
- return get_class($this) . '_';
2341
- }
2342
-
2343
- /**
2344
- * Deactivate the plugin
2345
- * @param string $file The name of the plugin to deactivate
2346
- *
2347
- */
2348
- public function deactivate_plugin($file) {
2349
- require_once ABSPATH . 'wp-admin/includes/plugin.php';
2350
- if (is_plugin_active($file)) {
2351
- deactivate_plugins($file);
2352
- $this->clear_w3_total_cache();
2353
- }
2354
- }
2355
-
2356
- /**
2357
- * Uninstall the plugin
2358
- * @param string $file The name of the plugin to uninstall
2359
- * @param boolean $delete Delete plugin files after uninstall
2360
- *
2361
- */
2362
- public function uninstall_plugin($file, $delete = true) {
2363
- require_once ABSPATH . 'wp-admin/includes/plugin.php';
2364
- require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
2365
-
2366
- $this->deactivate_plugin($file);
2367
- uninstall_plugin($file);
2368
- if ($delete) {
2369
- delete_plugins([$file]);
2370
- }
2371
- unset($this->plugin_list[$file]);
2372
- $this->clear_w3_total_cache();
2373
- }
2374
-
2375
- /**
2376
- * Set the install status for the plugin
2377
- * @param string $name The name of the plugin
2378
- * @param string $value The status of the plugin
2379
- *
2380
- */
2381
- public function set_install_status($name, $value) {
2382
- if (!isset($this->install_status)) {
2383
- $this->install_status = new StdClass;
2384
- }
2385
- $this->install_status->{$name} = $value;
2386
- }
2387
-
2388
- /**
2389
- * Define your options meta data here as an array, where each element in the array
2390
- * @return array of key=>display-name and/or key=>array(display-name, choice1, choice2, ...)
2391
- * key: an option name for the key (this name will be given a prefix when stored in
2392
- * the database to ensure it does not conflict with other plugin options)
2393
- * value: can be one of two things:
2394
- * (1) string display name for displaying the name of the option to the user on a web page
2395
- * (2) array where the first element is a display name (as above) and the rest of
2396
- * the elements are choices of values that the user can select
2397
- * e.g.
2398
- * array(
2399
- * 'item' => 'Item:', // key => display-name
2400
- * 'rating' => array( // key => array ( display-name, choice1, choice2, ...)
2401
- * 'CanDoOperationX' => array('Can do Operation X', 'Administrator', 'Editor', 'Author', 'Contributor', 'Subscriber'),
2402
- * 'Rating:', 'Excellent', 'Good', 'Fair', 'Poor')
2403
- */
2404
- public function getOptionMetaData() {
2405
- return [];
2406
- }
2407
-
2408
- private function curl($url) {
2409
- $ch = curl_init();
2410
- curl_setopt($ch, CURLOPT_URL, $url);
2411
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
2412
- $content = curl_exec($ch);
2413
- curl_close($ch);
2414
-
2415
- return $content;
2416
- }
2417
-
2418
- /*public function get_litespeed(){
2419
- return get_option('a2_optimized_litespeed');
2420
- }*/
2421
-
2422
- /*public function set_litespeed($litespeed = true){
2423
- update_option('a2_optimized_litespeed',$litespeed);
2424
- }*/
2425
-
2426
- public function get_optimization_status(&$item, $server_info) {
2427
- if ($item != null) {
2428
- if ($this->is_a2_managed() && isset($item['hide_managed']) && $item['hide_managed'] === true) {
2429
- return;
2430
- }
2431
-
2432
- $settings_slug = $this->getSettingsSlug();
2433
-
2434
- if (isset($item['is_configured'])) {
2435
- $item['is_configured']($item);
2436
- }
2437
- $active_color = 'danger';
2438
- $active_text = 'Not Activated';
2439
- $glyph = 'exclamation-sign';
2440
- $links = [];
2441
-
2442
- $active_class = '';
2443
- if (
2444
- isset($item['plugin']) && $item['plugin'] == 'W3 Total Cache'
2445
- && (
2446
- $this->is_plugin_installed('a2-w3-total-cache/a2-w3-total-cache.php') === false
2447
- || is_plugin_active('a2-w3-total-cache/a2-w3-total-cache.php') === false
2448
- )
2449
- ) {
2450
- $active_class = 'inactive';
2451
-
2452
- return;
2453
- }
2454
-
2455
- if ($item['configured']) {
2456
- $active_color = 'success';
2457
- $active_text = 'Configured';
2458
- $glyph = 'ok';
2459
-
2460
- if (isset($item['disable'])) {
2461
- if (isset($item['remove_link']) && $item['remove_link'] == true && ($server_info->cf || $server_info->gzip || $server_info->br)) {
2462
- // skip adding "disable" link if 'remove_link' key is set and site is behind cloudflare
2463
- // used for Gzip options
2464
- } else {
2465
- $a2_token = $this->set_a2_token($item['slug']);
2466
- $links[] = ["?page=$settings_slug&amp;disable_optimization={$item['slug']}&amp;a2_token={$a2_token}", 'Disable', '_self'];
2467
- }
2468
- }
2469
- if (isset($item['settings'])) {
2470
- $links[] = ["{$item['settings']}", 'Configure', '_self'];
2471
- }
2472
-
2473
- if (isset($item['configured_links'])) {
2474
- foreach ($item['configured_links'] as $name => $link) {
2475
- if (gettype($link) == 'array') {
2476
- $links[] = [$link[0], $name, $link[1]];
2477
- } else {
2478
- $links[] = [$link, $name, '_self'];
2479
- }
2480
- }
2481
- }
2482
- } elseif (isset($item['partially_configured']) && $item['partially_configured']) {
2483
- $active_color = 'warning';
2484
- $active_text = 'Partially Configured.';
2485
- if (isset($item['partially_configured_message'])) {
2486
- $active_text .= " {$item['partially_configured_message']}";
2487
- }
2488
- $glyph = 'warning-sign';
2489
-
2490
- if (isset($item['disable'])) {
2491
- $a2_token = $this->set_a2_token($item['slug']);
2492
- $links[] = ["?page=$settings_slug&amp;disable_optimization={$item['slug']}&amp;a2_token={$a2_token}", 'Disable', '_self'];
2493
- }
2494
- if (isset($item['settings'])) {
2495
- $links[] = ["{$item['settings']}", 'Configure', '_self'];
2496
- }
2497
-
2498
- if (isset($item['partially_configured_links'])) {
2499
- foreach ($item['partially_configured_links'] as $name => $link) {
2500
- if (gettype($link) == 'array') {
2501
- $links[] = [$link[0], $name, $link[1]];
2502
- } else {
2503
- $links[] = [$link, $name, '_self'];
2504
- }
2505
- }
2506
- }
2507
- } elseif (isset($item['optional']) && $item['optional']) {
2508
- $active_color = 'warning';
2509
- $active_text = 'Optional';
2510
- $glyph = 'warning-sign';
2511
- if (isset($item['enable']) && $active_class == '') {
2512
- $action_text = 'Enable';
2513
- if (isset($item['update'])) {
2514
- $action_text = 'Update Now';
2515
- }
2516
- $a2_token = $this->set_a2_token($item['slug']);
2517
- $links[] = ["?page=$settings_slug&amp;enable_optimization={$item['slug']}&amp;a2_token={$a2_token}", $action_text, '_self'];
2518
- }
2519
-
2520
- if (isset($item['not_configured_links'])) {
2521
- foreach ($item['not_configured_links'] as $name => $link) {
2522
- if (gettype($link) == 'array') {
2523
- $links[] = [$link[0], $name, $link[1]];
2524
- } else {
2525
- $links[] = [$link, $name, '_self'];
2526
- }
2527
- }
2528
- }
2529
- } else {
2530
- if (isset($item['enable']) && $active_class == '') {
2531
- $a2_token = $this->set_a2_token($item['slug']);
2532
- $links[] = ["?page=$settings_slug&amp;enable_optimization={$item['slug']}&amp;a2_token={$a2_token}", 'Enable', '_self'];
2533
- }
2534
-
2535
- if (isset($item['not_configured_links'])) {
2536
- foreach ($item['not_configured_links'] as $name => $link) {
2537
- if (gettype($link) == 'array') {
2538
- $links[] = [$link[0], $name, $link[1]];
2539
- } else {
2540
- $links[] = [$link, $name, '_self'];
2541
- }
2542
- }
2543
- }
2544
- }
2545
- if (isset($item['kb'])) {
2546
- $links[] = [$item['kb'], 'Learn More', '_blank'];
2547
- }
2548
- $link_html = '';
2549
- foreach ($links as $i => $link) {
2550
- if (isset($link[0]) && isset($link[1]) && isset($link[2])) {
2551
- $link_html .= <<<HTML
2552
- <a href="{$link[0]}" target="{$link[2]}">{$link[1]}</a> |
2553
- HTML;
2554
- }
2555
- }
2556
-
2557
- $premium = '';
2558
- if (isset($item['premium'])) {
2559
- $premium = '<div style="float:right;padding-right:10px"><a href="https://www.a2hosting.com/wordpress-hosting?utm_source=A2%20Optimized&utm_medium=Referral&utm_campaign=A2%20Optimized" target="_blank" class="a2-exclusive"></a></div>';
2560
- }
2561
-
2562
- $description = $item['description'];
2563
- if (isset($item['last_updated']) && $item['last_updated']) {
2564
- $description .= 'Last Updated: ';
2565
- if (get_option('a2_updated_' . $item['slug'])) {
2566
- $description .= get_option('a2_updated_' . $item['slug']);
2567
- } else {
2568
- $description .= 'Never';
2569
- }
2570
- }
2571
-
2572
- $link_html = rtrim($link_html, '|');
2573
-
2574
- return <<<HTML
2575
- <div class="optimization-item {$active_class} {$item['slug']}">
2576
- <div class="optimization-item-one" >
2577
- <span class="glyphicon glyphicon-{$glyph}"></span>
2578
- </div>
2579
- <div class="optimization-item-two">
2580
- <b>{$item['name']}</b><br>
2581
- <span class="{$active_color}">{$active_text}</span>
2582
- </div>
2583
- {$premium}
2584
- <div class="optimization-item-three">
2585
- <p>{$description}</p>
2586
- </div>
2587
- <div class="optimization-item-four">
2588
- {$link_html}
2589
- </div>
2590
- </div>
2591
- HTML;
2592
- }
2593
-
2594
- return true;
2595
- }
2596
-
2597
- /**
2598
- * Display the warnings for the plugin
2599
- *
2600
- * @return array $warnings
2601
- *
2602
- */
2603
- private function warnings() {
2604
- $num_warnings = 0;
2605
-
2606
- $opts = new A2_Optimized_Optimizations($this);
2607
- $warnings = $opts->get_warnings();
2608
-
2609
- $warning_html = '';
2610
-
2611
- foreach ($warnings as $type => $warning_set) {
2612
- switch ($type) {
2613
- case 'Bad WP Options':
2614
- foreach ($warning_set as $option_name => $warning) {
2615
- $warn = false;
2616
- $value = get_option($option_name);
2617
- switch ($warning['type']) {
2618
- case 'numeric':
2619
- switch ($warning['threshold_type']) {
2620
- case '>':
2621
- if ($value > $warning['threshold']) {
2622
- $warning_html .= $this->warning_display($warning);
2623
- $num_warnings++;
2624
- }
2625
-
2626
- break;
2627
- case '<':
2628
- if ($value < $warning['threshold']) {
2629
- $warning_html .= $this->warning_display($warning);
2630
- $num_warnings++;
2631
- }
2632
-
2633
- break;
2634
- case '=':
2635
- if ($value == $warning['threshold']) {
2636
- $warning_html .= $this->warning_display($warning);
2637
- $num_warnings++;
2638
- }
2639
-
2640
- break;
2641
- }
2642
-
2643
- break;
2644
- case 'text':
2645
- switch ($warning['threshold_type']) {
2646
- case '=':
2647
- if ($value == $warning['threshold']) {
2648
- $warning_html .= $this->warning_display($warning);
2649
- $num_warnings++;
2650
- }
2651
-
2652
- break;
2653
- case '!=':
2654
- if ($value != $warning['threshold']) {
2655
- $warning_html .= $this->warning_display($warning);
2656
- $num_warnings++;
2657
- }
2658
-
2659
- break;
2660
- }
2661
-
2662
- break;
2663
- case 'array_count':
2664
- switch ($warning['threshold_type']) {
2665
- case '>':
2666
- if (is_array($value) && count($value) > $warning['threshold']) {
2667
- $warning_html .= $this->warning_display($warning);
2668
- $num_warnings++;
2669
- }
2670
-
2671
- break;
2672
- }
2673
-
2674
- break;
2675
- }
2676
- }
2677
-
2678
- break;
2679
- case 'Advanced Warnings':
2680
- foreach ($warning_set as $name => $warning) {
2681
- if ($warning['is_warning']()) {
2682
- $warning_html .= $this->warning_display($warning);
2683
- $num_warnings++;
2684
- }
2685
- }
2686
-
2687
- break;
2688
- case 'Bad Plugins':
2689
- foreach ($warning_set as $plugin_folder => $warning) {
2690
- $warn = false;
2691
- }
2692
- }
2693
- }
2694
-
2695
- $warn = false;
2696
- $plugins = $this->get_plugins();
2697
- foreach ($plugins as $file => $plugin) {
2698
- if (!is_plugin_active($file)) {
2699
- $plugin['file'] = $file;
2700
- $warning_html .= $this->plugin_not_active_warning($plugin);
2701
- $num_warnings++;
2702
- }
2703
- }
2704
-
2705
- return [$warning_html, $num_warnings];
2706
- }
2707
-
2708
- /**
2709
- * Warning display for plugin
2710
- * @param string $warning The warning for installing or updating plugin
2711
- *
2712
- * @return markup HTML the formatted HTML to display plugin warning on web page
2713
- *
2714
- */
2715
- private function warning_display($warning) {
2716
- return <<<HTML
2717
- <div class="optimization-item">
2718
- <div style="float:left;width:44px;font-size:36px">
2719
- <span class="glyphicon glyphicon-exclamation-sign"></span>
2720
- </div>
2721
- <div style="float:left;">
2722
- <b>{$warning['title']}</b><br>
2723
- </div>
2724
- <div style="clear:both;">
2725
- <p>{$warning['description']}</p>
2726
- </div>
2727
- <div>
2728
- <a href="{$warning['config_url']}" >Configure</a>
2729
- </div>
2730
- </div>
2731
- HTML;
2732
- }
2733
-
2734
- /*
2735
- public function plugin_list(){
2736
- //Name,PluginURI,Version,Description,Author,AuthorURI,TextDomain,DomainPath,Network,Title,AuthorName
2737
-
2738
- $string = "";
2739
- include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
2740
-
2741
- $plugins = $this->get_plugins();
2742
- foreach($plugins as $filename=>$plugin){
2743
- $name = $plugin['Name'];
2744
- $title = $plugin['Title'];
2745
- $checked = "";
2746
- if(is_plugin_active($filename)){
2747
- $checked = "checked='checked'";
2748
- }
2749
- ob_start();
2750
- $dump = ob_get_contents();
2751
- ob_end_clean();
2752
- $string .=<<<HTML
2753
- <div class="wrap">
2754
- <span style="font-size:16pt"><input type="checkbox" $checked> $title</span> <a href="">delete</a>
2755
- {$dump}
2756
- </div>
2757
- HTML;
2758
-
2759
- }
2760
- return $string;
2761
- }*/
2762
-
2763
- /**
2764
- * Set the install status for the plugin
2765
- * @param string $plugin The name of the plugin
2766
- *
2767
- * @return markup HTML the formatted HTML to display plugin status on web page
2768
- *
2769
- */
2770
- private function plugin_not_active_warning($plugin) {
2771
- $manage = 'plugins.php?plugin_status=inactive';
2772
-
2773
- return <<<HTML
2774
- <div class="optimization-item">
2775
- <div style="float:left;width:44px;font-size:36px">
2776
- <span class="glyphicon glyphicon-exclamation-sign"></span>
2777
- </div>
2778
- <div style="float:left;">
2779
- <b>Inactive Plugin: {$plugin['Name']}</b><br>
2780
- </div>
2781
- <div style="clear:both;">
2782
- <p>Deactivated plugins should be deleted. Deactivating a plugin does not remove the plugin and its files from your website. Plugins with security flaws may still affect your site even when not active.</p>
2783
- <p>{$plugin['Description']}</p>
2784
- </div>
2785
- <div>
2786
- <a href="{$manage}" >Manage deactivated plugins</a>
2787
- </div>
2788
- </div>
2789
- HTML;
2790
- }
2791
-
2792
- /**
2793
- * Get the advanced optimizations for A2Optimized
2794
- *
2795
- * @return array @advanved_optimizations An array of optimization options
2796
- */
2797
- public function get_advanced_optimizations() {
2798
- return $this->advanced_optimizations;
2799
- }
2800
-
2801
- /**
2802
- * Set the lockdown status for the plugin
2803
- * @param boolean $lockdown Lockdown enabled or disabled
2804
- *
2805
- */
2806
- public function set_lockdown($lockdown = true) {
2807
- if ($lockdown == false) {
2808
- delete_option('a2_optimized_lockdown');
2809
- } else {
2810
- update_option('a2_optimized_lockdown', $lockdown);
2811
- }
2812
- }
2813
-
2814
- public function set_nomods($lockdown = true) {
2815
- if ($lockdown == false) {
2816
- delete_option('a2_optimized_nomods');
2817
- } else {
2818
- update_option('a2_optimized_nomods', $lockdown);
2819
- }
2820
- }
2821
-
2822
- /**
2823
- * Set the install status for the plugin
2824
- * @param boolean $deny Deny direct access option
2825
- *
2826
- */
2827
- public function set_deny_direct($deny = true) {
2828
- if ($deny == false) {
2829
- delete_option('a2_optimized_deny_direct');
2830
- } else {
2831
- update_option('a2_optimized_deny_direct', $deny);
2832
- }
2833
- }
2834
-
2835
- /**
2836
- * Write the config options
2837
- *
2838
- */
2839
- public function write_wp_config() {
2840
- $lockdown = $this->get_lockdown();
2841
- $nomods = $this->get_nomods();
2842
- $obj_server = $this->get_memcached_server();
2843
- $backup_filename = 'wp-config.bak-a2.php';
2844
- $error_message = '<div class="notice notice-error"><p>Unable to write to ' . ABSPATH . 'wp-config.php. Please check file permissions.</p><p><a href="' . admin_url('admin.php?page=A2_Optimized_Plugin_admin') . '">Back to A2 Optimized</a></p></div>';
2845
-
2846
- if (!file_exists(ABSPATH . 'wp-config.php')) {
2847
- echo $error_message;
2848
- exit;
2849
- }
2850
-
2851
- touch(ABSPATH . 'wp-config.php');
2852
- copy(ABSPATH . 'wp-config.php', ABSPATH . $backup_filename);
2853
-
2854
- $config_hash = sha1(file_get_contents(ABSPATH . 'wp-config.php'));
2855
- $backup_config_hash = sha1(file_get_contents(ABSPATH . $backup_filename));
2856
- if ($config_hash != $backup_config_hash || filesize(ABSPATH . $backup_filename) == 0) {
2857
- echo $error_message;
2858
- exit;
2859
- }
2860
-
2861
- $a2_config = <<<PHP
2862
-
2863
- // BEGIN A2 CONFIG
2864
-
2865
- PHP;
2866
-
2867
- if ($lockdown) {
2868
- $a2_config .= <<<PHP
2869
-
2870
- define('DISALLOW_FILE_EDIT', true);
2871
-
2872
- PHP;
2873
- }
2874
-
2875
- if ($nomods) {
2876
- $a2_config .= <<<PHP
2877
-
2878
- define('DISALLOW_FILE_MODS', true);
2879
-
2880
- PHP;
2881
- }
2882
-
2883
- if ($obj_server) {
2884
- $a2_config .= <<<PHP
2885
-
2886
- define('MEMCACHED_SERVERS', array('default' => array('{$obj_server}')));
2887
-
2888
- PHP;
2889
- }
2890
-
2891
- $a2_config .= <<<PHP
2892
- // END A2 CONFIG
2893
- PHP;
2894
-
2895
- $wpconfig = file_get_contents(ABSPATH . 'wp-config.php');
2896
- $pattern = "/[\r\n]*[\/][\/] BEGIN A2 CONFIG.*[\/][\/] END A2 CONFIG[\r\n]*/msU";
2897
- $wpconfig = preg_replace($pattern, '', $wpconfig);
2898
-
2899
- $wpconfig = str_replace('<?php', "<?php{$a2_config}", $wpconfig);
2900
-
2901
- //Write the rules to .htaccess
2902
- $fh = fopen(ABSPATH . 'wp-config.php', 'w+');
2903
- fwrite($fh, $wpconfig);
2904
- fclose($fh);
2905
-
2906
- $updated_config_hash = sha1(file_get_contents(ABSPATH . 'wp-config.php'));
2907
- if ($updated_config_hash != sha1($wpconfig) || filesize(ABSPATH . 'wp-config.php') == 0) {
2908
- copy(ABSPATH . $backup_filename, ABSPATH . 'wp-config.php');
2909
- echo $error_message;
2910
- exit;
2911
- }
2912
- }
2913
-
2914
- /**
2915
- * Check the theme lockdown option
2916
- *
2917
- */
2918
- public function get_lockdown() {
2919
- return get_option('a2_optimized_lockdown');
2920
- }
2921
-
2922
- /**
2923
- * Check if the theme has a no modication flag
2924
- *
2925
- */
2926
- public function get_nomods() {
2927
- return get_option('a2_optimized_nomods');
2928
- }
2929
-
2930
- /**
2931
- * Check if there is a memcached server set
2932
- *
2933
- */
2934
- public function get_memcached_server() {
2935
- return get_option('a2_optimized_memcached_server');
2936
- }
2937
-
2938
- /**
2939
- * Write WP changes to the .htaccess file
2940
- *
2941
- */
2942
- public function write_htaccess() {
2943
- //make sure .htaccess exists
2944
- touch(ABSPATH . '.htaccess');
2945
- touch(ABSPATH . '404.shtml');
2946
- touch(ABSPATH . '403.shtml');
2947
-
2948
- //make sure it is writable by owner and readable by everybody
2949
- chmod(ABSPATH . '.htaccess', 0644);
2950
-
2951
- $home_path = explode('/', str_replace(['http://', 'https://'], '', home_url()), 2);
2952
-
2953
- if (!isset($home_path[1]) || $home_path[1] == '') {
2954
- $home_path = '/';
2955
- } else {
2956
- $home_path = "/{$home_path[1]}/";
2957
- }
2958
-
2959
- $a2hardening = '';
2960
-
2961
- if ($this->get_deny_direct()) {
2962
- //Append the new rules to .htaccess
2963
-
2964
- //get the path to the WordPress install - nvm
2965
- //$rewrite_base = "/".trim(explode('/',str_replace(array('https://','http://'),'',site_url()),2)[1],"/")."/";
2966
-
2967
- $a2hardening = <<<APACHE
2968
-
2969
- # BEGIN WordPress Hardening
2970
- <FilesMatch "^.*(error_log|wp-config\.php|php.ini|\.[hH][tT][aApP].*)$">
2971
- Order deny,allow
2972
- Deny from all
2973
- </FilesMatch>
2974
- <IfModule mod_rewrite.c>
2975
- RewriteBase {$home_path}
2976
- RewriteRule ^wp-admin/includes/ - [F,L]
2977
- RewriteRule !^wp-includes/ - [S=3]
2978
- RewriteRule ^wp-includes/[^/]+\.php$ - [F,L]
2979
- RewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F,L]
2980
- RewriteRule ^wp-includes/theme-compat/ - [F,L]
2981
- RewriteRule ^wp-config\.php - [F,L]
2982
- RewriteRule ^php\.ini - [F,L]
2983
- RewriteRule \.htaccess - [F,L]
2984
- RewriteCond %{REQUEST_METHOD} POST
2985
- RewriteCond %{REQUEST_URI} .wp-comments-post.php*
2986
- RewriteCond %{HTTP_REFERER} !.*{$_SERVER['HTTP_HOST']}.* [OR]
2987
- RewriteCond %{HTTP_USER_AGENT} ^$
2988
- RewriteRule (.*) - [F,L]
2989
- </IfModule>
2990
- # END WordPress Hardening
2991
- APACHE;
2992
- }
2993
-
2994
- $litespeed = '';
2995
-
2996
- $htaccess = file_get_contents(ABSPATH . '.htaccess');
2997
-
2998
- $pattern = "/[\r\n]*# BEGIN WordPress Hardening.*# END WordPress Hardening[\r\n]*/msiU";
2999
- $htaccess = preg_replace($pattern, '', $htaccess);
3000
-
3001
- $htaccess = <<<HTACCESS
3002
- $litespeed
3003
- $a2hardening
3004
- $htaccess
3005
- HTACCESS;
3006
-
3007
- //Write the rules to .htaccess
3008
- $fp = fopen(ABSPATH . '.htaccess', 'c');
3009
-
3010
- if (flock($fp, LOCK_EX)) {
3011
- ftruncate($fp, 0); // truncate file
3012
- fwrite($fp, $htaccess);
3013
- fflush($fp); // flush output before releasing the lock
3014
- flock($fp, LOCK_UN); // release the lock
3015
- } else {
3016
- //no file lock :(
3017
- }
3018
- }
3019
-
3020
- public function get_deny_direct() {
3021
- return get_option('a2_optimized_deny_direct');
3022
- }
3023
-
3024
- /**
3025
- * A wrapper function delegating to WP delete_option() but it prefixes the input $optionName
3026
- * to enforce "scoping" the options in the WP options table thereby avoiding name conflicts
3027
- * @param $optionName string defined in settings.php and set as keys of $this->optionMetaData
3028
- * @return bool from delegated call to delete_option()
3029
- */
3030
- public function deleteOption($optionName) {
3031
- $prefixedOptionName = $this->prefix($optionName); // how it is stored in DB
3032
-
3033
- return delete_option($prefixedOptionName);
3034
- }
3035
-
3036
- /**
3037
- * A wrapper function delegating to WP add_option() but it prefixes the input $optionName
3038
- * to enforce "scoping" the options in the WP options table thereby avoiding name conflicts
3039
- * @param $optionName string defined in settings.php and set as keys of $this->optionMetaData
3040
- * @param $value mixed the new value
3041
- * @return null from delegated call to delete_option()
3042
- */
3043
- public function updateOption($optionName, $value) {
3044
- $prefixedOptionName = $this->prefix($optionName); // how it is stored in DB
3045
-
3046
- return update_option($prefixedOptionName, $value);
3047
- }
3048
-
3049
- /**
3050
- * Checks if a particular user has a role.
3051
- * Returns true if a match was found.
3052
- *
3053
- * @param string $role Role name.
3054
- * @param int $user_id (Optional) The ID of a user. Defaults to the current user.
3055
- * @return bool
3056
- */
3057
- public function checkUserRole($role, $user_id = null) {
3058
- if (is_numeric($user_id)) {
3059
- $user = get_userdata($user_id);
3060
- } else {
3061
- $user = wp_get_current_user();
3062
- }
3063
-
3064
- return empty($user) ? false : in_array($role, (array)$user->roles);
3065
- }
3066
-
3067
- /**
3068
- * A wrapper function delegating to WP get_option() but it prefixes the input $optionName
3069
- * to enforce "scoping" the options in the WP options table thereby avoiding name conflicts
3070
- * @param $optionName string defined in settings.php and set as keys of $this->optionMetaData
3071
- * @param $default string default value to return if the option is not set
3072
- * @return string the value from delegated call to get_option(), or optional default value
3073
- * if option is not set.
3074
- */
3075
- public function getOption($optionName, $default = null) {
3076
- $prefixedOptionName = $this->prefix($optionName); // how it is stored in DB
3077
- $retVal = get_option($prefixedOptionName);
3078
- if (!$retVal && $default) {
3079
- $retVal = $default;
3080
- }
3081
-
3082
- return $retVal;
3083
- }
3084
-
3085
- /**
3086
- * @param $roleName string a standard WP role name like 'Administrator'
3087
- * @return bool
3088
- */
3089
- public function isUserRoleEqualOrBetterThan($roleName) {
3090
- if ('Anyone' == $roleName) {
3091
- return true;
3092
- }
3093
- $capability = $this->roleToCapability($roleName);
3094
-
3095
- return $this->checkUserCapability($capability);
3096
- }
3097
-
3098
- /**
3099
- * Given a WP role name, return a WP capability which only that role and roles above it have
3100
- * http://codex.wordpress.org/Roles_and_Capabilities
3101
- * @param $roleName
3102
- * @return string a WP capability or '' if unknown input role
3103
- */
3104
- protected function roleToCapability($roleName) {
3105
- switch ($roleName) {
3106
- case 'Super Admin':
3107
- return 'manage_options';
3108
- case 'Administrator':
3109
- return 'manage_options';
3110
- case 'Editor':
3111
- return 'publish_pages';
3112
- case 'Author':
3113
- return 'publish_posts';
3114
- case 'Contributor':
3115
- return 'edit_posts';
3116
- case 'Subscriber':
3117
- return 'read';
3118
- case 'Anyone':
3119
- return 'read';
3120
- }
3121
-
3122
- return '';
3123
- }
3124
-
3125
- /**
3126
- * Checks if a particular user has a given capability without calling current_user_can.
3127
- * Returns true if a match was found.
3128
- *
3129
- * @param string $capability Capability name.
3130
- * @param int $user_id (Optional) The ID of a user. Defaults to the current user.
3131
- * @return bool
3132
- */
3133
- public function checkUserCapability($capability, $user_id = null) {
3134
- if (!is_numeric($user_id)) {
3135
- $user = wp_get_current_user();
3136
- } else {
3137
- $user = get_userdata($user_id);
3138
- }
3139
-
3140
- if (is_object($user)) {
3141
- $capabilities = (array)$user->allcaps;
3142
-
3143
- if (isset($capabilities[$capability])) {
3144
- return $capabilities[$capability];
3145
- }
3146
- }
3147
-
3148
- return false;
3149
- }
3150
-
3151
- /**
3152
- * Check Check for the correct a2_optimized directory
3153
- * @return boolean true|false
3154
- */
3155
- protected function is_a2() {
3156
- if (is_dir('/opt/a2-optimized')) {
3157
- return true;
3158
- }
3159
-
3160
- return false;
3161
- }
3162
-
3163
- /**
3164
- * Check to see if this is a ManagedWP install
3165
- *
3166
- * return bool
3167
- */
3168
- protected function is_a2_managed() {
3169
- return file_exists('/opt/a2-optimized/wordpress/a2managed');
3170
- }
3171
-
3172
- /**
3173
- * Check for installed plugin
3174
- * @param string $slug The plugin that we check for installation
3175
- * @return boolean true|false
3176
- */
3177
- private function is_plugin_installed($slug) {
3178
- $plugins = get_plugins();
3179
- if (array_key_exists($slug, $plugins)) {
3180
- return true;
3181
- }
3182
-
3183
- return false;
3184
- }
3185
-
3186
- /**
3187
- * Check for a valid and active w3tc plugin
3188
- * @return boolean true|false
3189
- */
3190
- private function is_valid_w3tc_installed() {
3191
- /* W3 Total Cache Offical is not valid */
3192
- if (is_plugin_active('w3-total-cache/w3-total-cache.php')) {
3193
- return false;
3194
- }
3195
-
3196
- /* W3 Total Cache Fixed < 0.9.5.x is ok */
3197
- if (is_plugin_active('w3-total-cache-fixed/w3-total-cache-fixed.php')) {
3198
- $w3tc_fixed_info = get_plugin_data('w3-total-cache-fixed/w3-total-cache-fixed.php');
3199
- if (version_compare($w3tc_fixed_info['Version'], '0.9.5.0') >= 0) {
3200
- return false;
3201
- } else {
3202
- return true;
3203
- }
3204
- }
3205
-
3206
- /* A2 Fixed W3TC is ok */
3207
- if (is_plugin_active('a2-w3-total-cache/a2-w3-total-cache.php')) {
3208
- return true;
3209
- }
3210
-
3211
- return false;
3212
- }
3213
-
3214
- public function getVersion() {
3215
- return $this->getPluginHeaderValue('Version');
3216
- }
3217
-
3218
- public function getPluginHeaderValue($key) {
3219
- // Read the string from the comment header of the main plugin file
3220
- $data = file_get_contents($this->getPluginDir() . DIRECTORY_SEPARATOR . $this->getMainPluginFileName());
3221
- $match = [];
3222
- preg_match('/' . $key . ':\s*(\S+)/', $data, $match);
3223
- if (count($match) >= 1) {
3224
- return $match[1];
3225
- }
3226
-
3227
- return null;
3228
- }
3229
-
3230
- protected function getPluginDir() {
3231
- return dirname(__FILE__);
3232
- }
3233
-
3234
- /**
3235
- * Generates a random string of lower case letters, used for Rename WP Login URL
3236
- *
3237
- * @param int $length The length of the random string
3238
- * @return string $output The random string
3239
- */
3240
- public function getRandomString($length = 4) {
3241
- $output = '';
3242
- $valid_chars = 'abcdefghijklmnopqrstuvwxyz';
3243
- // count the number of chars in the valid chars string so we know how many choices we have
3244
- $num_valid_chars = strlen($valid_chars);
3245
- // repeat the steps until we've created a string of the right length
3246
- for ($i = 0; $i < $length; $i++) {
3247
- // pick a random number from 1 up to the number of valid chars
3248
- $random_pick = mt_rand(1, $num_valid_chars);
3249
- // take the random character out of the string of valid chars
3250
- // subtract 1 from $random_pick because strings are indexed starting at 0, and we started picking at 1
3251
- $random_char = $valid_chars[$random_pick - 1];
3252
- // add the randomly-chosen char onto the end of our string so far
3253
- $output .= $random_char;
3254
- }
3255
-
3256
- return $output;
3257
- }
3258
-
3259
- /**
3260
- * Get the description for the plugin
3261
- * @return string $description The description of the plugin
3262
- */
3263
- public function get_plugin_description() {
3264
- $description = <<<HTML
3265
-
3266
- HTML;
3267
-
3268
- return $description;
3269
- }
3270
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
A2_Optimized_Plugin.php DELETED
@@ -1,859 +0,0 @@
1
- <?php
2
-
3
- /*
4
- Author: Benjamin Cool
5
- Author URI: https://www.a2hosting.com/
6
- License: GPLv2 or Later
7
- */
8
-
9
- // Prevent direct access to this file
10
- if (! defined('WPINC')) {
11
- die;
12
- }
13
-
14
- include_once('A2_Optimized_OptionsManager.php');
15
-
16
- class A2_Optimized_Plugin extends A2_Optimized_OptionsManager {
17
- const optionInstalled = '_installed';
18
- const optionVersion = '_version';
19
- private $config_pages = [
20
- 'w3tc_dashboard',
21
- 'w3tc_general',
22
- 'w3tc_pgcache',
23
- 'w3tc_minify',
24
- 'w3tc_dbcache',
25
- 'w3tc_objectcache',
26
- 'w3tc_browsercache',
27
- 'w3tc_mobile',
28
- 'w3tc_mobile',
29
- 'w3tc_referer',
30
- 'w3tc_cdn',
31
- 'w3tc_monitoring',
32
- 'w3tc_extensions',
33
- 'w3tc_install',
34
- 'w3tc_about',
35
- 'w3tc_faq',
36
- 'litespeed',
37
- 'litespeed-general',
38
- 'litespeed-cache',
39
- 'litespeed-cdn',
40
- 'litespeed-img_optm',
41
- 'litespeed-page_optm',
42
- 'litespeed-db_optm',
43
- 'litespeed-crawler',
44
- 'litespeed-toolbox'
45
- ];
46
-
47
- //list of plugins that may conflict, displays a notice on installation of these plugins
48
- private $incompatible_plugins = [
49
- 'wp-super-cache',
50
- 'wp-fastest-cache',
51
- 'wp-file-cache',
52
- 'better-wp-security',
53
- ];
54
-
55
- public function install() {
56
- // Initialize Plugin Options
57
- $this->initOptions();
58
-
59
- // Initialize DB Tables used by the plugin
60
- $this->installDatabaseTables();
61
-
62
- // Other Plugin initialization - for the plugin writer to override as needed
63
- //$this->otherInstall();
64
-
65
- // Record the installed version
66
- $this->saveInstalledVersion();
67
-
68
- // To avoid running install() more then once
69
- $this->markAsInstalled();
70
- }
71
-
72
- protected function initOptions() {
73
- $options = $this->getOptionMetaData();
74
- if (!empty($options)) {
75
- foreach ($options as $key => $arr) {
76
- if (is_array($arr) && count($arr) > 1) {
77
- $this->addOption($key, $arr[1]);
78
- }
79
- }
80
- }
81
- }
82
-
83
- public function getOptionMetaData() {
84
- // http://plugin.michael-simpson.com/?page_id=31
85
- return [
86
- //'_version' => array('Installed Version'), // Leave this one commented-out. Uncomment to test upgrades.
87
- 'recaptcha' => ['reCaptcha'],
88
- //'ATextInput' => array(__('Enter in some text', 'my-awesome-plugin')),
89
- //'CanSeeSubmitData' => array(__('Can See Submission data', 'my-awesome-plugin'),
90
- // 'Administrator', 'Editor', 'Author', 'Contributor', 'Subscriber', 'Anyone')
91
- ];
92
- }
93
-
94
- protected function installDatabaseTables() {
95
- // global $wpdb;
96
- // $tableName = $this->prefixTableName('mytable');
97
- // $wpdb->query("CREATE TABLE IF NOT EXISTS `$tableName` (
98
- // `id` INTEGER NOT NULL");
99
- }
100
-
101
- protected function saveInstalledVersion() {
102
- $this->setVersionSaved($this->getVersion());
103
- }
104
-
105
- protected function setVersionSaved($version) {
106
- return $this->updateOption(self::optionVersion, $version);
107
- }
108
-
109
- public function getVersion() {
110
- return $this->getPluginHeaderValue('Version');
111
- }
112
-
113
- public function getPluginHeaderValue($key) {
114
- // Read the string from the comment header of the main plugin file
115
- $data = file_get_contents($this->getPluginDir() . DIRECTORY_SEPARATOR . $this->getMainPluginFileName());
116
- $match = [];
117
- preg_match('/' . $key . ':\s*(\S+)/', $data, $match);
118
- if (count($match) >= 1) {
119
- return $match[1];
120
- }
121
-
122
- return null;
123
- }
124
-
125
- protected function getPluginDir() {
126
- return dirname(__FILE__);
127
- }
128
-
129
- protected function getMainPluginFileName() {
130
- return 'a2-optimized.php';
131
- }
132
-
133
- protected function markAsInstalled() {
134
- return $this->updateOption(self::optionInstalled, true);
135
- }
136
-
137
- public function uninstall() {
138
- $this->markAsUnInstalled();
139
- }
140
-
141
- protected function markAsUnInstalled() {
142
- return $this->deleteOption(self::optionInstalled);
143
- }
144
-
145
- public function activate() {
146
- touch(ABSPATH . '403.shtml');
147
- $this->write_htaccess();
148
- }
149
-
150
- public function deactivate() {
151
- //remove lines from .htaccess
152
-
153
- $htaccess = file_get_contents(ABSPATH . '.htaccess');
154
-
155
- $pattern = "/[\r\n]*# BEGIN WordPress Hardening.*# END WordPress Hardening[\r\n]*/msiU";
156
- $htaccess = preg_replace($pattern, '', $htaccess);
157
-
158
- //Write the rules to .htaccess
159
- $fp = fopen(ABSPATH . '.htaccess', 'c');
160
-
161
- if (flock($fp, LOCK_EX)) {
162
- ftruncate($fp, 0); // truncate file
163
- fwrite($fp, $htaccess);
164
- fflush($fp); // flush output before releasing the lock
165
- flock($fp, LOCK_UN); // release the lock
166
- } else {
167
- //no file lock :(
168
- }
169
-
170
- // deactivate the scheduled weekly database optimizations
171
- wp_clear_scheduled_hook('a2_execute_db_optimizations');
172
- }
173
-
174
- public function upgrade() {
175
- if (file_exists(ABSPATH . 'wp-config.php.bak.a2')) {
176
- unlink(ABSPATH . 'wp-config.php.bak.a2');
177
- }
178
- }
179
-
180
- public function update_notice() {
181
- global $code_version, $saved_version;
182
- echo<<<HTML
183
- <div class="updated">
184
- <p>
185
- HTML;
186
- _e("A2 Optimized has been Updated from {$saved_version} to {$code_version} !", 'a2-text-domain');
187
- echo<<<HTML
188
- </p>
189
- </div>
190
- HTML;
191
- }
192
-
193
- public function login_captcha() {
194
- if (file_exists('/opt/a2-optimized/wordpress/recaptchalib_v2.php') && !$this->is_a2_managed()) {
195
- include_once('/opt/a2-optimized/wordpress/recaptchalib_v2.php');
196
-
197
- $a2_recaptcha = $this->getOption('recaptcha');
198
- if ($a2_recaptcha == 1) {
199
- $captcha = a2recaptcha_get_html();
200
- echo <<<HTML
201
- <style>
202
- .g-recaptcha{
203
- position: relative;
204
- top: -6px;
205
- left: -15px;
206
- }
207
- </style>
208
-
209
- {$captcha}
210
- HTML;
211
- }
212
- }
213
- }
214
-
215
- public function comment_captcha() {
216
- if (!$this->checkUserCapability('moderate_comments', get_current_user_id())) {
217
- if (file_exists('/opt/a2-optimized/wordpress/recaptchalib_v2.php')) {
218
- include_once('/opt/a2-optimized/wordpress/recaptchalib_v2.php');
219
-
220
- $a2_recaptcha = $this->getOption('recaptcha');
221
- if ($a2_recaptcha == 1) {
222
- $captcha = a2recaptcha_get_html();
223
- echo <<<HTML
224
-
225
- {$captcha}
226
- HTML;
227
- }
228
- }
229
- }
230
- }
231
-
232
- public function captcha_authenticate($user, $username, $password) {
233
- if ($username != '' && !(defined('XMLRPC_REQUEST') && XMLRPC_REQUEST) && !$this->is_a2_managed()) {
234
- $a2_recaptcha = $this->getOption('recaptcha');
235
- if ($a2_recaptcha == 1) {
236
- if (file_exists('/opt/a2-optimized/wordpress/recaptchalib_v2.php')) {
237
- include_once('/opt/a2-optimized/wordpress/recaptchalib_v2.php');
238
- $resp = a2recaptcha_check_answer($_POST['g-recaptcha-response']);
239
-
240
- if (!empty($username)) {
241
- if (!$resp) {
242
- remove_filter('authenticate', 'wp_authenticate_username_password', 20);
243
-
244
- return new WP_Error('recaptcha_error', "<strong>The reCAPTCHA wasn't entered correctly. Please try it again.</strong>");
245
- }
246
- }
247
- }
248
- }
249
- }
250
- }
251
-
252
- public function captcha_comment_authenticate($commentdata) {
253
- if (!$this->checkUserCapability('moderate_comments', get_current_user_id()) && !(defined('XMLRPC_REQUEST') && XMLRPC_REQUEST)) {
254
- if (file_exists('/opt/a2-optimized/wordpress/recaptchalib_v2.php')) {
255
- include_once('/opt/a2-optimized/wordpress/recaptchalib_v2.php');
256
-
257
- $a2_recaptcha = $this->getOption('recaptcha');
258
- if ($a2_recaptcha == 1) {
259
- $resp = a2recaptcha_check_answer($_POST['g-recaptcha-response']);
260
-
261
- if (!empty($commentdata)) {
262
- if (!$resp) {
263
- wp_die("<strong>The reCAPTCHA wasn't entered correctly. Please use your browsers back button and try again.</strong>");
264
- }
265
- } else {
266
- wp_die('<strong>There was an error. Please try again.</strong>');
267
- }
268
- }
269
- }
270
- }
271
-
272
- return $commentdata;
273
- }
274
-
275
- public function permalink_changed() {
276
- $cookie = '';
277
- foreach ($_COOKIE as $name => $val) {
278
- $cookie .= "{$name}={$val};";
279
- }
280
- rtrim($cookie, ';');
281
- $ch = curl_init();
282
- curl_setopt($ch, CURLOPT_URL, get_admin_url() . 'admin.php?page=A2_Optimized_Plugin_admin');
283
- curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6');
284
- curl_setopt($ch, CURLOPT_TIMEOUT, 60);
285
- curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
286
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
287
- curl_setopt($ch, CURLOPT_COOKIE, $cookie);
288
- curl_setopt($ch, CURLOPT_REFERER, get_admin_url());
289
- $result = curl_exec($ch);
290
- curl_close($ch);
291
- }
292
-
293
- public function addActionsAndFilters() {
294
- add_action('permalink_structure_changed', [&$this, 'permalink_changed']);
295
-
296
- $date = date('Y-m-d');
297
- if (strpos($_SERVER['REQUEST_URI'], "login-{$date}") > 0) {
298
- add_action('template_redirect', [&$this, 'get_moved_login']);
299
- }
300
-
301
- add_filter('allow_minor_auto_core_updates', '__return_true');
302
- add_filter('auto_update_translation', '__return_true');
303
- /*add_filter( 'allow_major_auto_core_updates', '__return_true' );
304
- add_filter( 'allow_minor_auto_core_updates', '__return_true' );
305
- add_filter( 'auto_update_plugin', '__return_true' );
306
- add_filter( 'auto_update_theme', '__return_true' );
307
- add_filter( 'auto_update_translation', '__return_true' );
308
- */
309
-
310
- if (is_admin()) {
311
- add_filter('admin_init', [&$this, 'admin_init']);
312
- add_action('admin_bar_menu', [&$this, 'addAdminBar'], 8374);
313
- add_action('admin_menu', [&$this, 'addSettingsSubMenuPage']);
314
- if (defined('DISALLOW_FILE_EDIT') && DISALLOW_FILE_EDIT) {
315
- add_action('admin_menu', [&$this, 'addLockedEditor'], 100, 100);
316
- }
317
- add_action('admin_print_styles', [&$this, 'myStyleSheet']);
318
- add_action('wp_dashboard_setup', [&$this, 'dashboard_widget']);
319
- $a2_plugin_basename = plugin_basename($GLOBALS['A2_Plugin_Dir'] . '/a2-optimized.php');
320
- add_filter("plugin_action_links_{$a2_plugin_basename}", [&$this, 'plugin_settings_link']);
321
- register_setting('a2opt-cache', 'a2opt-cache', [ 'A2_Optimized_Cache', 'validate_settings' ]);
322
- register_setting('a2opt-cache', 'a2_optimized_objectcache_type');
323
- register_setting('a2opt-cache', 'a2_optimized_memcached_server', ['A2_Optimized_Cache', 'validate_object_cache' ]);
324
- register_setting('a2opt-cache', 'a2_optimized_redis_server', ['A2_Optimized_Cache', 'validate_object_cache' ]);
325
- new A2_Optimized_SiteHealth();
326
- register_setting('a2opt-cache', 'a2_db_optimizations', ['A2_Optimized_DBOptimizations', 'validate_db_optimization_settings']);
327
- add_action('admin_menu', [&$this, 'remove_admin_menu_items'], 999);
328
- }
329
-
330
- new A2_Optimized_DBOptimizations();
331
-
332
- if (get_option('A2_Optimized_Plugin_recaptcha', 0) == 1 && !is_admin()) {
333
- add_action('woocommerce_login_form', [&$this, 'login_captcha']);
334
- add_action('login_form', [&$this, 'login_captcha']);
335
- add_filter('authenticate', [&$this, 'captcha_authenticate'], 1, 3);
336
- add_action('comment_form_after_fields', [&$this, 'comment_captcha']);
337
- add_filter('preprocess_comment', [&$this, 'captcha_comment_authenticate'], 1, 3);
338
- }
339
- if ($this->is_xmlrpc_request() && get_option('a2_block_xmlrpc')) {
340
- $this->block_xmlrpc_request();
341
- add_filter('xmlrpc_methods', [&$this, 'remove_xmlrpc_methods']);
342
- }
343
- }
344
-
345
- public function remove_admin_menu_items() {
346
- if (isset($_GET) && isset($_GET['page'])) {
347
- if (!in_array($_GET['page'], $this->config_pages)) {
348
- // Only show the Litespeed Cache menu if the user has directly navigated to it
349
- remove_menu_page('litespeed');
350
- }
351
- } else {
352
- remove_menu_page('litespeed');
353
- }
354
- }
355
-
356
- public function plugin_settings_link($links) {
357
- $settings_link = '<a href="admin.php?page=A2_Optimized_Plugin_admin">Settings</a>';
358
- array_unshift($links, $settings_link);
359
-
360
- return $links;
361
- }
362
-
363
- public function get_moved_login() {
364
- wp_redirect(wp_login_url(), 302);
365
- exit();
366
- }
367
-
368
- public function myStyleSheet() {
369
- wp_enqueue_style('a2-optimized-css', plugins_url('/assets/css/style.css', __FILE__), '', $this->getVersion());
370
- }
371
-
372
- /**
373
- * Add a widget to the dashboard.
374
- *
375
- * This function is hooked into the 'wp_dashboard_setup' action below.
376
- */
377
- public function dashboard_widget() {
378
- $logo_url = plugins_url() . '/a2-optimized-wp/assets/images/a2optimized.png';
379
-
380
- wp_add_dashboard_widget(
381
- 'a2_optimized', // Widget slug.
382
- "<a href=\"admin.php?page=A2_Optimized_Plugin_admin\"><img src=\"{$logo_url}\" /></a>", // Title.
383
- [&$this, 'a2_dashboard_widget'] // Display function.
384
- );
385
-
386
- wp_add_dashboard_widget(
387
- 'a2_optimized_kb', // Widget slug.
388
- 'Have any questions? Search the A2 Hosting Knowledge Base for answers.', // Title.
389
- [&$this, 'kb_dashboard_widget'] // Display function.
390
- );
391
-
392
- //force the widget to the top of the dashboard
393
-
394
- global $wp_meta_boxes;
395
-
396
- // Get the regular dashboard widgets array
397
- // (which has our new widget already but at the end)
398
-
399
- unset($wp_meta_boxes['dashboard']['normal']['core']['wp_welcome_widget']);
400
-
401
- $normal_dashboard = $wp_meta_boxes['dashboard']['normal']['core'];
402
- // Backup and delete our new dashboard widget from the end of the array
403
- $example_widget_backup = ['a2_optimized' => $normal_dashboard['a2_optimized'], 'a2_optimized_kb' => $normal_dashboard['a2_optimized_kb']];
404
-
405
- // Merge the two arrays together so our widget is at the beginning
406
- $sorted_dashboard = array_merge($example_widget_backup, $normal_dashboard);
407
- // Save the sorted array back into the original metaboxes
408
- $wp_meta_boxes['dashboard']['normal']['core'] = $sorted_dashboard;
409
- }
410
-
411
- /**
412
- * Create the function to output the contents of our Dashboard Widget.
413
- */
414
- public function a2_dashboard_widget() {
415
- // Display whatever it is you want to show.
416
-
417
- echo <<<HTML
418
-
419
- <div style="font-size:14px">
420
- <p style="font-size:14px">A2 Optimized will automatically configure your WordPress site for speed and security.</p>
421
- <p>
422
- <a class="button button-primary" href="admin.php?page=A2_Optimized_Plugin_admin">Optimize Your Site</a>
423
- </p>
424
-
425
- <p style="font-size:14px">A2 Optimized includes these features.</p>
426
- <ul style="list-style-type:disc;list-style-position:inside">
427
- <li>Page caching</li>
428
- <li>Database caching</li>
429
- <li>CSS/JS/HTML minification</li>
430
- <li>reCAPTCHA on comment and login forms</li>
431
- <li>Move the login page</li>
432
- <li>Image compression</li>
433
- <li>Compress pages with gzip</li>
434
- </ul>
435
-
436
- <p style="font-size:14px">To learn more about the A2 Optimized WordPress plugin: read this <a target="_blank" href="http://www.a2hosting.com/kb/installable-applications/optimization-and-configuration/wordpress2/optimizing-wordpress-with-the-a2-optimized-plugin">Knowledge Base article</a></p>
437
- </div>
438
-
439
-
440
-
441
- HTML;
442
- }
443
-
444
- public function kb_dashboard_widget() {
445
- echo <<<HTML
446
- <p>
447
- <a class="button button-primary" href="http://www.a2hosting.com/kb" target="_blank">Search the Knowledge Base</a>
448
- </p>
449
- HTML;
450
- }
451
-
452
- public function locked_files_notice() {
453
- $dismiss_url = admin_url('admin.php?a2-page=dismiss_notice&a2-option=a2_notice_editinglocked&page=A2_Optimized_Plugin_admin');
454
- echo <<<HTML
455
- <div id="editing-locked" class="notice notice-success" >
456
- <p ><b style="color:#00CC00">Editing of plugin and theme files</b> in the wp-admin is <b style="color:#00CC00">disabled</b> by A2 Optimized<br>
457
- <b style="color:#00CC00">This is recommended for security reasons</b>. You can modify this setting on the <a href="admin.php?page=A2_Optimized_Plugin_admin">A2 Optimized Configuration page</a></p>
458
- <p><a href="{$dismiss_url}" class="button-primary">Don't show this again</a></p>
459
- </div>
460
- HTML;
461
- }
462
-
463
- public function not_locked_files_notice() {
464
- $dismiss_url = admin_url('admin.php?a2-page=dismiss_notice&a2-option=a2_notice_editingnotlocked&page=A2_Optimized_Plugin_admin');
465
- echo <<<HTML
466
- <div id="editing-locked" class="notice notice-error" >
467
- <p ><b style="color:red">Editing of plugin and theme files</b> in the wp-admin is <b style="color:red">enabled</b><br>
468
- <b style="color:red">This is not recommended for security reasons</b>. You can modify this setting on the <a href="admin.php?page=A2_Optimized_Plugin_admin">A2 Optimized Configuration page</a></p>
469
- <p><a href="{$dismiss_url}" class="button-primary">Don't show this again</a></p>
470
- </div>
471
- HTML;
472
- }
473
-
474
- public function divi_notice() {
475
- $current_theme = get_template();
476
- $dismiss_url = admin_url('admin.php?a2-page=dismiss_notice&a2-option=a2_notice_diviminify&page=A2_Optimized_Plugin_admin');
477
-
478
- echo <<<HTML
479
- <div id="divi-minify-notice" class="notice notice-error" >
480
- <p><strong style="color:red">Your theme, {$current_theme}, currently provides HTML/JS/CSS minification. This feature is also enabled by A2 Optimized. This may cause issues with some functionality of your theme.</strong></p>
481
- <p>You can disable HTML/JS/CSS either in your theme options or within the <a href="admin.php?page=A2_Optimized_Plugin_admin">A2 Optimized Configuration page</a></p>
482
- <p><a href="{$dismiss_url}" class="button-primary">Don't show this again</a></p>
483
-
484
- </div>
485
- HTML;
486
- }
487
-
488
- public function rwl_notice() {
489
- $rwl_page = get_option('wpseh_l01gnhdlwp');
490
- $home_page = get_home_url();
491
- $admin_url = get_admin_url();
492
-
493
- if ($a2_login_page = get_option('a2_login_page')) {//synch rwl_page and a2_login_page
494
- if ($a2_login_page != $rwl_page) {
495
- update_option('a2_login_page', $rwl_page);
496
- }
497
- } else {
498
- update_option('a2_login_page', $rwl_page);
499
- }
500
-
501
- $link = get_home_url() . '?' . $rwl_page;
502
-
503
- if (!(strpos(get_option('a2_login_bookmark', ''), $rwl_page) === 0)) {
504
- $dismiss_url = admin_url('admin.php?a2-page=dismiss_notice&a2-option=a2_login_bookmark&page=A2_Optimized_Plugin_admin');
505
- echo <<<HTML
506
- <div id="bookmark-login" class="updated" >
507
- <p>Your login page is now here: <a href="{$link}" >{$link}</a>. Bookmark this page!</p>
508
- <p><a href="{$dismiss_url}" class="button-primary">Don't show this again</a></p>
509
- </div>
510
- HTML;
511
- }
512
- }
513
-
514
- public function admin_init() {
515
- if (!$this->checkUserCapability('manage_options', get_current_user_id())) {
516
- return false;
517
- }
518
-
519
- $active_plugins = get_option('active_plugins');
520
- if (in_array('easy-hide-login/wp-hide-login.php', $active_plugins)) {
521
- if ($rwl_page = get_option('wpseh_l01gnhdlwp')) {
522
- if ($rwl_page != '') {
523
- add_action('admin_notices', [&$this, 'rwl_notice']);
524
- if ($a2_login_page = get_option('a2_login_page')) {
525
- if ($a2_login_page != $rwl_page) {
526
- update_option('a2_login_page', $rwl_page);
527
- }
528
- } else {
529
- update_option('a2_login_page', $rwl_page);
530
- }
531
- }
532
- }
533
- }
534
- if (in_array('a2-w3-total-cache/a2-w3-total-cache.php', $active_plugins)) {
535
- wp_enqueue_script('a2_functions', plugins_url('/assets/js/functions.js', __FILE__), ['jquery']);
536
- }
537
-
538
- if (isset($_GET['page']) && in_array($_GET['page'], $this->config_pages) && get_option('a2_notice_configpage') != '1') {
539
- add_action('admin_notices', [&$this, 'config_page_notice']);
540
- }
541
-
542
- if (get_template() == 'Divi') {
543
- $w3tc = $this->get_w3tc_config();
544
-
545
- if ($w3tc['minify.html.enable'] || $w3tc['minify.css.enable'] || $w3tc['minify.js.enable']) {
546
- if (get_option('a2_notice_diviminify') != '1') {
547
- add_action('admin_notices', [&$this, 'divi_notice']);
548
- }
549
- }
550
- }
551
-
552
- foreach ($active_plugins as $active_plugin) {
553
- $plugin_folder = explode('/', $active_plugin);
554
- if (in_array($plugin_folder[0], $this->incompatible_plugins) && get_option('a2_notice_incompatible_plugins') != '1') {
555
- add_action('admin_notices', [&$this, 'incompatible_plugin_notice']);
556
- }
557
- // Check for W3 Total Cache and show upgrade notice
558
- if ($plugin_folder[0] == 'w3-total-cache' && !$_GET['a2-page'] && get_option('a2_notice_w3totalcache') != '1') {
559
- add_action('admin_notices', [&$this, 'w3totalcache_plugin_notice']);
560
- }
561
- // Check for Wordfence and if WAF rules are setup correctly, show notice if not
562
- if ($plugin_folder[0] == 'wordfence' && $this->wordfence_waf_check() === false && get_option('a2_notice_wordfence_waf') != '1') {
563
- add_action('admin_notices', [&$this, 'wordfence_plugin_notice']);
564
- }
565
- }
566
-
567
- if (!(strpos($_SERVER['SCRIPT_FILENAME'], 'plugins.php') === false) && defined('DISALLOW_FILE_EDIT') && DISALLOW_FILE_EDIT) {
568
- if (get_option('a2_notice_editinglocked') != '1') {
569
- add_action('admin_notices', [&$this, 'locked_files_notice']);
570
- }
571
- } elseif (!(strpos($_SERVER['SCRIPT_FILENAME'], 'plugins.php') === false)) {
572
- if (get_option('a2_notice_editingnotlocked') != '1') {
573
- add_action('admin_notices', [&$this, 'not_locked_files_notice']);
574
- }
575
- }
576
- }
577
-
578
- /**
579
- * Puts the configuration page in the Plugins menu by default.
580
- * Override to put it elsewhere or create a set of submenus
581
- * Override with an empty implementation if you don't want a configuration page
582
- * @return void
583
- */
584
- public function addSettingsSubMenuPage() {
585
- $this->addSettingsSubMenuPageToMenu();
586
- }
587
-
588
- protected function addSettingsSubMenuPageToMenu() {
589
- $this->requireExtraPluginFiles();
590
- $displayName = $this->getPluginDisplayName();
591
- add_menu_page(
592
- $displayName,
593
- $displayName,
594
- 'manage_options',
595
- $this->getSettingsSlug(),
596
- [&$this, 'settingsPage'],
597
- null,
598
- 3
599
- );
600
- }
601
-
602
- protected function requireExtraPluginFiles() {
603
- //require_once(ABSPATH . 'wp-includes/pluggable.php');
604
- require_once(ABSPATH . 'wp-admin/includes/plugin.php');
605
- }
606
-
607
- public function getPluginDisplayName() {
608
- return 'A2 Optimized';
609
- }
610
-
611
- protected function getSettingsSlug() {
612
- return get_class($this) . '_admin';
613
- }
614
-
615
- public function addAdminBar() {
616
- $this->requireExtraPluginFiles();
617
- global $wp_admin_bar;
618
-
619
- if (current_user_can('manage_options')) {
620
- $wp_admin_bar->add_node([
621
- 'id' => 'a2-optimized-admin-bar',
622
- 'title' => 'A2 Optimized',
623
- 'href' => admin_url('admin.php?page=' . $this->getSettingsSlug())
624
- ]);
625
- }
626
- }
627
-
628
- public function addLockedEditor() {
629
- $this->requireExtraPluginFiles();
630
- add_theme_page('<span style="color:red !important">Editor Locked</span>', '<span style="color:red !important">Editor Locked</span>', 'manage_options', 'editor-locked', [&$this, 'settingsPage']);
631
- }
632
-
633
- /**
634
- * @return bool indicating if the plugin is installed already
635
- */
636
- public function isInstalled() {
637
- return $this->getOption(self::optionInstalled) == true;
638
- }
639
-
640
- protected function get_recaptcha_public_key() {
641
- if (file_exists('/opt/a2-optimized/wordpress_encoded/pk.php')) {
642
- return file_get_contents('/opt/a2-optimized/wordpress_encoded/pk.php');
643
- }
644
- if ($key = get_option('a2_recaptcha_pubkey')) {
645
- return $key;
646
- }
647
-
648
- return null;
649
- }
650
-
651
- protected function addSettingsSubMenuPageToPluginsMenu() {
652
- $this->requireExtraPluginFiles();
653
- $displayName = $this->getPluginDisplayName();
654
- add_submenu_page(
655
- 'plugins.php',
656
- $displayName,
657
- $displayName,
658
- 'manage_options',
659
- $this->getSettingsSlug(),
660
- [&$this, 'settingsPage']
661
- );
662
- }
663
-
664
- protected function addSettingsSubMenuPageToDashboard() {
665
- $this->requireExtraPluginFiles();
666
- $displayName = $this->getPluginDisplayName();
667
- add_dashboard_page(
668
- $displayName,
669
- $displayName,
670
- 'manage_options',
671
- $this->getSettingsSlug(),
672
- [&$this, 'settingsPage']
673
- );
674
- }
675
-
676
- protected function addSettingsSubMenuPageToSettingsMenu() {
677
- $this->requireExtraPluginFiles();
678
- $displayName = $this->getPluginDisplayName();
679
- add_options_page(
680
- $displayName,
681
- $displayName,
682
- 'manage_options',
683
- $this->getSettingsSlug(),
684
- [&$this, 'settingsPage']
685
- );
686
- }
687
-
688
- public function incompatible_plugin_notice() {
689
- $active_plugins = get_option('active_plugins');
690
- $plugins_arr = [];
691
- foreach ($active_plugins as $active_plugin) {
692
- $plugin_folder = explode('/', $active_plugin);
693
- if (in_array($plugin_folder[0], $this->incompatible_plugins)) {
694
- $folder = WP_PLUGIN_DIR . '/' . $active_plugin;
695
- $plugin_data = get_plugin_data($folder, false, false);
696
- $plugins_arr[] = $plugin_data['Name'];
697
- }
698
- }
699
- if (count($plugins_arr) > 1) {
700
- $plugin_output = implode(', ', $plugins_arr);
701
- } else {
702
- $plugin_output = $plugins_arr[0];
703
- }
704
- $dismiss_url = admin_url('admin.php?a2-page=dismiss_notice&a2-option=a2_notice_incompatible_plugins&page=A2_Optimized_Plugin_admin');
705
-
706
- echo <<<HTML
707
- <div class="notice notice-warning">
708
- <p class="danger">Proceed with caution: A currently active plugin, {$plugin_output} may be incompatible with A2 Optimized.</p>
709
- <p><a href="{$dismiss_url}" class="button-primary">Don't show this again</a></p>
710
- </div>
711
- HTML;
712
- }
713
-
714
- /*
715
- * XML-RPC Functions
716
- */
717
-
718
- /* Is this a xmlrpc request? */
719
- public function is_xmlrpc_request() {
720
- return defined('XMLRPC_REQUEST') && XMLRPC_REQUEST;
721
- }
722
-
723
- /* Block this xmlrpc request unless other criteria are met */
724
- private function block_xmlrpc_request() {
725
- if ($this->client_is_automattic()) {
726
- return;
727
- }
728
-
729
- if ($this->clientip_whitelisted()) {
730
- return;
731
- }
732
-
733
- if (!headers_sent()) {
734
- header('Connection: close');
735
- header('Content-Type: text/xml');
736
- header('Date: ' . date('r'));
737
- }
738
- echo '<?xml version="1.0"?><methodResponse><fault><value><struct><member><name>faultCode</name><value><int>405</int></value></member><member><name>faultString</name><value><string>XML-RPC is disabled</string></value></member></struct></value></fault></methodResponse>';
739
- exit;
740
- }
741
-
742
- /* Stop advertising we accept certain requests */
743
- public function remove_xmlrpc_methods($xml_rpc_methods) {
744
- if ($this->client_is_automattic()) {
745
- return $xml_rpc_methods;
746
- }
747
-
748
- if ($this->clientip_whitelisted()) {
749
- return $xml_rpc_methods;
750
- }
751
-
752
- unset($xml_rpc_methods['pingback.ping']); // block pingbacks
753
- unset($xml_rpc_methods['pingback.extensions.getPingbacks']); // block pingbacks
754
-
755
- return $xml_rpc_methods;
756
- }
757
-
758
- public function clientip_whitelisted() {
759
- // For future consideration
760
- return false;
761
- }
762
-
763
- /* Checks if a Automattic plugin is installed
764
- Checks if IP making request if from Automattic
765
- https://jetpack.com/support/hosting-faq/
766
- */
767
- public function client_is_automattic() {
768
- //check for jetpack / akismet / vaultpress
769
- if (
770
- !is_plugin_active('jetpack/jetpack.php')
771
- && !is_plugin_active('akismet/akismet.php')
772
- && !is_plugin_active('vaultpress/vaultpress.php')) {
773
- return false;
774
- }
775
-
776
- $ip_address = $_SERVER['REMOTE_ADDR'];
777
- if ($this->is_ip_in_range(
778
- $ip_address,
779
- [
780
- '122.248.245.244', // Jetpack
781
- '54.217.201.243', // Jetpack
782
- '54.232.116.4', // Jetpack
783
- ['195.234.108.0', '195.234.111.255'], // Jetpack
784
- ['192.0.64.1', '192.0.127.255'], // VaultPress range
785
- //array('192.0.80.0', '192.0.95.255'), // Akismet (covered by VaultPress range)
786
- //array('192.0.96.0', '192.0.111.255'), // Akismet
787
- //array('192.0.112.0', '192.0.127.255'), // Akismet
788
- ]
789
- )) {
790
- return true;
791
- }
792
-
793
- return false;
794
- }
795
-
796
- /* Use ip2long to do comparisons */
797
- public function is_ip_in_range($ip_address, $range_array) {
798
- $ip_long = ip2long($ip_address);
799
- foreach ($range_array as $item) {
800
- if (is_array($item)) {
801
- $ip_low = ip2long($item[0]);
802
- $ip_hi = ip2long($item[1]);
803
- if ($ip_long <= $ip_hi && $ip_low <= $ip_long) {
804
- return true;
805
- }
806
- } else {
807
- if ($ip_long == ip2long($item)) {
808
- return true;
809
- }
810
- }
811
- }
812
-
813
- return false;
814
- }
815
-
816
- /*
817
- * WordFence WAF Functions
818
- */
819
-
820
- public function wordfence_waf_check() {
821
- // Check if the .htaccess file has a Wordfence WAF entry
822
- $htaccess = file_get_contents(ABSPATH . '.htaccess');
823
-
824
- return strpos($htaccess, 'Wordfence WAF');
825
- }
826
-
827
- public function wordfence_plugin_notice() {
828
- $dismiss_url = admin_url('admin.php?a2-page=dismiss_notice&a2-option=a2_notice_wordfence_waf&page=A2_Optimized_Plugin_admin');
829
- echo <<<HTML
830
- <div class="notice notice-warning">
831
- <p class="danger">Wordfence is not properly configured to work with A2 Optimized. Please review the Wordfence help document below to update your Wordfence settings.</p>
832
- <p><a href="https://www.wordfence.com/help/firewall/optimizing-the-firewall/" class="button-primary" target="_blank">Optimizing The Wordfence Firewall</a></p>
833
- <p><a href="{$dismiss_url}" class="button-primary">Don't show this again</a></p>
834
- </div>
835
- HTML;
836
- }
837
-
838
- public function w3totalcache_plugin_notice() {
839
- $admin_url = admin_url('admin.php?a2-page=upgrade_wizard&page=A2_Optimized_Plugin_admin');
840
- $dismiss_url = admin_url('admin.php?a2-page=dismiss_notice&a2-option=a2_notice_w3totalcache&page=A2_Optimized_Plugin_admin');
841
- echo <<<HTML
842
- <div class="notice notice-warning">
843
- <p class="danger">We noticed you have W3 Total Cache already installed. We are not able to fully support this version of W3 Total Cache with A2 Optimized. To get the best options for optimizing your WordPress site, we can help you disable this W3 Total Cache plugin version and install a A2 Hosting supported version of W3 Total Cache in its place.</p>
844
- <p><a href="{$admin_url}" class="button-primary">Disable W3 Total Cache</a></p>
845
- <p><a href="{$dismiss_url}" class="button-primary">Don't show this again</a></p>
846
- </div>
847
- HTML;
848
- }
849
-
850
- public function config_page_notice() {
851
- $dismiss_url = admin_url('admin.php?a2-page=dismiss_notice&a2-option=a2_notice_configpage&page=A2_Optimized_Plugin_admin');
852
- echo <<<HTML
853
- <div class="notice notice-info">
854
- <p>This site has been configured using the A2 Optimized plugin. We, at A2 Hosting, have spent quite a bit of time figuring out the best set of options for this plugin; however, if you think you need to customize configuration: by all means... Continue. If you have arrived here by mistake, you may use the <a href="admin.php?page=A2_Optimized_Plugin_admin">A2 Optimized administration page to configure this plugin</a>.</p>
855
- <p><a href="{$dismiss_url}" class="button-primary">Don't show this again</a></p>
856
- </div>
857
- HTML;
858
- }
859
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
A2_Optimized_Server_Info.php DELETED
@@ -1,80 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * A2_Optimized_Server_Info
5
- * Class to get information about the server we're currently running on
6
- *
7
- **/
8
-
9
- // Prevent direct access to this file
10
- if ( ! defined( 'WPINC' ) ) {
11
- die;
12
- }
13
-
14
- class A2_Optimized_Server_Info {
15
- /* Is server behind Cloud Flare? */
16
- public $cf = false;
17
-
18
- /* Is server already gzipping files? */
19
- public $gzip = false;
20
-
21
- /* Is server using Brotli? */
22
- public $br = false;
23
-
24
- public $w3tc_config;
25
-
26
- public function __construct($w3tc) {
27
- $this->w3tc_config = $w3tc;
28
- $this->server_header_call();
29
- }
30
-
31
- /**
32
- * Makes a cURL call and loops through $encodings array to parse headers
33
- * looking for a match.
34
- * Also checks Server header for cloudflare string
35
- * Caches cURL headers in transient cache for 12 hours
36
- *
37
- **/
38
- private function server_header_call() {
39
- $encodings = array('gzip', 'br');
40
-
41
- $ch = curl_init();
42
- curl_setopt($ch, CURLOPT_URL, home_url());
43
- curl_setopt($ch, CURLOPT_HEADER, 1);
44
- curl_setopt($ch, CURLOPT_NOBODY, 1);
45
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
46
- curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
47
- curl_setopt($ch, CURLOPT_TIMEOUT, 30);
48
- curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)');
49
-
50
- foreach ($encodings as $encoding) {
51
- curl_setopt($ch, CURLOPT_ENCODING, $encoding);
52
-
53
- $header = get_transient( 'a2-server_resp2-' . $encoding );
54
-
55
- if (false === $header) {
56
- $header = curl_exec($ch);
57
- set_transient( 'a2-server_resp2-' . $encoding, $header, WEEK_IN_SECONDS );
58
- }
59
- $temp_headers = explode("\n", $header);
60
- foreach ($temp_headers as $i => $header) {
61
- $header = explode(':', $header, 2);
62
- if (isset($header[1])) {
63
- $headers[strtolower($header[0])] = $header[1];
64
- } else {
65
- $headers[strtolower($header[0])] = '';
66
- }
67
- }
68
- if (isset($headers['server']) && (strpos(strtolower($headers['server']), 'cloudflare') !== false)) {
69
- $this->cf = true;
70
- }
71
- if (isset($headers['content-encoding']) && (strpos(strtolower($headers['content-encoding']), 'gzip') !== false)) {
72
- $this->gzip = true;
73
- }
74
- if (isset($headers['content-encoding']) && (strpos(strtolower($headers['content-encoding']), 'br') !== false)) {
75
- $this->br = true;
76
- }
77
- }
78
- curl_close($ch);
79
- }
80
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
LICENSE.txt ADDED
@@ -0,0 +1,339 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ GNU GENERAL PUBLIC LICENSE
2
+ Version 2, June 1991
3
+
4
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6
+ Everyone is permitted to copy and distribute verbatim copies
7
+ of this license document, but changing it is not allowed.
8
+
9
+ Preamble
10
+
11
+ The licenses for most software are designed to take away your
12
+ freedom to share and change it. By contrast, the GNU General Frontend
13
+ License is intended to guarantee your freedom to share and change free
14
+ software--to make sure the software is free for all its users. This
15
+ General Frontend License applies to most of the Free Software
16
+ Foundation's software and to any other program whose authors commit to
17
+ using it. (Some other Free Software Foundation software is covered by
18
+ the GNU Lesser General Frontend License instead.) You can apply it to
19
+ your programs, too.
20
+
21
+ When we speak of free software, we are referring to freedom, not
22
+ price. Our General Frontend Licenses are designed to make sure that you
23
+ have the freedom to distribute copies of free software (and charge for
24
+ this service if you wish), that you receive source code or can get it
25
+ if you want it, that you can change the software or use pieces of it
26
+ in new free programs; and that you know you can do these things.
27
+
28
+ To protect your rights, we need to make restrictions that forbid
29
+ anyone to deny you these rights or to ask you to surrender the rights.
30
+ These restrictions translate to certain responsibilities for you if you
31
+ distribute copies of the software, or if you modify it.
32
+
33
+ For example, if you distribute copies of such a program, whether
34
+ gratis or for a fee, you must give the recipients all the rights that
35
+ you have. You must make sure that they, too, receive or can get the
36
+ source code. And you must show them these terms so they know their
37
+ rights.
38
+
39
+ We protect your rights with two steps: (1) copyright the software, and
40
+ (2) offer you this license which gives you legal permission to copy,
41
+ distribute and/or modify the software.
42
+
43
+ Also, for each author's protection and ours, we want to make certain
44
+ that everyone understands that there is no warranty for this free
45
+ software. If the software is modified by someone else and passed on, we
46
+ want its recipients to know that what they have is not the original, so
47
+ that any problems introduced by others will not reflect on the original
48
+ authors' reputations.
49
+
50
+ Finally, any free program is threatened constantly by software
51
+ patents. We wish to avoid the danger that redistributors of a free
52
+ program will individually obtain patent licenses, in effect making the
53
+ program proprietary. To prevent this, we have made it clear that any
54
+ patent must be licensed for everyone's free use or not licensed at all.
55
+
56
+ The precise terms and conditions for copying, distribution and
57
+ modification follow.
58
+
59
+ GNU GENERAL PUBLIC LICENSE
60
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61
+
62
+ 0. This License applies to any program or other work which contains
63
+ a notice placed by the copyright holder saying it may be distributed
64
+ under the terms of this General Frontend License. The "Program", below,
65
+ refers to any such program or work, and a "work based on the Program"
66
+ means either the Program or any derivative work under copyright law:
67
+ that is to say, a work containing the Program or a portion of it,
68
+ either verbatim or with modifications and/or translated into another
69
+ language. (Hereinafter, translation is included without limitation in
70
+ the term "modification".) Each licensee is addressed as "you".
71
+
72
+ Activities other than copying, distribution and modification are not
73
+ covered by this License; they are outside its scope. The act of
74
+ running the Program is not restricted, and the output from the Program
75
+ is covered only if its contents constitute a work based on the
76
+ Program (independent of having been made by running the Program).
77
+ Whether that is true depends on what the Program does.
78
+
79
+ 1. You may copy and distribute verbatim copies of the Program's
80
+ source code as you receive it, in any medium, provided that you
81
+ conspicuously and appropriately publish on each copy an appropriate
82
+ copyright notice and disclaimer of warranty; keep intact all the
83
+ notices that refer to this License and to the absence of any warranty;
84
+ and give any other recipients of the Program a copy of this License
85
+ along with the Program.
86
+
87
+ You may charge a fee for the physical act of transferring a copy, and
88
+ you may at your option offer warranty protection in exchange for a fee.
89
+
90
+ 2. You may modify your copy or copies of the Program or any portion
91
+ of it, thus forming a work based on the Program, and copy and
92
+ distribute such modifications or work under the terms of Section 1
93
+ above, provided that you also meet all of these conditions:
94
+
95
+ a) You must cause the modified files to carry prominent notices
96
+ stating that you changed the files and the date of any change.
97
+
98
+ b) You must cause any work that you distribute or publish, that in
99
+ whole or in part contains or is derived from the Program or any
100
+ part thereof, to be licensed as a whole at no charge to all third
101
+ parties under the terms of this License.
102
+
103
+ c) If the modified program normally reads commands interactively
104
+ when run, you must cause it, when started running for such
105
+ interactive use in the most ordinary way, to print or display an
106
+ announcement including an appropriate copyright notice and a
107
+ notice that there is no warranty (or else, saying that you provide
108
+ a warranty) and that users may redistribute the program under
109
+ these conditions, and telling the user how to view a copy of this
110
+ License. (Exception: if the Program itself is interactive but
111
+ does not normally print such an announcement, your work based on
112
+ the Program is not required to print an announcement.)
113
+
114
+ These requirements apply to the modified work as a whole. If
115
+ identifiable sections of that work are not derived from the Program,
116
+ and can be reasonably considered independent and separate works in
117
+ themselves, then this License, and its terms, do not apply to those
118
+ sections when you distribute them as separate works. But when you
119
+ distribute the same sections as part of a whole which is a work based
120
+ on the Program, the distribution of the whole must be on the terms of
121
+ this License, whose permissions for other licensees extend to the
122
+ entire whole, and thus to each and every part regardless of who wrote it.
123
+
124
+ Thus, it is not the intent of this section to claim rights or contest
125
+ your rights to work written entirely by you; rather, the intent is to
126
+ exercise the right to control the distribution of derivative or
127
+ collective works based on the Program.
128
+
129
+ In addition, mere aggregation of another work not based on the Program
130
+ with the Program (or with a work based on the Program) on a volume of
131
+ a storage or distribution medium does not bring the other work under
132
+ the scope of this License.
133
+
134
+ 3. You may copy and distribute the Program (or a work based on it,
135
+ under Section 2) in object code or executable form under the terms of
136
+ Sections 1 and 2 above provided that you also do one of the following:
137
+
138
+ a) Accompany it with the complete corresponding machine-readable
139
+ source code, which must be distributed under the terms of Sections
140
+ 1 and 2 above on a medium customarily used for software interchange; or,
141
+
142
+ b) Accompany it with a written offer, valid for at least three
143
+ years, to give any third party, for a charge no more than your
144
+ cost of physically performing source distribution, a complete
145
+ machine-readable copy of the corresponding source code, to be
146
+ distributed under the terms of Sections 1 and 2 above on a medium
147
+ customarily used for software interchange; or,
148
+
149
+ c) Accompany it with the information you received as to the offer
150
+ to distribute corresponding source code. (This alternative is
151
+ allowed only for noncommercial distribution and only if you
152
+ received the program in object code or executable form with such
153
+ an offer, in accord with Subsection b above.)
154
+
155
+ The source code for a work means the preferred form of the work for
156
+ making modifications to it. For an executable work, complete source
157
+ code means all the source code for all modules it contains, plus any
158
+ associated interface definition files, plus the scripts used to
159
+ control compilation and installation of the executable. However, as a
160
+ special exception, the source code distributed need not include
161
+ anything that is normally distributed (in either source or binary
162
+ form) with the major components (compiler, kernel, and so on) of the
163
+ operating system on which the executable runs, unless that component
164
+ itself accompanies the executable.
165
+
166
+ If distribution of executable or object code is made by offering
167
+ access to copy from a designated place, then offering equivalent
168
+ access to copy the source code from the same place counts as
169
+ distribution of the source code, even though third parties are not
170
+ compelled to copy the source along with the object code.
171
+
172
+ 4. You may not copy, modify, sublicense, or distribute the Program
173
+ except as expressly provided under this License. Any attempt
174
+ otherwise to copy, modify, sublicense or distribute the Program is
175
+ void, and will automatically terminate your rights under this License.
176
+ However, parties who have received copies, or rights, from you under
177
+ this License will not have their licenses terminated so long as such
178
+ parties remain in full compliance.
179
+
180
+ 5. You are not required to accept this License, since you have not
181
+ signed it. However, nothing else grants you permission to modify or
182
+ distribute the Program or its derivative works. These actions are
183
+ prohibited by law if you do not accept this License. Therefore, by
184
+ modifying or distributing the Program (or any work based on the
185
+ Program), you indicate your acceptance of this License to do so, and
186
+ all its terms and conditions for copying, distributing or modifying
187
+ the Program or works based on it.
188
+
189
+ 6. Each time you redistribute the Program (or any work based on the
190
+ Program), the recipient automatically receives a license from the
191
+ original licensor to copy, distribute or modify the Program subject to
192
+ these terms and conditions. You may not impose any further
193
+ restrictions on the recipients' exercise of the rights granted herein.
194
+ You are not responsible for enforcing compliance by third parties to
195
+ this License.
196
+
197
+ 7. If, as a consequence of a court judgment or allegation of patent
198
+ infringement or for any other reason (not limited to patent issues),
199
+ conditions are imposed on you (whether by court order, agreement or
200
+ otherwise) that contradict the conditions of this License, they do not
201
+ excuse you from the conditions of this License. If you cannot
202
+ distribute so as to satisfy simultaneously your obligations under this
203
+ License and any other pertinent obligations, then as a consequence you
204
+ may not distribute the Program at all. For example, if a patent
205
+ license would not permit royalty-free redistribution of the Program by
206
+ all those who receive copies directly or indirectly through you, then
207
+ the only way you could satisfy both it and this License would be to
208
+ refrain entirely from distribution of the Program.
209
+
210
+ If any portion of this section is held invalid or unenforceable under
211
+ any particular circumstance, the balance of the section is intended to
212
+ apply and the section as a whole is intended to apply in other
213
+ circumstances.
214
+
215
+ It is not the purpose of this section to induce you to infringe any
216
+ patents or other property right claims or to contest validity of any
217
+ such claims; this section has the sole purpose of protecting the
218
+ integrity of the free software distribution system, which is
219
+ implemented by public license practices. Many people have made
220
+ generous contributions to the wide range of software distributed
221
+ through that system in reliance on consistent application of that
222
+ system; it is up to the author/donor to decide if he or she is willing
223
+ to distribute software through any other system and a licensee cannot
224
+ impose that choice.
225
+
226
+ This section is intended to make thoroughly clear what is believed to
227
+ be a consequence of the rest of this License.
228
+
229
+ 8. If the distribution and/or use of the Program is restricted in
230
+ certain countries either by patents or by copyrighted interfaces, the
231
+ original copyright holder who places the Program under this License
232
+ may add an explicit geographical distribution limitation excluding
233
+ those countries, so that distribution is permitted only in or among
234
+ countries not thus excluded. In such case, this License incorporates
235
+ the limitation as if written in the body of this License.
236
+
237
+ 9. The Free Software Foundation may publish revised and/or new versions
238
+ of the General Frontend License from time to time. Such new versions will
239
+ be similar in spirit to the present version, but may differ in detail to
240
+ address new problems or concerns.
241
+
242
+ Each version is given a distinguishing version number. If the Program
243
+ specifies a version number of this License which applies to it and "any
244
+ later version", you have the option of following the terms and conditions
245
+ either of that version or of any later version published by the Free
246
+ Software Foundation. If the Program does not specify a version number of
247
+ this License, you may choose any version ever published by the Free Software
248
+ Foundation.
249
+
250
+ 10. If you wish to incorporate parts of the Program into other free
251
+ programs whose distribution conditions are different, write to the author
252
+ to ask for permission. For software which is copyrighted by the Free
253
+ Software Foundation, write to the Free Software Foundation; we sometimes
254
+ make exceptions for this. Our decision will be guided by the two goals
255
+ of preserving the free status of all derivatives of our free software and
256
+ of promoting the sharing and reuse of software generally.
257
+
258
+ NO WARRANTY
259
+
260
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261
+ FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262
+ OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263
+ PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264
+ OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266
+ TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267
+ PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268
+ REPAIR OR CORRECTION.
269
+
270
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272
+ REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273
+ INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274
+ OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275
+ TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276
+ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277
+ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278
+ POSSIBILITY OF SUCH DAMAGES.
279
+
280
+ END OF TERMS AND CONDITIONS
281
+
282
+ How to Apply These Terms to Your New Programs
283
+
284
+ If you develop a new program, and you want it to be of the greatest
285
+ possible use to the public, the best way to achieve this is to make it
286
+ free software which everyone can redistribute and change under these terms.
287
+
288
+ To do so, attach the following notices to the program. It is safest
289
+ to attach them to the start of each source file to most effectively
290
+ convey the exclusion of warranty; and each file should have at least
291
+ the "copyright" line and a pointer to where the full notice is found.
292
+
293
+ <one line to give the program's name and a brief idea of what it does.>
294
+ Copyright (C) <year> <name of author>
295
+
296
+ This program is free software; you can redistribute it and/or modify
297
+ it under the terms of the GNU General Frontend License as published by
298
+ the Free Software Foundation; either version 2 of the License, or
299
+ (at your option) any later version.
300
+
301
+ This program is distributed in the hope that it will be useful,
302
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
303
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304
+ GNU General Frontend License for more details.
305
+
306
+ You should have received a copy of the GNU General Frontend License along
307
+ with this program; if not, write to the Free Software Foundation, Inc.,
308
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309
+
310
+ Also add information on how to contact you by electronic and paper mail.
311
+
312
+ If the program is interactive, make it output a short notice like this
313
+ when it starts in an interactive mode:
314
+
315
+ Gnomovision version 69, Copyright (C) year name of author
316
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317
+ This is free software, and you are welcome to redistribute it
318
+ under certain conditions; type `show c' for details.
319
+
320
+ The hypothetical commands `show w' and `show c' should show the appropriate
321
+ parts of the General Frontend License. Of course, the commands you use may
322
+ be called something other than `show w' and `show c'; they could even be
323
+ mouse-clicks or menu items--whatever suits your program.
324
+
325
+ You should also get your employer (if you work as a programmer) or your
326
+ school, if any, to sign a "copyright disclaimer" for the program, if
327
+ necessary. Here is a sample; alter the names:
328
+
329
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
331
+
332
+ <signature of Ty Coon>, 1 April 1989
333
+ Ty Coon, President of Vice
334
+
335
+ This General Frontend License does not permit incorporating your program into
336
+ proprietary programs. If your program is a subroutine library, you may
337
+ consider it more useful to permit linking proprietary applications with the
338
+ library. If this is what you want to do, use the GNU Lesser General
339
+ Frontend License instead of this License.
a2-optimized.php CHANGED
@@ -1,138 +1,122 @@
1
  <?php
2
- /*
3
- Plugin Name: A2 Optimized WP
4
- Plugin URI: https://wordpress.org/plugins/a2-optimized/
5
- Version: 2.1.5.1
6
- Author: A2 Hosting
7
- Author URI: https://www.a2hosting.com/
8
- Description: A2 Optimized - WordPress Optimization Plugin
9
- Text Domain: a2-optimized
10
- License: GPLv3
11
- */
12
-
13
- // Prevent direct access to this file
14
- if (! defined('WPINC')) {
15
- die;
 
 
 
 
 
 
 
 
16
  }
17
 
18
- //////////////////////////////////
19
- // Run initialization
20
- /////////////////////////////////
21
-
22
- require_once 'A2_Optimized_Plugin.php';
23
- require_once ABSPATH . 'wp-admin/includes/plugin.php';
24
- require_once 'A2_Optimized_Server_Info.php';
25
- require_once 'A2_Optimized_Cache.php';
26
- require_once 'A2_Optimized_CacheEngine.php';
27
- require_once 'A2_Optimized_CacheDisk.php';
28
- require_once 'A2_Optimized_SiteHealth.php';
29
- require_once 'A2_Optimized_DB_Optimizations.php';
30
-
31
- //constants
32
- define('A2OPT_VERSION', '2.1');
33
- define('A2OPT_FULL_VERSION', '2.1.5.1');
34
- define('A2OPT_MIN_PHP', '5.6');
35
- define('A2OPT_MIN_WP', '5.1');
36
- define('A2OPT_FILE', __FILE__);
37
- define('A2OPT_BASE', plugin_basename(__FILE__));
38
- define('A2OPT_DIR', __DIR__);
39
-
40
- class A2_Optimized
41
- {
42
- public function __construct()
43
- {
44
- if (version_compare(PHP_VERSION, A2OPT_MIN_PHP) < 0) {
45
- add_action('admin_notices', [&$this,'A2_Optimized_noticePhpVersionWrong']);
46
-
47
- return;
48
- }
49
-
50
- $GLOBALS['A2_Plugin_Dir'] = dirname(__FILE__);
51
-
52
- $a2Plugin = new A2_Optimized_Plugin();
53
-
54
- // Install the plugin
55
- if (!$a2Plugin->isInstalled()) {
56
- $a2Plugin->install();
57
- } else {
58
- // Perform any version-upgrade activities prior to activation (e.g. database changes)
59
- $a2Plugin->upgrade();
60
- }
61
-
62
- // Add callbacks to hooks
63
- $a2Plugin->addActionsAndFilters();
64
-
65
- // Register the Plugin Activation Hook
66
- register_activation_hook(__FILE__, [&$a2Plugin, 'activate']);
67
-
68
- // Register the Plugin Deactivation Hook
69
- register_deactivation_hook(__FILE__, [&$a2Plugin, 'deactivate']);
70
- }
71
-
72
- public function A2_Optimized_noticePhpVersionWrong()
73
- {
74
- echo '<div class="notice notice-warning fade is-dismissible">' .
75
- __('Error: plugin "A2 Optimized" requires a newer version of PHP to be running.', 'a2-optimized') .
76
- '<br/>' . __('Minimal version of PHP required: ', 'a2-optimized') . '<strong>' . A2OPT_MIN_PHP . '</strong>' .
77
- '<br/>' . __('Your site is running PHP version: ', 'a2-optimized') . '<strong>' . phpversion() . '</strong>' .
78
- '<br />' . __(' To learn how to change the version of php running on your site') . ' <a target="_blank" href="http://www.a2hosting.com/kb/cpanel/cpanel-software-and-services/php-version">' . __('read this Knowledge Base Article') . '</a>.' .
79
- '</div>';
80
- }
81
-
82
- // add plugin upgrade notification
83
- public static function showUpgradeNotification($currentPluginMetadata)
84
- {
85
- // Notice Transient
86
- $upgrade_notices = get_transient('a2_opt_ug_notes');
87
- if (!$upgrade_notices) {
88
- $response = wp_remote_get('https://wp-plugins.a2hosting.com/wp-json/wp/v2/update_notice?notice_plugin=2');
89
- if (is_array($response)) {
90
- $upgrade_notices = [];
91
- $body = json_decode($response['body']); // use the content
92
- foreach ($body as $item) {
93
- $upgrade_notices[$item->title->rendered] = 'Version ' . $item->title->rendered . ': ' . strip_tags($item->content->rendered);
94
- }
95
- set_transient('a2_opt_ug_notes', $upgrade_notices, 3600 * 12);
96
- } else {
97
- return;
98
- }
99
- }
100
-
101
- foreach ($upgrade_notices as $ver => $notice) {
102
- if (version_compare($currentPluginMetadata['Version'], $ver) < 0) {
103
- echo '</div><p style="background-color: #d54e21; padding: 10px; color: #f9f9f9; margin-top: 10px" class="update-message notice inline notice-warning notice-alt"><strong>Important Upgrade Notice:</strong><br />';
104
- echo esc_html($notice), '</p><div>';
105
-
106
- break;
107
- }
108
- }
109
- }
110
-
111
- // Remove WooCommerce AJAX calls from homepage if user has selected
112
- public static function dequeue_woocommerce_cart_fragments()
113
- {
114
- if (is_front_page() && get_option('a2_wc_cart_fragments')) {
115
- wp_dequeue_script('wc-cart-fragments');
116
- }
117
- }
118
  }
119
 
120
- if (get_option('a2_cache_enabled') == 1) {
121
- if (is_plugin_active('litespeed-cache/litespeed-cache.php')) {
122
- A2_Optimized_Cache_Disk::clean();
123
- update_option('a2_cache_enabled', 0);
124
- } else {
125
- add_action('plugins_loaded', [ 'A2_Optimized_Cache', 'init' ]);
126
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
  }
128
- register_deactivation_hook(__FILE__, [ 'A2_Optimized_Cache', 'on_deactivation' ]);
129
- register_uninstall_hook(__FILE__, [ 'A2_Optimized_Cache', 'on_uninstall' ]);
130
 
131
- $a2opt_class = new A2_Optimized();
132
- add_action('in_plugin_update_message-a2-optimized-wp/a2-optimized.php', [ 'A2_Optimized','showUpgradeNotification'], 10, 2);
133
- add_action('wp_enqueue_scripts', ['A2_Optimized', 'dequeue_woocommerce_cart_fragments'], 11, 2);
134
-
135
- // load WP-CLI command
136
- if (defined('WP_CLI') && WP_CLI && class_exists('WP_CLI')) {
137
- require_once A2OPT_DIR . '/A2_Optimized_CLI.php';
138
- }
1
  <?php
2
+ /**
3
+ * Main Plugin File
4
+ *
5
+ * @link http://example.com
6
+ * @since 3.0.0
7
+ * @package A2_Optimized
8
+ *
9
+ * @wordpress-plugin
10
+ * Plugin Name: A2 Optimized WP
11
+ * Plugin URI: https://wordpress.org/plugins/a2-optimized/
12
+ * Version: 3.0.0
13
+ * Author: A2 Hosting
14
+ * Author URI: https://www.a2hosting.com/
15
+ * Description: A2 Optimized - WordPress Optimization Plugin
16
+ * Text Domain: a2-optimized
17
+ * License: GPLv3
18
+ * Domain Path: /languages
19
+ */
20
+
21
+ // If this file is called directly, abort.
22
+ if ( ! defined( 'WPINC' ) ) {
23
+ die;
24
  }
25
 
26
+ define( 'A2OPT_VERSION', '3.0' );
27
+ define( 'A2OPT_FULL_VERSION', '3.0.0' );
28
+ define( 'A2OPT_MIN_PHP', '5.6' );
29
+ define( 'A2OPT_MIN_WP', '5.1' );
30
+ define( 'A2OPT_FILE', __FILE__ );
31
+ define( 'A2OPT_BASE', plugin_basename( __FILE__ ) );
32
+ define( 'A2OPT_DIR', __DIR__ );
33
+
34
+ /**
35
+ * Creates/Maintains the object of Requirements Checker Class
36
+ *
37
+ * @return \A2_Optimized\Includes\Requirements_Checker
38
+ * @since 3.0.0
39
+ */
40
+ function plugin_requirements_checker() {
41
+ static $requirements_checker = null;
42
+
43
+ if ( null === $requirements_checker ) {
44
+ require_once plugin_dir_path( __FILE__ ) . 'includes/class-requirements-checker.php';
45
+ $requirements_conf = apply_filters( 'a2_optimized_minimum_requirements', include_once( plugin_dir_path( __FILE__ ) . 'requirements-config.php' ) );
46
+ $requirements_checker = new A2_Optimized\Includes\Requirements_Checker( $requirements_conf );
47
+ }
48
+
49
+ return $requirements_checker;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  }
51
 
52
+ /**
53
+ * Begins execution of the plugin.
54
+ *
55
+ * @since 3.0.0
56
+ */
57
+ function run_a2_optimized() {
58
+ // If Plugins Requirements are not met.
59
+ if ( ! plugin_requirements_checker()->requirements_met() ) {
60
+ add_action( 'admin_notices', [ plugin_requirements_checker(), 'show_requirements_errors' ] );
61
+
62
+ // Deactivate plugin immediately if requirements are not met.
63
+ require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
64
+ deactivate_plugins( plugin_basename( __FILE__ ) );
65
+
66
+ return;
67
+ }
68
+
69
+ /**
70
+ * The core plugin class that is used to define internationalization,
71
+ * admin-specific hooks, and frontend-facing site hooks.
72
+ */
73
+ require_once plugin_dir_path( __FILE__ ) . 'includes/class-a2-optimized.php';
74
+
75
+ /**
76
+ * Begins execution of the plugin.
77
+ *
78
+ * Since everything within the plugin is registered via hooks,
79
+ * then kicking off the plugin from this point in the file does
80
+ * not affect the page life cycle.
81
+ *
82
+ * @since 3.0.0
83
+ */
84
+ $router_class_name = apply_filters( 'a2_optimized_router_class_name', '\A2_Optimized\Core\Router' );
85
+ $routes = apply_filters( 'a2_optimized_routes_file', plugin_dir_path( __FILE__ ) . 'routes.php' );
86
+ $GLOBALS['a2_optimized'] = new A2_Optimized( $router_class_name, $routes );
87
+
88
+ register_activation_hook( __FILE__, [ new A2_Optimized\App\Activator(), 'activate' ] );
89
+ register_deactivation_hook( __FILE__, [ new A2_Optimized\App\Deactivator(), 'deactivate' ] );
90
+
91
+ if (get_option('a2_cache_enabled') == 1) {
92
+ if(in_array('litespeed-cache/litespeed-cache.php', apply_filters('active_plugins', get_option('active_plugins')))){
93
+ A2_Optimized_Cache_Disk::clean();
94
+ update_option('a2_cache_enabled', 0);
95
+ } else {
96
+ add_action('plugins_loaded', [ 'A2_Optimized_Cache', 'init' ]);
97
+ }
98
+ }
99
+ if(is_admin()){
100
+ new A2_Optimized_SiteHealth;
101
+ if (defined('DISALLOW_FILE_EDIT') && DISALLOW_FILE_EDIT) {
102
+ add_action('admin_menu', ['A2_Optimized_Optimizations', 'addLockedEditor'], 100, 100);
103
+ }
104
+ }
105
+ if (get_option('A2_Optimized_Plugin_recaptcha', 0) == 1 && !is_admin()) {
106
+ add_action('woocommerce_login_form', ['A2_Optimized_Optimizations', 'login_captcha']);
107
+ add_action('login_form', ['A2_Optimized_Optimizations', 'login_captcha']);
108
+ add_filter('authenticate', ['A2_Optimized_Optimizations', 'captcha_authenticate'], 1, 3);
109
+ add_action('comment_form_after_fields', ['A2_Optimized_Optimizations', 'comment_captcha']);
110
+ add_filter('preprocess_comment', ['A2_Optimized_Optimizations', 'captcha_comment_authenticate'], 1, 3);
111
+ }
112
+
113
+ new A2_Optimized_SiteData;
114
+ $optimizations = new A2_Optimized_Optimizations;
115
+
116
+ if ($optimizations->is_xmlrpc_request() && get_option('a2_block_xmlrpc')) {
117
+ $optimizations->block_xmlrpc_request();
118
+ add_filter('xmlrpc_methods', ['A2_Optimized_Optimizations', 'remove_xmlrpc_methods']);
119
+ }
120
  }
 
 
121
 
122
+ run_a2_optimized();
 
 
 
 
 
 
 
advanced-cache.php CHANGED
@@ -8,8 +8,8 @@ if ( ! defined( 'ABSPATH' ) ) {
8
  }
9
 
10
  $a2opt_cache_dir = ( ( defined( 'WP_PLUGIN_DIR' ) ) ? WP_PLUGIN_DIR : WP_CONTENT_DIR . '/plugins' ) . '/a2-optimized-wp';
11
- $a2opt_cache_engine_file = $a2opt_cache_dir . '/A2_Optimized_CacheEngine.php';
12
- $a2opt_cache_disk_file = $a2opt_cache_dir . '/A2_Optimized_CacheDisk.php';
13
 
14
  if ( file_exists( $a2opt_cache_engine_file ) && file_exists( $a2opt_cache_disk_file ) ) {
15
  require_once $a2opt_cache_engine_file;
8
  }
9
 
10
  $a2opt_cache_dir = ( ( defined( 'WP_PLUGIN_DIR' ) ) ? WP_PLUGIN_DIR : WP_CONTENT_DIR . '/plugins' ) . '/a2-optimized-wp';
11
+ $a2opt_cache_engine_file = $a2opt_cache_dir . '/core/A2_Optimized_CacheEngine.php';
12
+ $a2opt_cache_disk_file = $a2opt_cache_dir . '/core/A2_Optimized_CacheDisk.php';
13
 
14
  if ( file_exists( $a2opt_cache_engine_file ) && file_exists( $a2opt_cache_disk_file ) ) {
15
  require_once $a2opt_cache_engine_file;
app/class-activator.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace A2_Optimized\App;
3
+
4
+ /**
5
+ * Fired during plugin activation.
6
+ *
7
+ * This class defines all code necessary to run during the plugin's activation.
8
+ *
9
+ * @since 3.0.0
10
+ * @package A2_Optimized
11
+ * @subpackage A2_Optimized/App
12
+ * @author Your Name <email@example.com>
13
+ */
14
+ class Activator {
15
+
16
+ /**
17
+ * Short Description. (use period)
18
+ *
19
+ * Long Description.
20
+ *
21
+ * @since 3.0.0
22
+ */
23
+ public function activate() {
24
+ }
25
+
26
+ }
app/class-deactivator.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace A2_Optimized\App;
3
+
4
+ /**
5
+ * Fired during plugin deactivation.
6
+ *
7
+ * This class defines all code necessary to run during the plugin's deactivation.
8
+ *
9
+ * @since 3.0.0
10
+ * @package A2_Optimized
11
+ * @subpackage A2_Optimized/App
12
+ * @author Your Name <email@example.com>
13
+ */
14
+ class Deactivator {
15
+ /**
16
+ * Short Description. (use period)
17
+ *
18
+ * Long Description.
19
+ *
20
+ * @since 3.0.0
21
+ */
22
+ public function deactivate() {
23
+ $htaccess = file_get_contents(ABSPATH . '.htaccess');
24
+
25
+ $pattern = "/[\r\n]*# BEGIN WordPress Hardening.*# END WordPress Hardening[\r\n]*/msiU";
26
+ $htaccess = preg_replace($pattern, '', $htaccess);
27
+
28
+ //Write the rules to .htaccess
29
+ $fp = fopen(ABSPATH . '.htaccess', 'c');
30
+
31
+ if (flock($fp, LOCK_EX)) {
32
+ ftruncate($fp, 0); // truncate file
33
+ fwrite($fp, $htaccess);
34
+ fflush($fp); // flush output before releasing the lock
35
+ flock($fp, LOCK_UN); // release the lock
36
+ } else {
37
+ //no file lock :(
38
+ }
39
+
40
+ // deactivate the scheduled weekly database optimizations
41
+ wp_clear_scheduled_hook('a2_execute_db_optimizations');
42
+ }
43
+ }
app/class-uninstaller.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace A2_Optimized\App;
3
+
4
+ /**
5
+ * Fired during plugin uninstallation.
6
+ *
7
+ * This class defines all code necessary to run during the plugin's uninstallation.
8
+ *
9
+ * @since 3.0.0
10
+ * @package A2_Optimized
11
+ * @subpackage A2_Optimized/App
12
+ * @author Your Name <email@example.com>
13
+ */
14
+ class Uninstaller {
15
+
16
+ /**
17
+ * Short Description. (use period)
18
+ *
19
+ * Long Description.
20
+ *
21
+ * @since 3.0.0
22
+ */
23
+ public function uninstall() {
24
+ }
25
+
26
+ }
app/controllers/admin/class-admin-settings.php ADDED
@@ -0,0 +1,398 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace A2_Optimized\App\Controllers\Admin;
4
+
5
+ use A2_Optimized\App\Controllers\Admin\Base_Controller;
6
+ use A2_Optimized as A2_Optimized;
7
+
8
+ if (! class_exists(__NAMESPACE__ . '\\' . 'Admin_Settings')) {
9
+ /**
10
+ * Controller class that implements Plugin Admin Settings configurations
11
+ *
12
+ * @since 3.0.0
13
+ * @package A2_Optimized
14
+ * @subpackage A2_Optimized/controllers/admin
15
+ */
16
+ class Admin_Settings extends Base_Controller {
17
+ /**
18
+ * Holds suffix for dynamic add_action called on settings page.
19
+ *
20
+ * @var string
21
+ * @since 3.0.0
22
+ */
23
+ private static $hook_suffix = 'toplevel_page_' . A2_Optimized::PLUGIN_ID;
24
+
25
+ /**
26
+ * Slug of the Settings Page
27
+ *
28
+ * @since 3.0.0
29
+ */
30
+ public const SETTINGS_PAGE_SLUG = A2_Optimized::PLUGIN_ID;
31
+
32
+ /**
33
+ * Capability required to access settings page
34
+ *
35
+ * @since 3.0.0
36
+ */
37
+ public const REQUIRED_CAPABILITY = 'manage_options';
38
+
39
+ /**
40
+ * Register callbacks for actions and filters
41
+ *
42
+ * @since 3.0.0
43
+ */
44
+ public function register_hook_callbacks() {
45
+ // Create Menu.
46
+ add_action('admin_menu', [ $this, 'plugin_menu' ]);
47
+
48
+ // Enqueue Styles & Scripts.
49
+ add_action('admin_print_scripts-' . static::$hook_suffix, [ $this, 'enqueue_scripts' ]);
50
+ add_action('admin_print_styles-' . static::$hook_suffix, [ $this, 'enqueue_styles' ]);
51
+
52
+ // Register Fields.
53
+ add_action('load-' . static::$hook_suffix, [ $this, 'register_fields' ]);
54
+
55
+ // Register Settings.
56
+ add_action('admin_init', [ $this->get_model(), 'register_settings' ]);
57
+
58
+ // Settings Link on Plugin's Page.
59
+ add_filter(
60
+ 'plugin_action_links_' . A2_Optimized::PLUGIN_ID . '/' . A2_Optimized::PLUGIN_ID . '.php',
61
+ [ $this, 'add_plugin_action_links' ]
62
+ );
63
+
64
+ add_filter('submenu_file', [ $this, 'highlight_active_submenu' ]);
65
+
66
+
67
+ }
68
+
69
+
70
+ /**
71
+ * Create menu for Plugin inside Settings menu
72
+ *
73
+ * @since 3.0.0
74
+ */
75
+ public function plugin_menu() {
76
+ // @codingStandardsIgnoreStart.
77
+
78
+ $icon_base64 = 'PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCIKCSB3aWR0aD0iMTAwJSIgdmlld0JveD0iMCAwIDMwNCAzMDQiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDMwNCAzMDQiIHhtbDpzcGFjZT0icHJlc2VydmUiPgo8cGF0aCBmaWxsPSJibGFjayIgb3BhY2l0eT0iMS4wMDAwMDAiIHN0cm9rZT0ibm9uZSIgCglkPSIKTTEwMi40MzExMjksMjIuMjQwMTcwIAoJQzExNy40MDM3NjMsMjEuMDIxNDI3IDEzMi4wMTkyMTEsMTguODIzMjcxIDE0Ni41NTY3MTcsMTkuMjU0MjcxIAoJQzE3NC4zNjY4MDYsMjAuMDc4Nzc3IDIwMS43MzY2MTgsMjQuMjMxNzU4IDIyNi41MjA5NjYsMzguMjEwNDc2IAoJQzI0Ni44ODEzMDIsNDkuNjkzOTkzIDI1OS44Mzg2NTQsNjcuMDc4MDk0IDI2NS45ODcxMjIsODkuNTcwOTM4IAoJQzI2OS42ODQ3ODQsMTAzLjA5ODEyMiAyNjkuOTIzMjc5LDExNy4wMzQzNDggMjY4Ljc1NDYwOCwxMzAuNzQ1MzQ2IAoJQzI2Ny41MTkzNzksMTQ1LjIzNzc0NyAyNjQuMjU4Nzg5LDE1OS41NTEyMDggMjYyLjA1NTc4NiwxNzMuOTY5MjM4IAoJQzI1OS45MjIzNjMsMTg3LjkzMjA2OCAyNTguMDg0MzIwLDIwMS45Mzk5MTEgMjU1Ljk3NjAxMywyMTUuOTA2NzU0IAoJQzI1NC4wODg2NTQsMjI4LjQwOTg2NiAyNTEuNzMxMzM5LDI0MC44NDgwNTMgMjUwLjEwOTYwNCwyNTMuMzgzMjA5IAoJQzI0OC45NTMxMjUsMjYyLjMyMjA4MyAyNDguNjQyMjU4LDI3MS4zNzIxMzEgMjQ4LjAyMTc0NCwyODAuMzc3MjU4IAoJQzI0Ny44NzQ5ODUsMjgyLjUwNzE0MSAyNDguMDAwMDAwLDI4NC42NTU3NjIgMjQ4LjAwMDAwMCwyODcuMTIzNjI3IAoJQzIyOS43MTc1NDUsMjg0LjA0MzY3MSAyMTEuODY0NzQ2LDI4MS4wMjgyNTkgMTk0LjAwNzg3NCwyNzguMDM3MTcwIAoJQzE5MS42MDYzNTQsMjc3LjYzNDk0OSAxODkuMTczODI4LDI3Ny40MTY4NzAgMTg2Ljc3Mzc3MywyNzcuMDA3Mzg1IAoJQzE3OS43MDExMTEsMjc1LjgwMDY5MCAxNzkuMTkzNDIwLDI3NS4yNjA0NjggMTc5LjAyMzExNywyNjcuODk2Njk4IAoJQzE3OC45MDM3OTMsMjYyLjczNzMzNSAxNzkuMDAwMDc2LDI1Ny41NzMwMjkgMTc5LjAwMDA3NiwyNTEuMjgzMTQyIAoJQzE3Ni4wMjczNTksMjUzLjQ4MjkxMCAxNzMuNzk1MzM0LDI1NS40MzQ0MzMgMTcxLjI5Mjc1NSwyNTYuOTM0NjYyIAoJQzE2MC4zMjI3ODQsMjYzLjUxMDc0MiAxNDguODk1NDkzLDI2OC42MTEwODQgMTM1Ljg5NjYyMiwyNzAuMTE2MDI4IAoJQzExOC43NDMyODYsMjcyLjEwMTkyOSAxMDIuMDE4Mzg3LDI3MS4xNDQwMTIgODUuODI0OTEzLDI2NC45ODA4MzUgCglDNjAuMzkyMzg3LDI1NS4zMDEyMzkgNDMuNTgwMTIwLDIzNy4zMDYzMDUgMzguMjYxNDU2LDIxMC42MTczODYgCglDMzMuMDI0NTkzLDE4NC4zMzg5ODkgNDAuMzg4MDAwLDE2MC40NjA4NzYgNTcuMDA2NTM1LDEzOS41MDgxNzkgCglDNzAuNTY5NTU3LDEyMi40MDc4NzUgODcuMTA5OTQ3LDEwOS41ODU2NDAgMTA4LjU2NzIzMCwxMDMuODE2OTMzIAoJQzEyMi43MjMxMTQsMTAwLjAxMTE2OSAxMzYuODIxMTM2LDk5LjQ0MDgxMSAxNTAuODk0NTkyLDEwNC4wMzA4MzggCglDMTU2LjQ4NzU2NCwxMDUuODU0OTY1IDE2MC41NDMxMDYsMTEyLjM1NjM5MiAxNjEuMDg2ODg0LDExOC4yNzE0NjkgCglDMTYyLjMxMzc1MSwxMzEuNjE2OTU5IDE1NC4zMTg3ODcsMTQwLjA4MDU1MSAxNDUuMDExMjE1LDE0Ni44MDczMjcgCglDMTI2LjMzODA2NiwxNjAuMzAyNzgwIDEwNy4xMTU2OTIsMTczLjA3NDc4MyA4Ny42ODAzMDUsMTg1LjQ1NTA5MyAKCUM4Mi4zODIyMzMsMTg4LjgyOTk0MSA4NC43MTI0ODYsMTkzLjUyMDE3MiA4My4xMzY2MjAsMTk3LjQzNDY0NyAKCUM4MS45NTY4NjMsMjAwLjM2NTE3MyA4Mi4zMjI4ODQsMjAzLjg4Mjg3NCA4MS40MzUxNTAsMjA2Ljk3Njg4MyAKCUM4MC42ODc1ODQsMjA5LjU4MjM4MiA4MS4yODg2NTgsMjEwLjYwOTIzOCA4My44MzkzODYsMjExLjAzMzgyOSAKCUM5MS40ODY5MDAsMjEyLjMwNjgyNCA5OS4xMDI5MjgsMjEzLjc3NDk2MyAxMDYuNzYxMjQ2LDIxNC45NzU1NzEgCglDMTE4LjMwMzkxNywyMTYuNzg1MTQxIDEyOS44ODA0NjMsMjE4LjM3ODAwNiAxNDEuNDI2NjgyLDIyMC4xNjU3NDEgCglDMTUxLjM1MTc5MSwyMjEuNzAyNDg0IDE2MS4yNTIxNTEsMjIzLjM5ODQ5OSAxNzEuMTY4MzA0LDIyNC45OTM4MjAgCglDMTc2LjQ2NDI2NCwyMjUuODQ1ODU2IDE4MS43NzA1MDgsMjI2LjYzMzk0MiAxODguMDQyNTI2LDIyNy42MDA0MTggCglDMTg5LjM4Nzg5NCwyMTcuMjM1MzgyIDE5MC42NjgxOTgsMjA3LjM3MTU2NyAxOTIuMDg2Nzc3LDE5Ni40NDI1MzUgCglDMTc1LjQ2MTA3NSwxOTMuMzU2MTU1IDE1OC44NjYxMTksMTkwLjI3NTQ4MiAxNDEuMTk4MjI3LDE4Ni45OTU2MzYgCglDMTQ1LjA2NDI4NSwxODQuNjc0MzYyIDE0OC4zODM5ODcsMTgyLjQxMjM4NCAxNTEuOTMyNjE3LDE4MC41OTgxNDUgCglDMTY1LjQxMDAxOSwxNzMuNzA3Nzk0IDE3Ny42NjkwNTIsMTY1LjE5OTAzNiAxODcuNjkxMzE1LDE1My43NjQwNTMgCglDMTk1LjE4Nzg4MSwxNDUuMjEwODQ2IDE5OS42ODQ4MzAsMTM1LjQ2ODQzMCAyMDEuMjQ5NTI3LDEyMy45MDcyMTkgCglDMjAyLjk1NTEwOSwxMTEuMzA0OTcwIDE5OS44ODc3MTEsMTAwLjQ2MjM2NCAxOTIuMjUzNjMyLDkwLjg5ODE4NiAKCUMxODQuMzcyMzYwLDgxLjAyNDI3NyAxNzMuNTg1Njc4LDc1LjI4NDY5OCAxNjEuMjg1ODczLDczLjEzNzYyNyAKCUMxNTEuNjY2NTUwLDcxLjQ1ODQ1OCAxNDEuODA1MTkxLDY5Ljk3MzA3NiAxMzIuMTAzMTM0LDcwLjI0NTQ1MyAKCUMxMTguMjE4MzA3LDcwLjYzNTI1NCAxMDQuNDY4OTE4LDczLjEzMTI4NyA5MS4zNTc5OTQsNzguMjA5OTQ2IAoJQzg5Ljg2MTg4NSw3OC43ODk0NzQgODguMjcwNzk4LDc5LjEyMzgwMiA4NS44NzQ0ODksNzkuODE3NzcyIAoJQzgzLjc2NDc3MSw2Mi43NjI5ODUgODEuNjcwODMwLDQ1LjgzNTY5NyA3OS40OTEyNzIsMjguMjE2MjQwIAoJQzg3LjI1ODU5MSwyNi4yMjkyMjMgOTQuNjQ4NjY2LDI0LjMzODcxMyAxMDIuNDMxMTI5LDIyLjI0MDE3MCAKeiIvPgo8L3N2Zz4=';
79
+
80
+ $icon_data_uri = 'data:image/svg+xml;base64,' . $icon_base64;
81
+
82
+ static::$hook_suffix = add_menu_page(
83
+ __(A2_Optimized::PLUGIN_NAME, A2_Optimized::PLUGIN_ID), // Page Title.
84
+ __(A2_Optimized::PLUGIN_NAME, A2_Optimized::PLUGIN_ID), // Menu Title.
85
+ static::REQUIRED_CAPABILITY, // Capability.
86
+ static::SETTINGS_PAGE_SLUG,
87
+ [ $this, 'markup_settings_page' ],
88
+ $icon_data_uri,
89
+ '3' // menu position
90
+ );
91
+
92
+ add_submenu_page(
93
+ 'a2-optimized',
94
+ 'Page Load Speed Score', // phpcs:ignore
95
+ 'Page Load Speed Score', // phpcs:ignore
96
+ 'manage_options',
97
+ 'admin.php?page=a2-optimized'
98
+ );
99
+ add_submenu_page(
100
+ 'a2-optimized',
101
+ 'Website and Server Performance', // phpcs:ignore
102
+ 'Website and Server Performance', // phpcs:ignore
103
+ 'manage_options',
104
+ 'admin.php?page=a2-optimized&amp;a2_page=server_performance'
105
+ );
106
+ add_submenu_page(
107
+ 'a2-optimized',
108
+ 'Optimization', // phpcs:ignore
109
+ 'Optimization', // phpcs:ignore
110
+ 'manage_options',
111
+ 'admin.php?page=a2-optimized&amp;a2_page=optimizations'
112
+ );
113
+ remove_submenu_page('a2-optimized','a2-optimized'); //Removes duplicated top level item
114
+
115
+ // @codingStandardsIgnoreEnd.
116
+ }
117
+
118
+ /**
119
+ * Highlights the current active submenu
120
+ *
121
+ * @since 3.0.0
122
+ */
123
+ function highlight_active_submenu($submenu_file){
124
+ if (isset($_GET['page']) && $_GET['page'] == 'a2-optimized') {
125
+ if(!isset($_GET['a2_page']) || $_GET['a2_page'] == 'page_speed_score'){
126
+ return 'admin.php?page=a2-optimized';
127
+ } else {
128
+ return 'admin.php?page=a2-optimized&amp;a2_page=' . $_GET['a2_page'];
129
+ }
130
+ }
131
+ return $submenu_file;
132
+ }
133
+
134
+ /**
135
+ * Register the JavaScript for the admin area.
136
+ *
137
+ * @since 3.0.0
138
+ */
139
+ public function enqueue_scripts() {
140
+ /**
141
+ * This function is provided for demonstration purposes only.
142
+ */
143
+
144
+ wp_enqueue_script(
145
+ A2_Optimized::PLUGIN_ID . '_vue-js',
146
+ A2_Optimized::get_plugin_url() . 'assets/js/admin/vue.js',
147
+ [],
148
+ A2_Optimized::PLUGIN_VERSION,
149
+ false
150
+ );
151
+ wp_enqueue_script(
152
+ A2_Optimized::PLUGIN_ID . '_axios-js',
153
+ A2_Optimized::get_plugin_url() . 'assets/js/admin/axios.js',
154
+ [],
155
+ A2_Optimized::PLUGIN_VERSION,
156
+ true
157
+ );
158
+ wp_enqueue_script(
159
+ A2_Optimized::PLUGIN_ID . '_admin-js',
160
+ A2_Optimized::get_plugin_url() . 'assets/js/admin/a2-optimized.js',
161
+ [ 'jquery' ],
162
+ A2_Optimized::PLUGIN_VERSION,
163
+ true
164
+ );
165
+ wp_enqueue_script(
166
+ A2_Optimized::PLUGIN_ID . '_circles-js',
167
+ A2_Optimized::get_plugin_url() . 'assets/js/admin/circles.min.js',
168
+ [ 'jquery' ],
169
+ A2_Optimized::PLUGIN_VERSION,
170
+ true
171
+ );
172
+ wp_enqueue_script(
173
+ A2_Optimized::PLUGIN_ID . '_bootstrap-js',
174
+ A2_Optimized::get_plugin_url() . 'assets/bootstrap/js/bootstrap.js',
175
+ [ 'jquery' ],
176
+ A2_Optimized::PLUGIN_VERSION,
177
+ true
178
+ );
179
+ wp_enqueue_script(
180
+ A2_Optimized::PLUGIN_ID . '_chart-js',
181
+ A2_Optimized::get_plugin_url() . 'assets/js/admin/chart.min.js',
182
+ [ 'jquery' ],
183
+ A2_Optimized::PLUGIN_VERSION,
184
+ true
185
+ );
186
+ wp_localize_script(
187
+ 'jquery',
188
+ 'ajax',
189
+ [
190
+ 'url' => admin_url('admin-ajax.php'),
191
+ 'nonce' => wp_create_nonce('a2opt_ajax_nonce'),
192
+ ]
193
+ );
194
+ }
195
+
196
+ /**
197
+ * Register the JavaScript for the admin area.
198
+ *
199
+ * @since 3.0.0
200
+ */
201
+ public function enqueue_styles() {
202
+ /**
203
+ * This function is provided for demonstration purposes only.
204
+ */
205
+
206
+ wp_enqueue_style(
207
+ A2_Optimized::PLUGIN_ID . '_admin-css',
208
+ A2_Optimized::get_plugin_url() . 'assets/css/admin/a2-optimized.css',
209
+ [],
210
+ A2_Optimized::PLUGIN_VERSION,
211
+ 'all'
212
+ );
213
+ wp_enqueue_style(
214
+ A2_Optimized::PLUGIN_ID . '_bootstrap-css',
215
+ A2_Optimized::get_plugin_url() . 'assets/bootstrap/css/bootstrap.css',
216
+ [],
217
+ A2_Optimized::PLUGIN_VERSION,
218
+ 'all'
219
+ );
220
+ wp_enqueue_style(
221
+ A2_Optimized::PLUGIN_ID . '_bootstraptheme-css',
222
+ A2_Optimized::get_plugin_url() . 'assets/bootstrap/css/bootstrap-theme.css',
223
+ [],
224
+ A2_Optimized::PLUGIN_VERSION,
225
+ 'all'
226
+ );
227
+ wp_enqueue_style(
228
+ A2_Optimized::PLUGIN_ID . '_animations-css',
229
+ A2_Optimized::get_plugin_url() . 'assets/css/admin/animate.min.css',
230
+ [],
231
+ A2_Optimized::PLUGIN_VERSION,
232
+ 'all'
233
+ );
234
+ wp_enqueue_style(
235
+ A2_Optimized::PLUGIN_ID . '_fonts-css',
236
+ 'https://fonts.googleapis.com/css?family=Raleway:300,500,700,900|Poppins:300,500,700,900',
237
+ [],
238
+ A2_Optimized::PLUGIN_VERSION,
239
+ 'all'
240
+ );
241
+ }
242
+
243
+ /**
244
+ * Creates the markup for the Settings page
245
+ *
246
+ * @since 3.0.0
247
+ */
248
+ public function markup_settings_page() {
249
+ if (current_user_can(static::REQUIRED_CAPABILITY)) {
250
+ if (!isset($_REQUEST['a2_page'])) {
251
+ $page = 'page_speed_score';
252
+ } else {
253
+ $page = $_REQUEST['a2_page'];
254
+ }
255
+ $run_benchmarks = false;
256
+ $notifications = $this->get_model()->get_notifications();
257
+ switch ($page) {
258
+ case 'server_performance':
259
+ $graphs = $this->get_model()->get_frontend_benchmark($run_benchmarks);
260
+ $this->view->admin_server_performance_page(
261
+ [
262
+ 'page_title' => A2_Optimized::PLUGIN_NAME,
263
+ 'settings_name' => $this->get_model()->get_plugin_settings_option_key(),
264
+ 'notifications' => $notifications,
265
+ 'graphs' => $graphs['pagespeed_desktop'],
266
+ 'run_benchmarks' => $run_benchmarks
267
+ ]
268
+ );
269
+
270
+ break;
271
+ case 'hosting_matchup':
272
+ $data = $this->get_model()->get_hosting_benchmark();
273
+ $this->view->admin_hosting_matchup_page(
274
+ [
275
+ 'page_title' => A2_Optimized::PLUGIN_NAME,
276
+ 'settings_name' => $this->get_model()->get_plugin_settings_option_key(),
277
+ 'notifications' => $notifications,
278
+ 'data' => $data,
279
+ 'run_benchmarks' => $run_benchmarks
280
+ ]
281
+ );
282
+ break;
283
+ case 'optimizations':
284
+ $data = $this->get_model()->get_opt_performance();
285
+
286
+ $this->view->admin_opt_performance_page(
287
+ [
288
+ 'page_title' => A2_Optimized::PLUGIN_NAME,
289
+ 'settings_name' => $this->get_model()->get_plugin_settings_option_key(),
290
+ 'notifications' => $notifications,
291
+ 'data' => $data,
292
+ ]
293
+ );
294
+ break;
295
+ case 'page_speed_score':
296
+ default:
297
+ $frontend_metrics = $this->get_model()->get_frontend_benchmark($run_benchmarks);
298
+ $opt_data = $this->get_model()->get_opt_performance();
299
+
300
+ $graphs = array_merge($frontend_metrics, $opt_data['graphs']);
301
+
302
+ $this->view->admin_pagespeed_page(
303
+ [
304
+ 'page_title' => A2_Optimized::PLUGIN_NAME,
305
+ 'settings_name' => $this->get_model()->get_plugin_settings_option_key(),
306
+ 'notifications' => $notifications,
307
+ 'graphs' => $graphs,
308
+ 'run_benchmarks' => $run_benchmarks
309
+ ]
310
+ );
311
+ break;
312
+ }
313
+ } else {
314
+ wp_die(__('Access denied.')); // WPCS: XSS OK.
315
+ }
316
+ }
317
+
318
+ /**
319
+ * Registers settings sections and fields
320
+ *
321
+ * @since 3.0.0
322
+ */
323
+ public function register_fields() {
324
+ // Add Settings Page Section.
325
+ add_settings_section(
326
+ 'a2_optimized_section', // Section ID.
327
+ __('Settings', A2_Optimized::PLUGIN_ID), // Section Title.
328
+ [ $this, 'markup_section_headers' ], // Section Callback.
329
+ static::SETTINGS_PAGE_SLUG // Page URL.
330
+ );
331
+
332
+ // Add Settings Page Field.
333
+ add_settings_field(
334
+ 'a2_optimized_field', // Field ID.
335
+ __('A2 Optimized Field:', A2_Optimized::PLUGIN_ID), // Field Title.
336
+ [ $this, 'markup_fields' ], // Field Callback.
337
+ static::SETTINGS_PAGE_SLUG, // Page.
338
+ 'a2_optimized_section', // Section ID.
339
+ [ // Field args.
340
+ 'id' => 'a2_optimized_field',
341
+ 'label_for' => 'a2_optimized_field',
342
+ ]
343
+ );
344
+ }
345
+
346
+ /**
347
+ * Adds the section introduction text to the Settings page
348
+ *
349
+ * @param array $section Array containing information Section Id, Section
350
+ * Title & Section Callback.
351
+ *
352
+ * @since 3.0.0
353
+ */
354
+ public function markup_section_headers($section) {
355
+ $this->view->section_headers(
356
+ [
357
+ 'section' => $section,
358
+ 'text_example' => __('This is a text example for section header', A2_Optimized::PLUGIN_ID),
359
+ ]
360
+ );
361
+ }
362
+
363
+ /**
364
+ * Delivers the markup for settings fields
365
+ *
366
+ * @param array $field_args Field arguments passed in `add_settings_field`
367
+ * function.
368
+ *
369
+ * @since 3.0.0
370
+ */
371
+ public function markup_fields($field_args) {
372
+ $field_id = $field_args['id'];
373
+ $settings_value = $this->get_model()->get_setting($field_id);
374
+ $this->view->markup_fields(
375
+ [
376
+ 'field_id' => esc_attr($field_id),
377
+ 'settings_name' => $this->get_model()->get_plugin_settings_option_key(),
378
+ 'settings_value' => ! empty($settings_value) ? esc_attr($settings_value) : '',
379
+ ]
380
+ );
381
+ }
382
+
383
+ /**
384
+ * Adds links to the plugin's action link section on the Plugins page
385
+ *
386
+ * @param array $links The links currently mapped to the plugin.
387
+ * @return array
388
+ *
389
+ * @since 3.0.0
390
+ */
391
+ public function add_plugin_action_links($links) {
392
+ $settings_link = '<a href="options-general.php?page=' . static::SETTINGS_PAGE_SLUG . '">' . __('Settings', A2_Optimized::PLUGIN_ID) . '</a>';
393
+ array_unshift($links, $settings_link);
394
+
395
+ return $links;
396
+ }
397
+ }
398
+ }
app/controllers/admin/class-base-controller.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace A2_Optimized\App\Controllers\Admin;
3
+
4
+ use A2_Optimized\Core\Controller;
5
+
6
+
7
+ if ( ! class_exists( __NAMESPACE__ . '\\' . 'Base_Controller' ) ) {
8
+ /**
9
+ * Blueprint for Admin related Controllers. All Admin Controllers should extend this Base_Controller
10
+ *
11
+ * @since 3.0.0
12
+ * @package A2_Optimized
13
+ * @subpackage A2_Optimized/controllers/admin
14
+ */
15
+ abstract class Base_Controller extends Controller {
16
+
17
+ /**
18
+ * Register callbacks for actions and filters. Most of your add_action/add_filter
19
+ * go into this method.
20
+ *
21
+ * NOTE: register_hook_callbacks method is not called automatically. You
22
+ * as a developer have to call this method where you see fit. For Example,
23
+ * You may want to call this in constructor, if you feel hooks/filters
24
+ * callbacks should be registered when the new instance of the class
25
+ * is created.
26
+ *
27
+ * The purpose of this method is to set the convention that first place to
28
+ * find add_action/add_filter is register_hook_callbacks method.
29
+ *
30
+ * @since 3.0.0
31
+ */
32
+ abstract protected function register_hook_callbacks();
33
+ }
34
+
35
+ }
app/models/admin/class-admin-settings.php ADDED
@@ -0,0 +1,655 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace A2_Optimized\App\Models\Admin;
3
+
4
+ use A2_Optimized\App\Models\Settings as Settings_Model;
5
+ use A2_Optimized\App\Models\Admin\Base_Model;
6
+ use A2_Optimized_Benchmark;
7
+ use A2_Optimized_Optimizations;
8
+
9
+ if ( ! class_exists( __NAMESPACE__ . '\\' . 'Admin_Settings' ) ) {
10
+ /**
11
+ * Model class that implements Plugin Admin Settings
12
+ *
13
+ * @since 3.0.0
14
+ * @package A2_Optimized
15
+ * @subpackage A2_Optimized/models/admin
16
+ */
17
+ class Admin_Settings extends Base_Model {
18
+ private $benchmark;
19
+ private $optimizations;
20
+
21
+ const NOTIFICATIONS_KEY = 'a2_opt_notifications';
22
+
23
+ /**
24
+ * Constructor
25
+ *
26
+ * @since 3.0.0
27
+ */
28
+ protected function __construct() {
29
+ $this->register_hook_callbacks();
30
+ $this->benchmark = new A2_Optimized_Benchmark();
31
+ $this->optimizations = new A2_Optimized_Optimizations();
32
+ }
33
+
34
+ /**
35
+ * Register callbacks for actions and filters
36
+ *
37
+ * @since 3.0.0
38
+ */
39
+ protected function register_hook_callbacks() {
40
+ /**
41
+ * If you think all model related add_actions & filters should be in
42
+ * the model class only, then this this the place where you can place
43
+ * them.
44
+ *
45
+ * You can remove this method if you are not going to use it.
46
+ */
47
+
48
+ add_action( 'wp_ajax_run_benchmarks', [$this, 'run_benchmarks'] );
49
+ add_action( 'wp_ajax_apply_optimizations', [$this, 'apply_optimizations'] );
50
+ add_action( 'wp_ajax_add_notification', [$this, 'add_notification'] );
51
+ }
52
+
53
+ /* Callback for run_benchmarks AJAX request */
54
+ public function run_benchmarks() {
55
+ if ( !wp_verify_nonce($_POST['nonce'], 'a2opt_ajax_nonce') || !current_user_can('manage_options') ){
56
+ echo json_encode(['result' => 'fail', 'status' => 'Permission Denied']);
57
+ wp_die();
58
+ }
59
+
60
+ $target_url = $_POST['target_url'];
61
+ $page = $_POST['a2_page'];
62
+ $run_checks = $_POST['run_checks'] !== 'false';
63
+
64
+ switch($page){
65
+ case 'server-performance':
66
+ case 'page-speed-score':
67
+ $frontend_data = $this->get_frontend_benchmark($run_checks);
68
+
69
+ if ($page == 'server-performance') {
70
+ $strategy = 'pagespeed_' . $_POST['a2_performance_strategy'];
71
+ $frontend_data = $frontend_data[$strategy];
72
+ }
73
+
74
+ $opt_data = $this->get_opt_performance();
75
+
76
+ $data = array_merge($frontend_data, $opt_data['graphs']);
77
+ break;
78
+ case 'hosting-matchup':
79
+ $hosting_data = $this->get_hosting_benchmark($run_checks);
80
+
81
+ $data = $hosting_data;
82
+ break;
83
+ }
84
+
85
+
86
+ echo json_encode($data);
87
+ wp_die();
88
+ }
89
+
90
+ //// notification functions //
91
+ public function get_notifications() {
92
+ $notifications = get_option(self::NOTIFICATIONS_KEY);
93
+ if ($notifications && count($notifications) == 0){
94
+ $notifications = [];
95
+ }
96
+
97
+ return $notifications;
98
+
99
+ }
100
+
101
+ public function add_notification(){
102
+ if ( !wp_verify_nonce($_POST['nonce'], 'a2opt_ajax_nonce') || !current_user_can('manage_options') ){
103
+ echo json_encode(['result' => 'fail', 'status' => 'Permission Denied']);
104
+ wp_die();
105
+ }
106
+ $new_notification = esc_html($_POST['a2_notification_text']) ?? '';
107
+ if (!empty($new_notification)){
108
+ $notifications = $this->get_notifications();
109
+ $max_id = 0;
110
+ if (count($notifications) > 0){
111
+ $max_id = max(array_keys($notifications));
112
+ }
113
+ $new_id = $max_id + 1;
114
+
115
+ $notifications[$new_id] = $new_notification;
116
+ update_option(self::NOTIFICATIONS_KEY, $notifications);
117
+ echo json_encode($notifications);
118
+ }
119
+ wp_die();
120
+ }
121
+ ////
122
+ /* Callback for apply_optimizations AJAX request */
123
+ public function apply_optimizations() {
124
+ if ( !wp_verify_nonce($_POST['nonce'], 'a2opt_ajax_nonce') || !current_user_can('manage_options') ){
125
+ echo json_encode(['result' => 'fail', 'status' => 'Permission Denied']);
126
+ wp_die();
127
+ }
128
+
129
+ $data = [];
130
+
131
+ $optimizations = [];
132
+ foreach($_POST as $k => $value){
133
+ if(substr($k, 0, 4) === "opt-"){
134
+ $k = str_replace("opt-", "", $k);
135
+ $optimizations[$k] = $value;
136
+ $this->optimizations->apply_optimization($k, $value);
137
+ }
138
+ }
139
+
140
+ $opt_perf = $this->get_opt_performance();
141
+
142
+ $data['updated_data'] = $opt_perf;
143
+
144
+ $data['result'] = 'success';
145
+
146
+ echo json_encode($data);
147
+ wp_die();
148
+ }
149
+
150
+ public function get_hosting_benchmark($run = false) {
151
+ if($run){
152
+ $this->benchmark->run_hosting_test_suite();
153
+ }
154
+ $backend_benchmarks = get_option('a2opt-benchmarks-hosting');
155
+ $baseline_benchmarks = $this->benchmark->get_baseline_results();
156
+
157
+ $result = [
158
+ 'last_check_date' => 'None'
159
+ ];
160
+ if ($backend_benchmarks){
161
+ $bm = array_pop($backend_benchmarks);
162
+ $result['last_check_date'] = $this->get_readable_last_check_date($bm['sysinfo']['time']);
163
+ $hostentry = [
164
+ 'php' => $bm['php']['total'],
165
+ 'mysql' => $bm['mysql']['benchmark']['mysql_total'],
166
+ 'wordpress_db' => $bm['wordpress_db']['time'],
167
+ 'filesystem' => $bm['filesystem'],
168
+ ];
169
+ }
170
+ else {
171
+ $hostentry = [
172
+ 'php' => null,
173
+ 'mysql' => null,
174
+ 'wordpress_db' => null,
175
+ 'filesystem' => null,
176
+ ];
177
+ }
178
+ $hostentry = array_merge(self::BENCHMARK_DISPLAY_DATA['benchmark-host'], $hostentry);
179
+
180
+ $result['graph_data']['host'] = $hostentry;
181
+
182
+ foreach ($baseline_benchmarks as $key => $benchmark){
183
+ $entry = [
184
+ 'php' => $benchmark['php']['total'],
185
+ 'mysql' => $benchmark['mysql'],
186
+ 'wordpress_db' => $benchmark['wordpress_db']['time'],
187
+ 'filesystem' => $benchmark['filesystem']
188
+ ];
189
+ $entry = array_merge(self::BENCHMARK_DISPLAY_DATA[$key], $entry);
190
+ $result['graph_data'][$key] = $entry;
191
+ }
192
+ $result['graphs']['webperformance'] = self::BENCHMARK_DISPLAY_DATA['webperformance'];
193
+ $result['graphs']['serverperformance'] = self::BENCHMARK_DISPLAY_DATA['serverperformance'];
194
+ $result['graphs']['tooltips'] = self::BENCHMARK_DISPLAY_DATA['hostingmatchup_tooltips'];
195
+
196
+ return $result;
197
+ }
198
+
199
+ public function get_frontend_benchmark($run = false) {
200
+ if ($run) {
201
+ $desktop_result = $this->benchmark->get_lighthouse_results('desktop');
202
+ $mobile_result = $this->benchmark->get_lighthouse_results('mobile');
203
+
204
+ if ($desktop_result['status'] != 'success' || $mobile_result['status'] != 'success') {
205
+ // then what? dunno.
206
+ }
207
+ }
208
+
209
+ $frontend_benchmarks = get_option('a2opt-benchmarks-frontend');
210
+ if ($frontend_benchmarks) {
211
+ $last_desktop = null;
212
+ $last_mobile = null;
213
+ $prev_desktop = null;
214
+ $prev_mobile = null;
215
+ $desktop_check_date = null;
216
+ $mobile_check_date = null;
217
+
218
+ foreach (array_reverse($frontend_benchmarks) as $check_date => $fbm) {
219
+ if ($fbm['strategy'] == 'desktop') {
220
+ if ($last_desktop == null) {
221
+ $desktop_check_date = $check_date;
222
+ $last_desktop = $fbm;
223
+ } elseif ($prev_desktop == null) {
224
+ $prev_desktop = $fbm;
225
+ }
226
+ } elseif ($fbm['strategy'] == 'mobile') {
227
+ if ($last_mobile == null) {
228
+ $mobile_check_date = $check_date;
229
+ $last_mobile = $fbm;
230
+ } elseif ($prev_mobile == null) {
231
+ $prev_mobile = $fbm;
232
+ }
233
+ }
234
+
235
+ if (isset($last_desktop) && isset($prev_desktop) && isset($last_mobile) && isset($prev_mobile) ) {
236
+ break;
237
+ }
238
+ }
239
+ // set these to false if no benchmarks
240
+ $result['pagespeed_desktop'] = $this->get_graph_data($desktop_check_date, $last_desktop, $prev_desktop);
241
+ $result['pagespeed_mobile'] = $this->get_graph_data($mobile_check_date, $last_mobile, $prev_mobile);
242
+ } else {
243
+ $desktop = [
244
+ "strategy" => "desktop",
245
+ "description" => null,
246
+ "scores" => [
247
+ "fcp" => 0,
248
+ "lcp" => 0,
249
+ "cls" => 0,
250
+ "fid" => 0,
251
+ "ttfb" => 0,
252
+ "audit_result" => [],
253
+ "overall_score" => 0
254
+ ]
255
+ ];
256
+
257
+ $mobile = [
258
+ "strategy" => "mobile",
259
+ "description" => null,
260
+ "scores" => [
261
+ "fcp" => 0,
262
+ "lcp" => 0,
263
+ "cls" => 0,
264
+ "fid" => 0,
265
+ "ttfb" => 0,
266
+ "audit_result" => [],
267
+ "overall_score" => 0
268
+ ]
269
+ ];
270
+ $result['pagespeed_desktop'] = $this->get_graph_data('None', $desktop, null);
271
+ $result['pagespeed_mobile'] = $this->get_graph_data('None', $mobile, null);
272
+ }
273
+
274
+ return $result;
275
+ }
276
+
277
+ public function get_opt_performance() {
278
+ $result = [];
279
+ $result['optimizations'] = $this->optimizations->get_optimizations();
280
+ $result['best_practices'] = $this->optimizations->get_best_practices();
281
+ $extra_settings = $result['optimizations']['extra_settings']; // has to be before $result['optimizations'] gets changed
282
+ $settings_tethers = $result['optimizations']['settings_tethers'];
283
+
284
+
285
+ $displayed_optimizations = [];
286
+ $other_optimizations = [];
287
+ $opt_counts = [];
288
+ $graphs = [];
289
+ $categories = ['performance', 'security', 'bestp'];
290
+
291
+ /* Setup initial counts */
292
+ foreach($categories as $cat){
293
+ $opt_counts[$cat]['active'] = 0;
294
+ $opt_counts[$cat]['total'] = 0;
295
+ }
296
+
297
+ /* Assign optimizations to display area and determine which are configured */
298
+ foreach($result['optimizations'] as $k => $optimization){
299
+ foreach($categories as $cat){
300
+ if(isset($optimization['category']) && $optimization['category'] == $cat){
301
+ if(isset($optimization['optional'])){
302
+ $other_optimizations[$cat][$k] = $optimization;
303
+ } else {
304
+ $displayed_optimizations[$cat][$k] = $optimization;
305
+ if($optimization['configured']){
306
+ $opt_counts[$cat]['active']++;
307
+ }
308
+ $opt_counts[$cat]['total']++;
309
+ }
310
+ }
311
+ }
312
+ }
313
+
314
+ foreach($result['best_practices'] as $key => $item){
315
+ $color_class = 'warn';
316
+ if(!$item['status']['is_warning']){
317
+ $color_class = 'success';
318
+ }
319
+ $result['best_practices'][$key]['color_class'] = $color_class;
320
+
321
+ if (!isset($item['slug'])){
322
+ $opt_counts['bestp']['total']++;
323
+ if ($color_class == 'success'){
324
+ $opt_counts['bestp']['active']++;
325
+ }
326
+ }
327
+ }
328
+
329
+ /* Determine circle colors */
330
+ foreach($categories as $cat){
331
+ $color_class = 'danger';
332
+ if($opt_counts[$cat]['active'] > 1){
333
+ $color_class = 'warn';
334
+ }
335
+ if($opt_counts[$cat]['active'] == $opt_counts[$cat]['total']){
336
+ $color_class = 'success';
337
+ }
338
+ if($opt_counts[$cat]['total'] == 0){
339
+ $opt_counts[$cat]['total'] = 1;
340
+ }
341
+ $graphs[$cat] = [
342
+ 'score' => ($opt_counts[$cat]['active'] / $opt_counts[$cat]['total']),
343
+ 'max' => 1, //todo not being used? otherwise, shouldn't it be $opt_counts[$cat]['total'] ?
344
+ 'text' => $opt_counts[$cat]['active'] . "/" . $opt_counts[$cat]['total'],
345
+ 'color_class' => $color_class,
346
+ ];
347
+ $graphs[$cat] = array_merge($graphs[$cat], self::BENCHMARK_DISPLAY_DATA['optimizations'][$cat]);
348
+
349
+ }
350
+
351
+ $result['graphs'] = $graphs;
352
+ $result['opt_counts'] = $opt_counts;
353
+ $result['optimizations'] = $displayed_optimizations;
354
+ $result['other_optimizations'] = $other_optimizations;
355
+ $result['extra_settings'] = $extra_settings;
356
+ $result['settings_tethers'] =$settings_tethers;
357
+ return $result;
358
+ }
359
+
360
+ public const BENCHMARK_DISPLAY_DATA = [
361
+ 'overall_score' => [
362
+ 'display_text' => 'Overall Score',
363
+ 'metric_text' => 'The Performance score is a weighted average of the metric scores.',
364
+ 'explanation' => 'The overall score measures how your website scores overall when looking at all metrics.
365
+ Metrics include: <br />
366
+ - Time to First Byte (TTFB)<br />
367
+ - Largest Contentful Paint (LCP)<br />
368
+ - First Input Delay (FID) <br />
369
+ - First Contentful Paint (FCP)<br />
370
+ - Cumulative Layout Shift (CLS)<br />
371
+ <br />
372
+ The higher your overall score, the better your website will perform.'
373
+ ],
374
+ 'ttfb' => [
375
+ 'display_text' => 'Server Speed',
376
+ 'metric_text' => 'Time to first Byte (TTFB)',
377
+ 'explanation' => 'Time to First Byte (TTFB) refers to the time between the browser requesting a page and when it receives the first byte of information from the server. The less time taken, the faster your website will load. For example, a website with a TTFB of 40 ms (milliseconds) will load faster than a website with a TTFB of 90 MLS.'
378
+ ],
379
+ 'fcp' => [
380
+ 'display_text' => 'User Perception',
381
+ 'metric_text' => 'First Contentful Paint (FCP)',
382
+ 'explanation' => 'First Contentful Paint (FCP) measures the time taken for the browser to provide the first feedback to the user that the page is actually loading. The shorter the time, the faster your website will load.'
383
+ ],
384
+ 'lcp' => [
385
+ 'display_text' => 'Page Load Speed',
386
+ 'metric_text' => 'Largest Contentful Paint (LCP)',
387
+ 'explanation' => 'We measure a website’s page load speed with “Largest Contentful Paint” (LCP). LCP represents how quickly the main content of a web page is loaded. Specifically, LCP measures the time from when the user initiates loading the page until the largest image or text block is rendered within the viewable area of the browser window. The shorter the time, the faster your website will load.'
388
+ ],
389
+ 'fid' => [
390
+ 'display_text' => 'Website Browser Speed',
391
+ 'metric_text' => 'First Input Delay (FID)',
392
+ 'explanation' => 'First Input Delay (FID) measures the time from when a user first interacts with your site (i.e. when they click a link, tap on a button, or use a custom, JavaScript-powered control) to the time when the browser is actually able to respond to that interaction. Your website will load faster if you can shorten your FID time.'
393
+ ],
394
+ 'cls' => [
395
+ 'display_text' => 'Visual Stability',
396
+ 'metric_text' => 'Cumulative Layout Shift (CLS)',
397
+ 'explanation' => 'Cumulative Layout Shift (CLS) is the unexpected shifting of webpage elements while the page is still loading. When elements suddenly change position while loading, it can cause the user to accidentally click the wrong link on your webpage resulting in a bad user experience. CLS is an important ranking factor for search engines such as Google, and a bad user experience can negatively impact your website\'s SEO.'
398
+ ],
399
+ 'recommendations' => [
400
+ 'display_text' => 'Opportunity',
401
+ 'metric_text' => 'Areas that can be improved',
402
+ 'explanation' => 'These suggestions can help your page load faster. They don\'t directly affect the Performance score.',
403
+ ],
404
+ 'benchmark-host' => [
405
+ 'display_text' => 'Your Host',
406
+ 'metric_text' => '',
407
+ 'explanation' => 'this is your pathetic slow host',
408
+ 'color_class' => 'thishost'
409
+ ],
410
+ 'a2hosting-turbo' => [
411
+ 'display_text' => 'Turbo Boost',
412
+ 'metric_text' => '',
413
+ 'explanation' => 'fast as lightning',
414
+ 'color_class' => 'warn'
415
+ ],
416
+ 'a2hosting-mwp' => [
417
+ 'display_text' => 'Managed Wordpress',
418
+ 'metric_text' => '',
419
+ 'explanation' => 'this is your pathetic slow host',
420
+ 'color_class' => 'success'
421
+ ],
422
+ 'webperformance' => [
423
+ 'display_text' => 'Web Performance',
424
+ 'metric_text' => 'How does your hosting provider compare to A2 Hosting?',
425
+ 'legend_text' => "Overall Wordpress Execution Time",
426
+ 'explanation' => 'The web performance score measures how your current host performs compared to A2 Hosting. This web performance score looks at server speed and other metrics to determine how fast your website will load, based on which hosting company & plan you host your website with. <br />
427
+
428
+ The lower the score on the graph the faster your website will load. Not all hosting companies and plans use the same hardware. A2 Hosting uses the best server hardware on the market, focusing on speed & security. A2 Hosting also offers free site migration to help you move your existing websites to them. ',
429
+ 'color_class' => 'success'
430
+ ],
431
+ 'serverperformance' => [
432
+ 'display_text' => 'Server Performance',
433
+ 'metric_text' => "How fast is your hosting provider compare to A2 Hosting's server?",
434
+ 'legend_text' => "PHP, Mysql, and File I/O Response Time Comparison",
435
+ 'explanation' => 'The lower the scores on the graph, the faster your experience will be in the WordPress Admin dashboard and on pages that use dynamic content that can\'t be easily cached—like search forms and shopping carts. <br />
436
+ Not all hosting companies and plans use the same hardware. If your current host has a lower server performance score than A2 Hosting, then consider moving your websites to A2 Hosting. A2 Hosting uses the best server hardware on the market, focusing on speed & security. A2 Hosting also offers free site migration to help you move your existing websites to them.',
437
+ 'color_class' => 'success'
438
+ ],
439
+ 'optimizations' => [
440
+ 'performance' => [
441
+ 'display_text' => 'Performance',
442
+ 'metric_text' => "Optimizations that will help your performance.",
443
+ 'legend_text' => '',
444
+ 'explanation' => ''
445
+ ],
446
+ 'security' => [
447
+ 'display_text' => 'Security',
448
+ 'metric_text' => "Optimizations that will help your security.",
449
+ 'legend_text' => '',
450
+ 'explanation' => ''
451
+ ],
452
+ 'bestp' => [
453
+ 'display_text' => 'Best Practices',
454
+ 'metric_text' => "Optimizations that bring things in line with current best practices.",
455
+ 'legend_text' => '',
456
+ 'explanation' => ''
457
+ ],
458
+ ],
459
+ 'hostingmatchup_tooltips' => [
460
+ 'wordpress_db' => 'Wordpress Database Response Time',
461
+ 'filesystem' => 'Server Disk Response Time',
462
+ 'mysql' => 'MYSQL Query Response Time',
463
+ 'php' => 'PHP Response Time'
464
+ ]
465
+
466
+ ];
467
+
468
+ public const BENCHMARK_SCORE_PROFILES = [
469
+ //higher is better [low/med/high] so we will invert the score when checking
470
+ 'overall_score' => ['success'=>100, 'warn'=>89, 'danger'=>49, 'max'=>100, 'decimalplaces'=>0],
471
+ 'overall_score_inverted' => ['success'=>0, 'warn'=>11, 'danger'=>51, 'decimalplaces'=>0],
472
+
473
+ //lower is better [high/med/low]
474
+ 'fcp' => ['success'=> 1999, 'warn'=>3999, 'danger'=>6000, 'max'=>6000, 'decimalplaces'=>0],
475
+ 'ttfb' => ['success'=> 99, 'warn'=>599, 'danger'=>1000, 'max'=>1000, 'decimalplaces'=>0],
476
+ 'cls' => ['success'=> 0.1, 'warn'=>0.25, 'danger'=>1, 'max'=>1, 'decimalplaces'=>2],
477
+ 'lcp' => ['success'=> 2499, 'warn'=>3999, 'danger'=>6000, 'max'=>6000, 'decimalplaces'=>0],
478
+ 'fid' => ['success'=> 99, 'warn'=>299, 'danger'=>1000, 'max'=>1000, 'decimalplaces'=>0],
479
+ ];
480
+
481
+ public function get_score_status_and_thresholds($metric, $score) {
482
+ // invert values when needed
483
+ $thresholds = self::BENCHMARK_SCORE_PROFILES[$metric];
484
+ $display_thresholds = $thresholds;
485
+ if ($metric == 'overall_score') {
486
+ $score = $thresholds['success'] - $score;
487
+ $thresholds = self::BENCHMARK_SCORE_PROFILES[$metric . '_inverted'];
488
+ }
489
+
490
+ $status = 'success';
491
+ if ($score >= $thresholds['warn']) {
492
+ $status = 'warn';
493
+ }
494
+ if ($score >= $thresholds['danger']) {
495
+ $status = 'danger';
496
+ }
497
+
498
+ return [
499
+ 'status' => $status,
500
+ 'thresholds' => $display_thresholds
501
+ ];
502
+ }
503
+
504
+ public function get_readable_last_check_date($last_check_date){
505
+ if ($last_check_date == 'None'){
506
+ return $last_check_date;
507
+ }
508
+ else {
509
+ return human_time_diff(strtotime($last_check_date)) . " ago";
510
+ }
511
+ }
512
+
513
+ public function get_graph_data($last_check_date, $latest, $previous) {
514
+ $metrics = ['overall_score', 'fcp', 'ttfb', 'cls','lcp', 'fid'];
515
+
516
+ $result = [];
517
+ foreach ($metrics as $metric) {
518
+ $latest_score = $latest['scores'][$metric];
519
+ if(is_array($previous) && is_array($previous['scores'])){
520
+ $previous_score = $previous['scores'][$metric];
521
+ } else {
522
+ $previous_score = 0;
523
+ }
524
+
525
+ /*
526
+ // round test
527
+ $latest_score += 0.14234636236256256;
528
+ $previous_score += 0.0990809856203465203;
529
+ // color test
530
+ $latest_score = rand(0, $status_info['thresholds']['max']);
531
+ $previous_score = rand(0, $status_info['thresholds']['max']);
532
+ */
533
+
534
+ $status_info = $this->get_score_status_and_thresholds($metric, $latest_score);
535
+ if ($last_check_date == 'None'){
536
+ $status_info['status'] = 'empty';
537
+ }
538
+
539
+
540
+ $decimalplaces = self::BENCHMARK_SCORE_PROFILES[$metric]['decimalplaces'];
541
+ $latest_score = round($latest_score, $decimalplaces);
542
+ $data = [
543
+ 'last_check_date' => $this->get_readable_last_check_date($last_check_date),
544
+ 'score' => $latest_score,
545
+ 'max' => $status_info['thresholds']['max'],
546
+ 'text' => "{$latest_score}",
547
+ 'color_class' => $status_info['status'],
548
+ 'thresholds' => $status_info['thresholds'],
549
+ 'explanation' => 'Here is a detailed explanation of what the ' . $metric . ' means, as rendered lovingly by George'
550
+ ];
551
+
552
+ $direction = 'none';
553
+ $percent_change = 0;
554
+ $diff = $latest_score - $previous_score;
555
+ if ($diff != 0) {
556
+ if ($diff < 0) {
557
+ $direction = 'down';
558
+ } elseif ($diff > 0) {
559
+ $direction='up';
560
+ }
561
+ $diff = abs($diff);
562
+ $diff = round($diff, $decimalplaces);
563
+ $percent_change = $diff; // i'm not really sure what formula they want us to use for this
564
+ }
565
+ $data['last_check_percent'] = $percent_change;
566
+ $data['last_check_dir'] = $direction;
567
+
568
+ // pull in display data
569
+ $data = array_merge($data, self::BENCHMARK_DISPLAY_DATA[$metric]);
570
+ $result[$metric] = $data;
571
+
572
+ $audits = [];
573
+ $lcv = 0;
574
+ $pattern = "/\[([^]]*)\] *\(([^)]*)\)/i";
575
+ $replacement = '<a href="$2" target="_blank">$1</a>';
576
+ if(is_array($latest['scores']) && is_array($latest['scores']['audit_result'])){
577
+ foreach ($latest['scores']['audit_result'] as $audit) {
578
+ $display_value = '';
579
+ $description = preg_replace($pattern, $replacement, $audit['description']);
580
+ if(isset($audit['displayValue'])){
581
+ $description .= '<br />' . $audit['displayValue'];
582
+ }
583
+ $audits[] = [
584
+ 'lcv' => $lcv,
585
+ 'display_text' => $audit['title'],
586
+ 'description' => $description,
587
+ ];
588
+ ++$lcv;
589
+ if ($lcv > 4) {
590
+ break;
591
+ }
592
+ }
593
+ }
594
+ $result['recommendations'] = [
595
+ 'list' => $audits
596
+ ];
597
+
598
+ $result['recommendations'] = array_merge($result['recommendations'], self::BENCHMARK_DISPLAY_DATA['recommendations']);
599
+ }
600
+
601
+ return $result;
602
+ }
603
+
604
+ /**
605
+ * Register settings
606
+ *
607
+ * @since 3.0.0
608
+ */
609
+ public function register_settings() {
610
+ // The settings container.
611
+ register_setting(
612
+ Settings_Model::SETTINGS_NAME, // Option group Name.
613
+ Settings_Model::SETTINGS_NAME, // Option Name.
614
+ [ $this, 'sanitize' ] // Sanitize.
615
+ );
616
+ }
617
+
618
+ /**
619
+ * Validates submitted setting values before they get saved to the database.
620
+ *
621
+ * @param array $input Settings Being Saved.
622
+ * @since 3.0.0
623
+ * @return array
624
+ */
625
+ public function sanitize($input) {
626
+ $new_input = [];
627
+ if ( isset( $input ) && ! empty( $input ) ) {
628
+ $new_input = $input;
629
+ }
630
+
631
+ return $new_input;
632
+ }
633
+
634
+ /**
635
+ * Returns the option key used to store the settings in database
636
+ *
637
+ * @since 3.0.0
638
+ * @return string
639
+ */
640
+ public function get_plugin_settings_option_key() {
641
+ return Settings_Model::get_plugin_settings_option_key();
642
+ }
643
+
644
+ /**
645
+ * Retrieves all of the settings from the database
646
+ *
647
+ * @param string $setting_name Setting to be retrieved.
648
+ * @since 3.0.0
649
+ * @return array
650
+ */
651
+ public function get_setting($setting_name) {
652
+ return Settings_Model::get_setting( $setting_name );
653
+ }
654
+ }
655
+ }
app/models/admin/class-base-model.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace A2_Optimized\App\Models\Admin;
3
+
4
+ use A2_Optimized\Core\Model;
5
+
6
+ if ( ! class_exists( __NAMESPACE__ . '\\' . 'Base_Model' ) ) {
7
+ /**
8
+ * Blueprint for Admin related Models. All Admin Models should extend this Base_Model
9
+ *
10
+ * @since 3.0.0
11
+ * @package A2_Optimized
12
+ * @subpackage A2_Optimized/Models/Admin
13
+ */
14
+ abstract class Base_Model extends Model {
15
+
16
+
17
+ /**
18
+ * Register callbacks for actions and filters. Most of your add_action/add_filter
19
+ * go into this method.
20
+ *
21
+ * NOTE: register_hook_callbacks method is not called automatically. You
22
+ * as a developer have to call this method where you see fit. For Example,
23
+ * You may want to call this in constructor, if you feel hooks/filters
24
+ * callbacks should be registered when the new instance of the class
25
+ * is created.
26
+ *
27
+ * The purpose of this method is to set the convention that first place to
28
+ * find add_action/add_filter is register_hook_callbacks method.
29
+ *
30
+ * This method is not marked abstract because it may not be needed in every
31
+ * model. Making it abstract would enforce every child class to implement
32
+ * the method.
33
+ *
34
+ * If I were you, I would define register_hook_callbacks method in the child
35
+ * class when it is a 'Model only' route. This is not a rule, it
36
+ * is just my opinion when I would define this method.
37
+ *
38
+ * @since 3.0.0
39
+ */
40
+ protected function register_hook_callbacks(){}
41
+
42
+ }
43
+
44
+ }
app/models/class-settings.php ADDED
@@ -0,0 +1,132 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace A2_Optimized\App\Models;
3
+
4
+ use A2_Optimized as A2_Optimized;
5
+ use A2_Optimized\Core\Model;
6
+
7
+ if ( ! class_exists( __NAMESPACE__ . '\\' . 'Settings' ) ) {
8
+ /**
9
+ * Implements operations related to Plugin Settings.
10
+ *
11
+ * @since 3.0.0
12
+ * @package A2_Optimized
13
+ * @subpackage A2_Optimized/Models
14
+ */
15
+ class Settings extends Model {
16
+
17
+ const SETTINGS_NAME = A2_Optimized::PLUGIN_ID;
18
+
19
+ /**
20
+ * Holds all Settings
21
+ *
22
+ * @var array
23
+ * @since 3.0.0
24
+ */
25
+ protected static $settings;
26
+
27
+ /**
28
+ * Returns the Option name/key saved in the database
29
+ *
30
+ * @return string
31
+ * @since 3.0.0
32
+ */
33
+ public static function get_plugin_settings_option_key() {
34
+ return Settings::SETTINGS_NAME;
35
+ }
36
+
37
+ /**
38
+ * Helper method that retuns all Saved Settings related to Plugin
39
+ *
40
+ * @return array
41
+ * @since 3.0.0
42
+ */
43
+ public static function get_settings() {
44
+ if ( ! isset( static::$settings ) ) {
45
+ static::$settings = get_option( static::SETTINGS_NAME, array() );
46
+ }
47
+
48
+ return static::$settings;
49
+ }
50
+
51
+ /**
52
+ * Helper method that returns a individual setting
53
+ *
54
+ * @param string $setting_name Setting to be retrieved.
55
+ * @return mixed
56
+ * @since 3.0.0
57
+ */
58
+ public static function get_setting( $setting_name ) {
59
+ $all_settings = static::get_settings();
60
+
61
+ return isset( $all_settings[ $setting_name ] ) ? $all_settings[ $setting_name ] : array();
62
+ }
63
+
64
+ /**
65
+ * Helper method to delete all settings related to plugin
66
+ *
67
+ * @return void
68
+ * @since 3.0.0
69
+ */
70
+ public static function delete_settings() {
71
+ static::$settings = [];
72
+ delete_option( static::SETTINGS_NAME );
73
+ }
74
+
75
+ /**
76
+ * Helper method to delete a specific setting
77
+ *
78
+ * @param string $setting_name Setting to be Deleted.
79
+ * @return void
80
+ * @since 3.0.0
81
+ */
82
+ public static function delete_setting( $setting_name ) {
83
+ $all_settings = static::get_settings();
84
+
85
+ if ( isset( $all_settings[ $setting_name ] ) ) {
86
+ unset( $all_settings[ $setting_name ] );
87
+ static::$settings = $all_settings;
88
+ update_option( static::SETTINGS_NAME, $all_settings );
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Helper method to Update Settings
94
+ *
95
+ * @param array $new_settings New Setting Values to store.
96
+ * @return void
97
+ * @since 3.0.0
98
+ */
99
+ public static function update_settings( $new_settings ) {
100
+ $all_settings = static::get_settings();
101
+ $updated_settings = array_merge( $all_settings, $new_settings );
102
+ static::$settings = $updated_settings;
103
+ update_option( static::SETTINGS_NAME, $updated_settings );
104
+ }
105
+
106
+ /**
107
+ * Helper method Update Single Setting
108
+ *
109
+ * Similar to update_settings, this function won't by called anywhere automatically.
110
+ * This is a custom helper function to delete individual setting. You can
111
+ * delete this method if you don't want this ability.
112
+ *
113
+ * @param string $setting_name Setting to be Updated.
114
+ * @param mixed $setting_value New value to set for that setting.
115
+ * @return void
116
+ * @since 3.0.0
117
+ */
118
+ public static function update_setting( $setting_name, $setting_value ) {
119
+ static::update_setting( [ $setting_name => $setting_value ] );
120
+ }
121
+
122
+ public static function get_nav_class($nav_data, $nav_token)
123
+ {
124
+ if (isset($nav_data[$nav_token])){
125
+ return $nav_data[$nav_token];
126
+ }
127
+ return '';
128
+ }
129
+
130
+ }
131
+
132
+ }
app/templates/admin/errors/admin-notice.php ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ <div class="error">
2
+
3
+ <p><?php echo esc_html( $admin_notice ); ?></p>
4
+
5
+ </div>
app/templates/admin/errors/requirements-error.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="error">
2
+
3
+ <p>Your environment doesn't meet the system requirements listed below. Therefore <strong>A2 Optimized</strong> has been <strong>deactivated.</strong></p>
4
+
5
+ <ul class="ul-disc">
6
+ <?php foreach ( $errors as $error ) : ?>
7
+ <li>
8
+ <strong><?php echo esc_html( $error->error_message ); ?></strong>
9
+ <em><?php echo esc_html( $error->supportive_information ); ?></em>
10
+ </li>
11
+ <?php endforeach; ?>
12
+ </ul>
13
+
14
+ </div>
app/templates/admin/page-settings/page-settings-fields.php ADDED
@@ -0,0 +1 @@
 
1
+ <input type="text" id="<?php echo esc_attr( $field_id ); ?>" name="<?php echo esc_attr( $settings_name . '[' . $field_id . ']' ); ?>" value="<?php echo esc_attr( $settings_value ); ?>" />
app/templates/admin/page-settings/page-settings.php ADDED
@@ -0,0 +1,893 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="wrap">
2
+ <script>
3
+ let page_data = <?php echo $data['data_json'] ?>;
4
+ page_data.login_url = '<?php echo esc_url(get_home_url()) . "/wp-login.php" ?>';
5
+ page_data.show_coaching = false;
6
+ page_data.showModal = false;
7
+ page_data.modalMsg = '';
8
+ page_data.openModal = function(msg){
9
+ page_data.showModal = true;
10
+ page_data.modalMsg = msg;
11
+ }
12
+ page_data.closeModal = function(){
13
+ page_data.showModal = false;
14
+ page_data.modalMsg = '';
15
+ }
16
+ page_data.showA2Only = false;
17
+ page_data.yesNoDialog = {
18
+ showYesNo: false,
19
+ message: 'default',
20
+ doYes: () => {
21
+ if (page_data.yesNoDialog.yesAction){
22
+ page_data.yesNoDialog.yesAction();
23
+ }
24
+ page_data.yesNoDialog.showYesNo = false;
25
+ },
26
+ doNo: () => {
27
+ if (page_data.yesNoDialog.noAction){
28
+ page_data.yesNoDialog.noAction();
29
+ }
30
+ page_data.yesNoDialog.showYesNo = false;
31
+ },
32
+ noAction: null,
33
+ yesAction: null,
34
+ };
35
+ </script>
36
+
37
+ <script type="text/x-template" id="info-button-template">
38
+ <div class="info-toggle-button">
39
+ <span @click="toggleInfoDiv(metric, $event);"><span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span></span>
40
+ </div>
41
+ </script>
42
+
43
+ <script type="text/x-template" id="flip-panel-template">
44
+ <div :id="content_id" class="flip-card">
45
+ <div class="flip-card-inner">
46
+ <div class="flip-card-front">
47
+ <div class="box-element" :class="[additional_classes, status_class]">
48
+ <div v-if="!disable_show_button" class="info-toggle-button" title="More Information">
49
+ <span @click="toggleFlipPanel(content_id, $event);"><span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span></span>
50
+ </div>
51
+ <slot name="content1"></slot>
52
+ </div>
53
+ </div>
54
+ <div class="flip-card-back" style="display:none;">
55
+ <div class="box-element" :class="[additional_classes, status_class]">
56
+ <div class="info-toggle-button" title="Close">
57
+ <span @click="toggleFlipPanel(content_id, $event);"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></span>
58
+ </div>
59
+ <slot name="content2"></slot>
60
+ </div>
61
+ </div>
62
+ </div>
63
+ </div>
64
+ </script>
65
+ <!--
66
+ <script type="text/x-template" id="flip-panel-template">
67
+ <div :id="content_id" class="box-element" :class="status_class" class="flip-card flip-card-inner">
68
+ <div class="info-toggle-button">
69
+ <span @click="toggleFlipPanel($event);"><span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span></span>
70
+ </div>
71
+ <div v-show="content_index == 0" class="graph-data flip-card-front">
72
+ <slot name="content1"></slot>
73
+ </div>
74
+ <div v-show="content_index == 1" class="graph-info flip-card-back">
75
+ <slot name="content2"></slot>
76
+ </div>
77
+ </div>
78
+ </script>
79
+ -->
80
+
81
+ <script type="text/x-template" id="graph-legend-template">
82
+ <div class="col-sm-10 graph-legend ">
83
+ <div class="row graph-legend-header">
84
+ <div class="col-sm-4 success">
85
+ good
86
+ </div>
87
+ <div class="col-sm-4 warn">
88
+ not good
89
+ </div>
90
+ <div class="col-sm-4 danger">
91
+ bad
92
+ </div>
93
+ </div>
94
+ <div class="row">
95
+ <div class="col-sm-4">
96
+ &nbsp;
97
+ </div>
98
+ <div class="col-sm-4 left-label">
99
+ <span>&nbsp;{{thresholds.warn}}</span>
100
+ </div>
101
+ <div class="col-sm-4 left-label">
102
+ <span>&nbsp;{{thresholds.danger}}</span>
103
+ </div>
104
+ </div>
105
+ </div>
106
+ </script>
107
+
108
+ <script type="text/x-template" id="speed-metric-card-template">
109
+ <flip-panel :content_id="'graph-' + metric_name"
110
+ :status_class="metric.color_class"
111
+ :additional_classes="'normal graph-card ' + (show_wave == 'true' ? 'wave-bg ' : '')">
112
+ <template v-slot:content1>
113
+ <div class="row">
114
+ <div class="col-sm-10">
115
+ <h4>{{metric.display_text}}</h4>
116
+ <p class="sub-heading">{{metric.metric_text}}</p>
117
+ </div>
118
+ </div>
119
+ <div v-if="show_line == 'true'" class="row">
120
+ <div class="col-sm-10">
121
+ <div class="circle" :id="'circles-' + metric_name"></div>
122
+ <div class="line-graph" :id="'line-graph-' + metric_name"></div>
123
+ </div>
124
+ </div>
125
+ <div v-else class="row">
126
+ <div class="col-sm-6">
127
+ <div class="circle" :id="'circles-' + metric_name"></div>
128
+ </div>
129
+ <div class="col-sm-6">
130
+ <span class="glyphicon" :class="['glyphicon-arrow-' + metric.last_check_dir,metric.color_class]" style="font-size: 2em;"></span>
131
+ <br>
132
+ <span :class="metric.color_class">{{metric.last_check_percent}}</span>
133
+ <span>vs <br> last check</span>
134
+ </div>
135
+ </div>
136
+ <div v-if="show_legend == 'true'" class="row">
137
+ <graph-legend :metric='metric_name'></graph-legend>
138
+ </div>
139
+ <div v-if="show_wave == 'true'" class="row graph-card_bottom" style="min-height: 50px;">
140
+ &nbsp;
141
+ </div>
142
+ </template>
143
+ <template v-slot:content2>
144
+ <div class="row">
145
+ <div class="col-sm-10">
146
+ <h4>{{metric.display_text}}</h4>
147
+ <p>{{metric.explanation}}</p>
148
+ </div>
149
+ </div>
150
+ </template>
151
+ </flip-panel>
152
+ </script>
153
+
154
+ <script type="text/x-template" id="hosting-matchup-template">
155
+ <div class="col-sm-12">
156
+ <div class="row">
157
+ <div class="col-md-12 col-lg-2 side-nav">
158
+ <div class="col-md-5 col-md-offset-1 col-lg-12 col-lg-offset-0 navlink-wrapper">
159
+ <button type="button" @click="$emit('nav-change-url', 'admin.php?page=a2-optimized&a2_page=server_performance')"
160
+ class="navlink-button" :class="nav.webperf_class">Web Performance</button>
161
+ </div>
162
+ <div class="col-md-5 col-md-offset-1 col-lg-12 col-lg-offset-0 navlink-wrapper">
163
+ <button type="button" @click="$emit('nav-change-url', 'admin.php?page=a2-optimized&a2_page=hosting_matchup')"
164
+ class="navlink-button" :class="nav.hmatch_class">Hosting Matchup</button>
165
+ </div>
166
+ </div>
167
+ <div class="col-md-12 col-lg-10 border-left" id="a2-optimized-hostingmatchup">
168
+ <div class="row">
169
+ <div class="col-sm-12">
170
+ <a class="btn cta-btn-green" @click="pageSpeedCheck()">Run Check</a> <span class="last-check">Last Check: {{ last_check_date }}</span>
171
+ </div>
172
+ </div>
173
+ <div v-if="show_coaching" class="row">
174
+ <div class="col-sm-12">
175
+ <div class="notice notice-warning"><p>Click Run Check to see the overall performance of your site.</p></div>
176
+ </div>
177
+ </div>
178
+ <div class="row padding-bottom"></div>
179
+ <div class="row">
180
+ <div class="col-md-6 col-md-offset-3 col-lg-6 col-lg-offset-0 hosting-matchup-graph-container">
181
+ <flip-panel content_id="graph-webperformance"
182
+ status_class="success"
183
+ additional_classes="">
184
+ <template v-slot:content1>
185
+ <div class="row">
186
+ <div class="col-sm-11 col-sm-offset-1">
187
+ <h4>{{graphs.webperformance.display_text}}</h4>
188
+ <p>{{graphs.webperformance.metric_text}}</p>
189
+ </div>
190
+ </div>
191
+ <div class="row" style="max-height:500px;">
192
+ <div v-if="graphs" class="col-sm-11 col-sm-offset-1">
193
+ <canvas id="overall_wordpress_canvas" width="400" height="400"></canvas>
194
+ </div>
195
+ <div v-else>
196
+ <p>&nbsp; no data yet</p>
197
+ </div>
198
+ </div>
199
+ </template>
200
+ <template v-slot:content2>
201
+ <div class="row">
202
+ <div class="col-sm-11 col-sm-offset-1">
203
+ <h4>{{graphs.webperformance.display_text}}</h4>
204
+ <p>{{graphs.webperformance.metric_text}}</p>
205
+ </div>
206
+ </div>
207
+ <div class="row">
208
+ <div class="col-sm-10 col-sm-offset-1">
209
+ <p><span v-html="graphs.webperformance.explanation"></span></p>
210
+ </div>
211
+ </div>
212
+ </template>
213
+ </flip-panel>
214
+ </div>
215
+ <div class="col-md-6 col-md-offset-3 col-lg-6 col-lg-offset-0 hosting-matchup-graph-container">
216
+ <flip-panel content_id="graph-serverperformance"
217
+ status_class="success"
218
+ additional_classes="">
219
+ <template v-slot:content1>
220
+ <div class="row">
221
+ <div class="col-sm-11 col-sm-offset-1">
222
+ <h4>{{graphs.serverperformance.display_text}}</h4>
223
+ <p>{{graphs.serverperformance.metric_text}}</p>
224
+ </div>
225
+ </div>
226
+ <div class="row" style="max-height:500px">
227
+ <div v-if="graphs" class="col-sm-11 col-sm-offset-1">
228
+ <canvas id="server_perf_canvas" width="400" height="400"></canvas>
229
+ </div>
230
+ <div v-else>
231
+ <p>&nbsp; no data yet</p>
232
+ </div>
233
+ </div>
234
+ </template>
235
+ <template v-slot:content2>
236
+ <div class="row">
237
+ <div class="col-sm-11 col-sm-offset-1">
238
+ <h4>{{graphs.serverperformance.display_text}}</h4>
239
+ <p>{{graphs.serverperformance.metric_text}}</p>
240
+ </div>
241
+ </div>
242
+ <div class="row">
243
+ <div class="col-sm-10 col-sm-offset-1">
244
+ <p><span v-html="graphs.serverperformance.explanation"></span></p>
245
+ </div>
246
+ </div>
247
+ </template>
248
+ </flip-panel>
249
+ </div>
250
+ </div>
251
+ </div>
252
+ </div>
253
+ </div>
254
+ </script>
255
+
256
+ <script type="text/x-template" id="optimization-entry">
257
+ <div class="row">
258
+ <div class="col-md-8 col-lg-9 ">
259
+ <h4>{{ name }} <a class="glyphicon glyphicon-chevron-down toggle" aria-hidden="true" v-on:click.prevent="desc_toggle(slug)" :id="'opt_item_toggle_' + slug"></a></h4>
260
+ <div :id="'opt_item_desc_' + slug" style="display: none" v-html="description" class="desc"></div>
261
+ <div :id="'opt_item_error_' + slug" v-if="error" v-html="error" style="border: 2px solid red;"></div>
262
+ </div>
263
+ <div class="col-md-1 col-lg-1 padding-top-30">
264
+ <a v-if="extra_setting" href="javascript:void(0)" @click="toggleExtraSettings(slug, $event)">Modify</a>
265
+ </div>
266
+ <div class="col-md-3 col-lg-2 padding-top-30" >
267
+ <li class="tg-list-item" @click="optimizationClicked(disabled)" @change="settingToggled($event)">
268
+ <input class="tgl tgl-ios" :id="'toggle-' + slug" :name="slug" v-model="configured" true-value="true" false-value="false" type="checkbox" :disabled="disabled"/>
269
+ <label class="tgl-btn" :for="'toggle-' + slug"></label>
270
+ </li>
271
+ </div>
272
+ </div>
273
+ </script>
274
+
275
+ <script type="text/x-template" id="opt-extra-settings-template">
276
+ <div v-if="opt_group" :key="selected_slug">
277
+ <div class="row header">
278
+ <div class="col-lg-8">
279
+ <h3>{{ opt_group.title }}</h3>
280
+ </div>
281
+ </div>
282
+ <div v-for="section in opt_group.settings_sections" class="padding-15 opt-extra-settings-items">
283
+ <div class="row">
284
+ <div class="col-lg-10">
285
+ <h4 v-if="section.title" class="less-vertical-space section-title">{{ section.title}}</h4>
286
+ </div>
287
+ </div>
288
+ <div v-for="(setting, setting_name) in section.settings" :key="setting_name" :id="'setting-' + setting_name" class="setting-item">
289
+ <div class="row">
290
+ <div v-if="setting.extra_fields">
291
+ <div class="col-md-6 col-lg-6">
292
+ <h4 class="less-vertical-space setting-desc-extra">{{ setting.description }}</h4>
293
+ </div>
294
+ <div class="col-md-3 col-lg-4">
295
+ <div v-for="(field, field_name) in setting.extra_fields">
296
+ <input :name="field_name" :id="field_name" :type="field.input_type" v-model="field.value"></input>
297
+ </div>
298
+ </div>
299
+ </div>
300
+ <div v-else>
301
+ <div class="col-md-9">
302
+ <h4 class="less-vertical-space setting-desc">{{ setting.description }}</h4>
303
+ </div>
304
+ </div>
305
+ <p v-if="setting.input_type == 'text'">
306
+ <input type="text" :id="'cb-' + setting_name" :name="setting_name" v-model="setting.value" class="opt-setting-input text-input"/>
307
+ </p>
308
+ <div v-else-if="setting.input_type == 'options'" class="col-md-3">
309
+ <select :id="'select-' + setting_name" :name="setting_name" v-model="setting.value" @change="adjustSettingVisibility()">
310
+ <option v-for="(opt_value,label) in setting.input_options" :value="opt_value" :selected="opt_value == setting.value">{{ label }}</option>
311
+ </select>
312
+ </div>
313
+ <div v-else class="col-md-3 col-lg-2 text-right" :class="setting.extra_fields ? '' : 'col-lg-offset-1'">
314
+ <li class="tg-list-item">
315
+ <input class="tgl tgl-ios" :id="'toggle-' + setting_name" :name="setting_name"
316
+ true-value="true" false-value="false" v-model="setting.value" type="checkbox"/>
317
+ <label class="tgl-btn" :for="'toggle-' + setting_name"></label>
318
+ </li>
319
+ </div>
320
+ </div>
321
+ <div class="row">
322
+ <div class="col-lg-10">
323
+ {{ setting.explanation }}
324
+ </div>
325
+ </div>
326
+ </div>
327
+ </div>
328
+ </div>
329
+ </script>
330
+
331
+ <script type="text/x-template" id="optimizations-performance-template">
332
+ <div class="col-sm-12">
333
+ <div class="row">
334
+ <div class="col-md-12 col-lg-2 side-nav">
335
+ <div id='optperf-wrapper' class="col-md-3 col-lg-12 navlink-wrapper">
336
+ <button type="button" v-on:click.prevent="updateNavLinks('optperf')"
337
+ class="navlink-button" :class="[sidenav == 'optperf' ? 'current' : '']">Performance</button>
338
+ </div>
339
+ <div id='optsec-wrapper' class="col-md-3 col-md-offset-1 col-lg-12 col-lg-offset-0 navlink-wrapper">
340
+ <button type="button" v-on:click.prevent="updateNavLinks('optsec')"
341
+ class="navlink-button" :class="[sidenav == 'optsec' ? 'current' : '']">Security</button>
342
+ </div>
343
+ <div id='optbestp-wrapper' class="col-md-3 col-md-offset-1 col-lg-12 col-lg-offset-0 navlink-wrapper">
344
+ <button type="button" v-on:click.prevent="updateNavLinks('optbestp')"
345
+ class="navlink-button" :class="[sidenav == 'optbestp' ? 'current' : '']">Best Practices</button>
346
+ </div>
347
+ <!--
348
+ <div class="col-md-4 col-lg-12 navlink-wrapper" :class="nav.optresult_class">
349
+ <a name='optresults' v-on:click.prevent="updateNavLinks('optresults')" class="navlink">Results</a>
350
+ </div> -->
351
+ </div>
352
+ <div class="col-md-12 col-lg-10 border-left" id="a2-optimized-opt_performance">
353
+ <!-- Performance -->
354
+ <div class="row" v-show="sidenav == 'optperf'">
355
+ <div class="col-sm-9">
356
+ <flip-panel content_id="optimizations_performance_front"
357
+ status_class="success"
358
+ additional_classes=""
359
+ disable_show_button=true>
360
+ <template v-slot:content1>
361
+ <div class="padding-15">
362
+ <h3>Optimization Essentials</h3>
363
+ <optimization-entry v-for="optimization in optimizations.performance" :key="optimization.slug" :opt="optimization" wrapper_id="optimizations_performance_front"></optimization-entry>
364
+ <div class="row" v-show="perf_more == 'false'">
365
+ <div class="col-sm-12 text-center">
366
+ <p><a href="#" class="more-optimizations-toggle" @click.prevent="perf_more = 'true'">More Optimizations</a></p>
367
+ </div>
368
+ </div>
369
+ <optimization-entry v-show="perf_more == 'true'" v-for="optimization in other_optimizations.performance" :key="optimization.slug" :opt="optimization" wrapper_id="optimizations_performance_front"></optimization-entry>
370
+ <div class="row" v-show="perf_more == 'true'">
371
+ <div class="col-sm-12 text-center">
372
+ <p><a href="#" class="more-optimizations-toggle" @click.prevent="perf_more = 'false'">Less Optimizations</a></p>
373
+ </div>
374
+ </div>
375
+ </div>
376
+ </template>
377
+ <template v-slot:content2>
378
+ <opt-extra-settings :extra_settings="extra_settings">
379
+ </opt-extra-settings>
380
+ </template>
381
+ </flip-panel>
382
+ </div>
383
+ <div class="col-sm-3">
384
+ <div class="opt-completed">
385
+ <h4><span>Completed</span><br />Performance<br />Optimization</h4>
386
+ <div class="row">
387
+ <div class="col-sm-6 col-sm-offset-3">
388
+ <div class="box-element hide-small" style="padding-top: 5px;">
389
+ <div class="circle" id="circles-opt-perf"></div>
390
+ </div>
391
+ </div>
392
+ </div>
393
+ </div>
394
+ </div>
395
+ </div>
396
+
397
+ <!-- Security -->
398
+ <div class="row" v-show="sidenav == 'optsec'" style="display: none">
399
+ <div class="col-sm-9">
400
+ <div id="" class="box-element success">
401
+ <div class="padding-15">
402
+ <h3>Security</h3>
403
+ <optimization-entry v-for="optimization in optimizations.security" :key="optimization.slug" :opt="optimization"></optimization-entry>
404
+ <div class="row" v-show="sec_more == 'false'">
405
+ <div class="col-sm-12 text-center">
406
+ <p><a href="#" class="more-optimizations-toggle" @click.prevent="sec_more = 'true'">More Optimizations</a></p>
407
+ </div>
408
+ </div>
409
+ <optimization-entry v-show="sec_more == 'true'" v-for="optimization in other_optimizations.security" :key="optimization.slug" :opt="optimization"></optimization-entry>
410
+ <div class="row" v-show="sec_more == 'true'">
411
+ <div class="col-sm-12 text-center">
412
+ <p><a href="#" class="more-optimizations-toggle" @click.prevent="sec_more = 'false'">Less Optimizations</a></p>
413
+ </div>
414
+ </div>
415
+ </div>
416
+ </div>
417
+ </div>
418
+ <div class="col-sm-3">
419
+ <div class="opt-completed">
420
+ <h4><span>Completed</span><br />Security<br />Optimization</h4>
421
+ <div class="row">
422
+ <div class="col-sm-6 col-sm-offset-3">
423
+ <div class="box-element hide-small" style="padding-top: 5px;">
424
+ <div class="circle" id="circles-opt-security"></div>
425
+ </div>
426
+ </div>
427
+ </div>
428
+ </div>
429
+ </div>
430
+ </div>
431
+
432
+
433
+ <!-- Best Practices -->
434
+ <div class="row" v-show="sidenav == 'optbestp'" style="display: none">
435
+ <div class="col-sm-9">
436
+ <div class="box-element clear">
437
+ <div class="padding-15">
438
+ <h3>Best Practices</h3>
439
+ <div class="row" v-for="item in best_practices">
440
+ <div class="col-sm-12 box-element" :class="item.color_class">
441
+ <h4 class="less-vertical-space">
442
+ <div class="row">
443
+ <div class="col-sm-8 col-lg-9">
444
+ {{ item.title }}
445
+ <span v-if="item.status.is_warning" :class="item.color_class"> - WARNING</span>
446
+ <span v-else :class="item.color_class"> - GOOD</span>
447
+ </div>
448
+ <div v-if="!item.hasOwnProperty('slug')" class="col-md-4 col-lg-3 text-right line-height-15">
449
+ <span v-if="item.status.is_warning">
450
+ <span class="glyphicon glyphicon-remove-circle" :class="item.color_class" aria-hidden="true"></span>
451
+ </span>
452
+ <span v-else>
453
+ <span class="glyphicon glyphicon-ok-circle" :class="item.color_class" aria-hidden="true"></span>
454
+ </span>
455
+ <a :href="item.config_url" target="a2opt_config">Modify</a><br><span class="small">via wordpress</span>
456
+ </div>
457
+ <div v-else class="col-md-4 col-lg-3 text-right">
458
+ <span v-if="item.status.is_warning">
459
+ <span class="glyphicon glyphicon-remove-circle" :class="item.color_class" aria-hidden="true"></span>
460
+ </span>
461
+ <span v-else>
462
+ <span class="glyphicon glyphicon-ok-circle" :class="item.color_class" aria-hidden="true"></span>
463
+ </span>
464
+ <a href="" @click.prevent="promptToUpdate($event, 'Are you sure?', 'This will log you out. Click Yes to proceed.', item.slug, 'true')" >Update</a>
465
+ </div>
466
+ </div>
467
+ </h4>
468
+ <div class="best-practices-status">
469
+ <strong>Status: </strong><span :class="item.color_class">{{ item.status.current }}</span><br>
470
+ <strong>Best Practice: </strong><span v-html="item.description"></span>
471
+ </div>
472
+ </div>
473
+ </div>
474
+ </div>
475
+ </div>
476
+ </div>
477
+ <div class="col-sm-3">
478
+ <div class="opt-completed">
479
+ <h4><span>Completed</span><br />Best<br />Practices</h4>
480
+ <div class="row">
481
+ <div class="col-sm-6 col-sm-offset-3">
482
+ <div class="box-element hide-small" style="padding-top: 5px;">
483
+ <div class="circle" id="circles-opt-bestp"></div>
484
+ </div>
485
+ </div>
486
+ </div>
487
+ </div>
488
+ </div>
489
+ </div>
490
+
491
+
492
+ <!-- Results, when ready -->
493
+
494
+
495
+ <!-- update button -->
496
+ <div class="col-sm-9 text-right" style="padding-top: 1em;">
497
+ <a href="#" @click.prevent="updateOptimizations" class="cta-btn-green btn-xlg btn-lg cta-btn-green text-right">Update</a>
498
+ </div>
499
+ </div>
500
+ </div>
501
+ </div>
502
+ </script>
503
+
504
+ <script type="text/x-template" id="page-speed-score-template">
505
+ <div class="row">
506
+ <div class="col-md-10 col-md-offset-2 col-lg-10 col-lg-offset-1">
507
+ <div class="row">
508
+ <div class="col-sm-6" id="a2-optimized-pagespeed">
509
+ <flip-panel content_id="graph-pagespeed" status_class="success">
510
+ <template v-slot:content1>
511
+ <div class="row header">
512
+ <div class="col-sm-8">
513
+ <h3>Page Load Speed</h3>
514
+ </div>
515
+ <div class="col-sm-4 text-right">
516
+ <p><a class="btn cta-btn-green" @click="pageSpeedCheck('page_speed_score')">Run check</a><br>
517
+ <span>Last Check: {{ last_check_date }}</span></p>
518
+ </div>
519
+ </div>
520
+ <div class="row">
521
+ <div class="col-sm-10 col-sm-offset-1">
522
+ <div v-if="show_coaching" class="notice notice-warning">
523
+ <p>Click Run Check to see how fast your page loads. The higher the score the better!</p>
524
+ </div>
525
+ </div>
526
+ <div class="col-sm-11 col-sm-offset-1">
527
+ <div v-if="graphs.pagespeed_mobile" class="col-sm-5 box-element" :class="graphs.pagespeed_mobile.overall_score.color_class">
528
+ <p class='box-title'>Mobile</p>
529
+ <div class="circle" id="circles-pls-mobile"></div>
530
+ <div v-if="graphs.pagespeed_mobile.overall_score.last_check_percent != 0">
531
+ <p><span :class="graphs.pagespeed_mobile.overall_score.color_class"><span class="glyphicon" :class="'glyphicon-arrow-' + graphs.pagespeed_mobile.overall_score.last_check_dir" aria-hidden="true"></span>{{ graphs.pagespeed_mobile.overall_score.last_check_percent }}%</span> Since Last Check</p>
532
+ </div>
533
+ <div v-else>
534
+ <p>&nbsp;</p>
535
+ </div>
536
+ </div>
537
+ <div v-if="graphs.pagespeed_desktop" class="col-sm-5 col-sm-offset-1 box-element" :class="graphs.pagespeed_desktop.overall_score.color_class">
538
+ <p class='box-title'>Desktop</p>
539
+ <div class="circle" id="circles-pls-desktop"></div>
540
+ <div v-if="graphs.pagespeed_desktop.overall_score.last_check_percent != 0">
541
+ <p><span :class="graphs.pagespeed_desktop.overall_score.color_class"><span class="glyphicon" :class="'glyphicon-arrow-' + graphs.pagespeed_desktop.overall_score.last_check_dir" aria-hidden="true"></span>{{ graphs.pagespeed_desktop.overall_score.last_check_percent }}%</span> Since Last Check</p>
542
+ </div>
543
+ <div v-else>
544
+ <p>&nbsp;</p>
545
+ </div>
546
+ </div>
547
+ </div>
548
+ </div>
549
+ </template>
550
+ <template v-slot:content2>
551
+ <div class="row header">
552
+ <div class="col-sm-8">
553
+ <h3>Page Load Speed</h3>
554
+ </div>
555
+ </div>
556
+ <div class="row">
557
+ <div class="col-sm-10 col-sm-offset-1">
558
+ <p>{{ explanations.pagespeed}}</p>
559
+ </div>
560
+ </div>
561
+ </template>
562
+ </flip-panel>
563
+ <div class="row">
564
+ <div class="col-sm-7">
565
+ <p>Data pulled from Google PageSpeed Insights</p>
566
+ </div>
567
+ <div class="col-sm-5 text-right">
568
+ <p>Compare with <a href="https://gtmetrix.com/?url=<?php echo home_url(); ?>" target="_blank">GTMetrix</a></p>
569
+ </div>
570
+ </div>
571
+ </div>
572
+ <div class="col-sm-6" id="a2-optimized-optstatus">
573
+ <flip-panel content_id="graph-opt" status_class="success">
574
+ <template v-slot:content1>
575
+ <div class="row header">
576
+ <div class="col-sm-12">
577
+ <h3>Optimization Status</h3>
578
+ </div>
579
+ </div>
580
+ <div class="row">
581
+ <div class="col-sm-11 col-sm-offset-1">
582
+ <div class="col-sm-11 box-element normal">
583
+ <div class="row">
584
+ <div class="col-sm-4 text-center">
585
+ <div class="circle" id="circles-opt-perf"></div>
586
+ {{ graphs.performance.display_text }}
587
+ </div>
588
+ <div class="col-sm-4 text-center">
589
+ <div class="circle" id="circles-opt-sec"></div>
590
+ {{ graphs.security.display_text }}
591
+ </div>
592
+ <div class="col-sm-4 text-center">
593
+ <div class="circle" id="circles-opt-bestp"></div>
594
+ {{ graphs.bestp.display_text }}
595
+ </div>
596
+ </div>
597
+ </div>
598
+ </div>
599
+ <div class="col-sm-10 col-sm-offset-1 text-right">
600
+ <p><a href="admin.php?page=a2-optimized&a2_page=optimizations" class="cta-link">Go to Recommendations</a></p>
601
+ </div>
602
+ </div>
603
+ </template>
604
+ <template v-slot:content2>
605
+ <div class="row header">
606
+ <div class="col-sm-12">
607
+ <h3>Optimization Status</h3>
608
+ </div>
609
+ </div>
610
+ <div class="row">
611
+ <div class="col-sm-10 col-sm-offset-1">
612
+ <p v-html="explanations.opt"></p>
613
+ </div>
614
+ </div>
615
+ </template>
616
+ </flip-panel>
617
+ </div>
618
+ </div>
619
+ </div>
620
+ </div>
621
+ </script>
622
+
623
+ <script type="text/x-template" id="server-performance-template">
624
+ <div class="col-sm-12">
625
+ <div class="row">
626
+ <div class="col-md-12 col-lg-2 side-nav">
627
+ <div class="col-md-5 col-md-offset-1 col-lg-12 col-lg-offset-0 navlink-wrapper">
628
+ <button type="button" @click="$emit('nav-change-url', 'admin.php?page=a2-optimized&a2_page=server_performance')"
629
+ class="navlink-button" :class="nav.webperf_class">Web Performance</button>
630
+ </div>
631
+ <div class="col-md-5 col-md-offset-1 col-lg-12 col-lg-offset-0 navlink-wrapper">
632
+ <button type="button" @click="$emit('nav-change-url', 'admin.php?page=a2-optimized&a2_page=hosting_matchup')"
633
+ class="navlink-button" :class="nav.hmatch_class">Hosting Matchup</button>
634
+ </div>
635
+ </div>
636
+ <div class="col-md-12 col-lg-10 border-left" id="a2-optimized-serverperformance">
637
+ <div class="row">
638
+ <div class="col-sm-12">
639
+ <select name="server-perf-strategy" id="server-perf-strategy-select" class="form-element" @change="strategyChanged($event)">
640
+ <option selected value="desktop">Desktop</option>
641
+ <option value="mobile">Mobile</option>
642
+ </select>
643
+ <a class="btn cta-btn-green" @click="pageSpeedCheck()">Run Check</a> <span class="last-check">Last Check: {{ last_check_date }}</span>
644
+ </div>
645
+ </div>
646
+ <div v-if="show_coaching" class="row">
647
+ <div class="col-sm-12">
648
+ <div class="notice notice-warning"><p>Click Run Check to see how fast your page loads.</p></div>
649
+ </div>
650
+ </div>
651
+ <div class="row padding-bottom"></div>
652
+ <div class="row">
653
+ <div class="col-sm-4"> <!-- using graphs.ttfb -->
654
+ <speed-metric-card metric_name="ttfb" :metric="graphs.ttfb" show_line=false></speed-metric-card>
655
+ <speed-metric-card metric_name="lcp" :metric="graphs.lcp" show_wave=false></speed-metric-card>
656
+ <speed-metric-card metric_name="fid" :metric="graphs.fid" show_wave=false></speed-metric-card>
657
+ </div>
658
+ <div class="col-sm-4" :class="last_check_date == 'None' ? 'bg-empty' : 'bg-green'">
659
+ <flip-panel content_id="graph-overall_score"
660
+ :status_class="graphs.overall_score.color_class"
661
+ additional_classes="normal graph-card-centered">
662
+ <template v-slot:content1>
663
+ <div class="row">
664
+ <div class="col-sm-12">
665
+ <h4>{{graphs.overall_score.display_text}}</h4>
666
+ <p>{{graphs.overall_score.metric_text}}</p>
667
+ </div>
668
+ </div>
669
+ <div class="row">
670
+ <div class="col-sm-12">
671
+ <div class="circle" id="circles-overall_score"></div>
672
+ </div>
673
+ </div>
674
+ <div class="row">
675
+ <div class="col-sm-12">
676
+ <span class="glyphicon" :class="['glyphicon-arrow-' + graphs.overall_score.last_check_dir,graphs.overall_score.color_class]" style="font-size: 2em;"></span>
677
+ <br>
678
+ <span :class="graphs.overall_score.color_class">{{graphs.overall_score.last_check_percent}}</span>
679
+ <span>vs <br> last check</span>
680
+ </div>
681
+ </div>
682
+ </template>
683
+ <template v-slot:content2>
684
+ <div class="row">
685
+ <div class="col-sm-12">
686
+ <h4>{{graphs.overall_score.display_text}}</h4>
687
+ <p><span v-html="graphs.overall_score.explanation"></span></p>
688
+ </div>
689
+ </div>
690
+ </template>
691
+ </flip-panel>
692
+ <flip-panel content_id="graph-Recommendations"
693
+ additional_classes="normal graph-card-centered">
694
+ <template v-slot:content1>
695
+ <div class="row">
696
+ <div class="col-sm-12">
697
+ <h4>{{graphs.recommendations.display_text}}</h4>
698
+ </div>
699
+ </div>
700
+ <div class="row text-left" >
701
+ <div class="col-sm-12">
702
+ <ul>
703
+ <li v-for="recommendation in graphs.recommendations.list" :id="'rec_item_' + recommendation.lcv">
704
+ {{recommendation.display_text}} <a v-on:click.prevent='rec_toggle(recommendation.lcv)'><span :id="'rec_item_toggle_' + recommendation.lcv" class="glyphicon glyphicon-chevron-right toggle" aria-hidden="true"></span></a>
705
+ <span style="display:none" :id="'rec_item_desc_' + recommendation.lcv ">
706
+ <span v-html='recommendation.description'></span>
707
+ </span>
708
+ </li>
709
+ </ul>
710
+ </div>
711
+ </div>
712
+ </template>
713
+ <template v-slot:content2>
714
+ <div class="row">
715
+ <div class="col-sm-12">
716
+ <h4>{{graphs.recommendations.display_text}}</h4>
717
+ <p>{{ graphs.recommendations.explanation}}</p>
718
+ </div>
719
+ </div>
720
+ </template>
721
+ </flip-panel>
722
+ </div>
723
+ <div class="col-sm-4">
724
+ <speed-metric-card metric_name="fcp" :metric="graphs.fcp" show_wave=false show_line=true></speed-metric-card>
725
+ <speed-metric-card metric_name="cls" :metric="graphs.cls" show_line=false></speed-metric-card>
726
+ <div class="text-center">
727
+ <a href="admin.php?page=a2-optimized&a2_page=optimizations" class="btn btn-lg cta-btn-green text-right">Improve Score</a>
728
+ </div>
729
+ </div>
730
+ </div>
731
+ </div>
732
+ </div>
733
+ </div>
734
+ </script>
735
+
736
+ <script type="text/x-template" id="modal-template">
737
+ <transition name="modal">
738
+ <div class="modal-mask">
739
+ <div class="modal-wrapper">
740
+ <div class="modal-container">
741
+
742
+ <div class="modal-top-bar">
743
+ <span v-show="show_close" class="glyphicon glyphicon-remove" style="font-size: 2em;" @click="$emit('close')"></span>
744
+ </div>
745
+
746
+ <div class="modal-header">
747
+ <slot name="header">
748
+ <p>{{modalMsg}}</p>
749
+ </slot>
750
+ </div>
751
+
752
+ <div class="modal-body">
753
+ <slot name="body">
754
+ </slot>
755
+ </div>
756
+
757
+ <div class="modal-footer">
758
+ <slot name="footer"></slot>
759
+ </div>
760
+ <div v-if="show_busy=='true'" class="row">
761
+ <div class="col-sm-4"></div>
762
+ <div class="col-sm-4">
763
+ <div class="item-loader-container">
764
+ <div class="la-line-spin-fade-rotating la-2x la-dark">
765
+ <div></div>
766
+ <div></div>
767
+ <div></div>
768
+ <div></div>
769
+ <div></div>
770
+ <div></div>
771
+ <div></div>
772
+ <div></div>
773
+ </div>
774
+ </div>
775
+ </div>
776
+ <div class="col-sm-4"></div>
777
+ </div>
778
+ </div>
779
+ </div>
780
+ </div>
781
+ </transition>
782
+ </script>
783
+
784
+ <div class="container-fluid" id="a2-optimized-wrapper">
785
+ <modal v-if="showModal" @close="showModal = false" show_busy=true>
786
+ </modal>
787
+ <modal v-if="showA2Only" @close="showA2Only = false" show_busy=false show_close=true>
788
+ <template v-slot:header><h3 class="text-center" >This feature is not supported on your current hosting environment</h3></template>
789
+ <template v-slot:body>
790
+ <p>At A2 Hosting, our servers are built around providing unbeatable speed. As such, A2 Optimized is configured with speed in mind, and works best when installed on our servers where we can make your site lighting fast!</p>
791
+ <p>As an A2 Hosting customer, you get access to the following features for Free:</p>
792
+ <div class="row">
793
+ <div class="col-sm-2"></div>
794
+ <div class="col-sm-8">
795
+ <ul class="bullet-points">
796
+ <li>Object Caching*</li>
797
+ <li>Login URL Change</li>
798
+ <li>Compress Images on upload</li>
799
+ <li>Turbo web hosting*</li>
800
+ </ul>
801
+ </div>
802
+ <div class="col-sm-2"></div>
803
+ </div>
804
+ <p>Join the A2 family and get access to these amazing speed-enhancing features to give your site the ultimate speed boost. Best of all we offer FREE website migration!</p>
805
+ </template>
806
+ <template v-slot:footer>
807
+ <p><small>* Features are not available on Startup or Drive plans.</small></p>
808
+ <a href="https://www.a2hosting.com/hosting" target="_blank" class="btn cta-btn-green">Get Started</a>
809
+ </template>
810
+ </modal>
811
+ <modal v-if="yesNoDialog.showYesNo" @close="yesNoDialog.showYesNo = false" show_busy=false show_close=true>
812
+ <template v-slot:header><h3>{{ yesNoDialog.header }}</h3></template>
813
+ <template v-slot:body>
814
+ <span class="modal-dialog-text">{{ yesNoDialog.message }}</span>
815
+ </template>
816
+ <template v-slot:footer>
817
+ <a class="btn cta-btn-green" @click="yesNoDialog.doNo" >Cancel</a>
818
+ <a class="btn cta-btn-green" @click="yesNoDialog.doYes">Ok</a></template>
819
+ </modal>
820
+ <div class="row" id="a2-optimized-header">
821
+ <div class="col-sm-10 title">
822
+ <img srcset=" <?php echo esc_url(get_home_url()); ?>/wp-content/plugins/a2-optimized-wp/assets/images/admin/a2opt-logo-2022-2x.png 2x, <?php echo esc_url(get_home_url()); ?>/wp-content/plugins/a2-optimized-wp/assets/images/admin/a2opt-logo-2022.png 1x " src="<?php echo esc_url(get_home_url()); ?>/wp-content/plugins/a2-optimized-wp/assets/images/admin/a2opt-logo-2022.png" >
823
+ </div>
824
+ <div class="col-sm-2 text-right">
825
+ <div class="utility-icon">
826
+ <a id="drop-bell" href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" title="Alerts">
827
+ <span id="drop-bell-wrapper" class="glyphicon glyphicon-bell notification-bell" aria-hidden="true"></span>
828
+ </a>
829
+ <ul id="menu-bell" class="dropdown-menu" aria-labelledby="drop-bell-wrapper">
830
+ <!-- comment until the notifications are ready
831
+ <li v-for="(content, id) in notifications">
832
+ <div class="">
833
+ {{ content }}
834
+ </div>
835
+ </li>
836
+ -->
837
+ </ul>
838
+ </div>
839
+ <div class="utility-icon">
840
+ <a id="drop-links" href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" title="More Information">
841
+ <span id="drop-links-wrapper" class="glyphicon glyphicon-option-vertical" aria-hidden="true"></span>
842
+ </a>
843
+ <ul id="menu-links" class="dropdown-menu" aria-labelledby="drop-links-wrapper">
844
+ <li><a target="_blank" href="https://my.a2hosting.com/">A2 Client Area</a></li>
845
+ <li><a target="_blank" href="https://my.a2hosting.com/submitticket.php?action=support">A2 Client Support</a></li>
846
+ <li><a target="_blank" href="https://wordpress.org/support/plugin/a2-optimized-wp/">Wordpress Support</a></li>
847
+ <li><a target="_blank" href="https://www.a2hosting.com/kb/collections/wordpress-articles">Wordpress Knowledge Base</a></li>
848
+ </ul>
849
+ </div>
850
+ </div>
851
+ <div id="color-palette" style="display:none;">
852
+ <span class="success"></span>
853
+ <span class="warn"></span>
854
+ <span class="danger"></span>
855
+ <span class="thishost"></span>
856
+ <span class="empty"></span>
857
+ </div>
858
+ </div>
859
+ <?php $reporting_active = get_option('a2_sitedata_allow');
860
+ if(!$reporting_active){ ?>
861
+ <div class="row">
862
+ <div class="notice notice-warning">
863
+ <p><strong>Help Us Get You the Best Performance Possible</strong></p>
864
+ <p>A2 Hosting would like to collect technical data about your installation. This data will be used to make sure that the A2 Optimized plugin works seamlessly on the widest possible range of WordPress sites. A full list of the data that is collected can be found <a href="https://www.a2hosting.com/kb/installable-applications/optimization-and-configuration/wordpress2/information-collected-by-the-a2-optimized-wp-plugin" target="_blank">here</a>.</p>
865
+ <p><a href="admin.php?page=a2-optimized&data-collection=yes" class="btn btn-primary">Yes, I would like to help</a>&nbsp;<a href="admin.php?page=a2-optimized&data-collection=no" class="btn btn-default">No, thank you</a></p>
866
+ </div>
867
+ </div>
868
+ <?php }; ?>
869
+ <div class="row" id="a2-optimized-nav">
870
+ <div class="col-md-12 col-lg-11 col-lg-offset-1">
871
+ <div class="row a2-optimized-navigation" id="a2-optimized-navigation">
872
+ <div class="col-md-4 col-lg-3">
873
+ <button type="button" class="navlink-button <?php echo A2_Optimized\App\Models\Settings::get_nav_class($data['nav'], 'pls_class') ?>"
874
+ @click="loadSubPage('page_speed_score')">Page Load Speed Score</button>
875
+ </div>
876
+ <div class="col-md-4 col-lg-3 col-lg-offset-1">
877
+ <button type="button" class="navlink-button <?php echo A2_Optimized\App\Models\Settings::get_nav_class($data['nav'], 'wsp_class') ?>"
878
+ v-on:click.prevent="loadSubPage('server_performance')">Website &amp; Server Performance</button>
879
+ </div>
880
+ <div class="col-md-4 col-lg-3 col-lg-offset-1">
881
+ <button type="button" class="navlink-button <?php echo A2_Optimized\App\Models\Settings::get_nav_class($data['nav'], 'opt_class') ?>"
882
+ @click="loadSubPage('optimizations')">Optimization</button>
883
+ </div>
884
+ </div>
885
+ </div>
886
+ </div>
887
+ <?php echo $data['content-element'] ?>
888
+ </div>
889
+
890
+ </div> <!-- .wrap -->
891
+
892
+ <link rel="preconnect" href="https://fonts.googleapis.com">
893
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
app/views/admin/class-admin-settings.php ADDED
@@ -0,0 +1,206 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace A2_Optimized\App\Views\Admin;
4
+
5
+ use A2_Optimized\Core\View;
6
+ use A2_Optimized as A2_Optimized;
7
+
8
+ if (! class_exists(__NAMESPACE__ . '\\' . 'Admin_Settings')) {
9
+ /**
10
+ * View class to load all templates related to Plugin's Admin Settings Page
11
+ *
12
+ * @since 3.0.0
13
+ * @package A2_Optimized
14
+ * @subpackage A2_Optimized/views/admin
15
+ */
16
+ class Admin_Settings extends View {
17
+ const EVENT_LISTENERS = '@nav-change-url="loadSubPage"';
18
+ /**
19
+ * Prints Settings Page.
20
+ *
21
+ * @param array $args Arguments passed by `markup_settings_page` method from `A2_Optimized\App\Controllers\Admin\Admin_Settings` controller.
22
+ * @return void
23
+ * @since 3.0.0
24
+ */
25
+ public function admin_pagespeed_page($args = []) {
26
+ $last_check = 'None';
27
+ $graphs = $args['graphs'];
28
+ if ($graphs['pagespeed_desktop']) {
29
+ $last_check = $graphs['pagespeed_desktop']['overall_score']['last_check_date'];
30
+ } elseif ($graphs['pagespeed_mobile']) {
31
+ $last_check = $graphs['pagespeed_mobile']['overall_score']['last_check_date'];
32
+ }
33
+
34
+ if(isset($_GET['data-collection'])){
35
+ if($_GET['data-collection'] == 'yes'){
36
+ update_option('a2_sitedata_allow', '1');
37
+ }
38
+ if($_GET['data-collection'] == 'no'){
39
+ update_option('a2_sitedata_allow', '2');
40
+ }
41
+ }
42
+
43
+ $data = [
44
+ 'mainkey' => 1,
45
+ 'updateView' => 0,
46
+ 'notifications' => $args['notifications'],
47
+ 'content-element' => '<page-speed-score :update-Child="updateView" :key="mainkey" ' . self::EVENT_LISTENERS . '></page-speed-score>',
48
+ 'home_url' => home_url(),
49
+ 'nav' => [
50
+ 'pls_class' => 'current',
51
+ 'wsp_class' => '',
52
+ 'opt_class' => ''
53
+ ],
54
+ 'last_check_date' => $last_check,
55
+ 'explanations' => [
56
+ 'pagespeed' => 'Our page load speed score is calculated by measuring how fast your website loads. The higher the score, the faster your website loads. You can visit the “Optimization Recommendations" section to see how you can improve your website\'s page load speed.',
57
+ 'opt' => 'Our optimization status score shows how well your website performs in three categories:<br />
58
+ - Performance (page load speed)<br />
59
+ - Security (can your website be hacked)<br />
60
+ - Best Practices (speed & security)<br />
61
+ <br />
62
+ Optimizing your website for these three categories will improve your user experience, improve conversion rates and prevent malicious people from accessing your website. ',
63
+ ],
64
+ 'graphs' => $args['graphs']
65
+ ];
66
+
67
+ $data_json = json_encode($data);
68
+ /*
69
+ if ($args['run_benchmarks']) {
70
+ echo $data_json;
71
+
72
+ return;
73
+ }
74
+ */
75
+ $data['data_json'] = $data_json;
76
+ $args['data'] = $data;
77
+ echo $this->render_template(
78
+ 'admin/page-settings/page-settings.php',
79
+ $args
80
+ ); // WPCS: XSS OK.
81
+ }
82
+
83
+ public function admin_server_performance_page($args = []) {
84
+ $pagespeed_last_check = 'None';
85
+ $graphs = $args['graphs'];
86
+ if ($graphs) {
87
+ $pagespeed_last_check = $graphs['overall_score']['last_check_date'];
88
+ }
89
+
90
+ $data = [
91
+ 'mainkey' => 1,
92
+ 'updateView' => 0,
93
+ 'content-element' => '<server-performance :update-Child="updateView" :key="mainkey" ' . self::EVENT_LISTENERS . '></server-performance>',
94
+ 'home_url' => home_url(),
95
+ 'nav' => [
96
+ 'wsp_class' => 'current',
97
+ 'webperf_class' => 'current'
98
+ ],
99
+ 'last_check_date' => $pagespeed_last_check,
100
+ 'graphs' => $graphs,
101
+ ];
102
+ $data_json = json_encode($data);
103
+
104
+ $data['data_json'] = $data_json;
105
+ $args['data'] = $data;
106
+ echo $this->render_template(
107
+ 'admin/page-settings/page-settings.php',
108
+ $args
109
+ ); // WPCS: XSS OK.
110
+ }
111
+
112
+ public function admin_hosting_matchup_page($args = []) {
113
+ $last_check = 'None';
114
+ $data = $args['data'];
115
+ if ($data) {
116
+ $last_check = $data['last_check_date'];
117
+ }
118
+
119
+ $data = [
120
+ 'mainkey' => 1,
121
+ 'updateView' => 0,
122
+ 'content-element' => '<hosting-matchup :update-Child="updateView" :key="mainkey" ' . self::EVENT_LISTENERS . '></hosting-matchup>',
123
+ 'home_url' => home_url(),
124
+ 'nav' => [
125
+ 'wsp_class' => 'current',
126
+ 'hmatch_class' => 'current'
127
+ ],
128
+ 'last_check_date' => $last_check,
129
+ 'graphs' => $data['graphs'],
130
+ 'graph_data' => $data['graph_data']
131
+ ];
132
+ $data_json = json_encode($data);
133
+
134
+ $data['data_json'] = $data_json;
135
+ $args['data'] = $data;
136
+
137
+ echo $this->render_template(
138
+ 'admin/page-settings/page-settings.php',
139
+ $args
140
+ ); // WPCS: XSS OK.
141
+ }
142
+
143
+ public function admin_opt_performance_page($args = []) {
144
+
145
+ $data = $args['data'];
146
+
147
+ $data = [
148
+ 'mainkey' => 1,
149
+ 'updateView' => 0,
150
+ 'content-element' => '<optimizations-performance :update-Child="updateView" :key="mainkey" ' . self::EVENT_LISTENERS . '></optimizations-performance>',
151
+ 'home_url' => home_url(),
152
+ 'nav' => [
153
+ 'opt_class' => 'current',
154
+ 'optperf_class' => 'current'
155
+ ],
156
+ 'sidenav' => 'optperf',
157
+ 'perf_more' => 'false',
158
+ 'sec_more' => 'false',
159
+ 'opt_counts' => $data['opt_counts'],
160
+ 'optimizations' => $data['optimizations'],
161
+ 'other_optimizations' => $data['other_optimizations'],
162
+ 'best_practices' => $data['best_practices'],
163
+ 'extra_settings' => $data['extra_settings'],
164
+ 'settings_tethers' => $data['settings_tethers'],
165
+ 'graphs' => $data['graphs']
166
+ ];
167
+ $data_json = json_encode($data);
168
+
169
+ $data['data_json'] = $data_json;
170
+ $args['data'] = $data;
171
+
172
+ echo $this->render_template(
173
+ 'admin/page-settings/page-settings.php',
174
+ $args
175
+ ); // WPCS: XSS OK.
176
+ }
177
+
178
+ /**
179
+ * Prints Section's Description.
180
+ *
181
+ * @param array $args Arguments passed by `markup_section_headers` method from `A2_Optimized\App\Controllers\Admin\Admin_Settings` controller.
182
+ * @return void
183
+ * @since 3.0.0
184
+ */
185
+ public function section_headers($args = []) {
186
+ echo $this->render_template(
187
+ 'admin/page-settings/page-settings-section-headers.php',
188
+ $args
189
+ ); // WPCS: XSS OK.
190
+ }
191
+
192
+ /**
193
+ * Prints text field
194
+ *
195
+ * @param array $args Arguments passed by `markup_fields` method from `A2_Optimized\App\Controllers\Admin\Admin_Settings` controller.
196
+ * @return void
197
+ * @since 3.0.0
198
+ */
199
+ public function markup_fields($args = []) {
200
+ echo $this->render_template(
201
+ 'admin/page-settings/page-settings-fields.php',
202
+ $args
203
+ ); // WPCS: XSS OK.
204
+ }
205
+ }
206
+ }
assets/bootstrap/config.json CHANGED
@@ -11,8 +11,20 @@
11
  "@brand-info": "#5bc0de",
12
  "@brand-warning": "#f0ad4e",
13
  "@brand-danger": "#d9534f",
 
 
 
14
  "@link-hover-color": "darken(@link-color, 15%)",
15
  "@link-hover-decoration": "underline",
 
 
 
 
 
 
 
 
 
16
  "@font-size-h3": "ceil((@font-size-base * 1.7))",
17
  "@font-size-h4": "ceil((@font-size-base * 1.25))",
18
  "@font-size-h5": "@font-size-base",
@@ -370,6 +382,8 @@
370
  "@hr-border": "@gray-lighter"
371
  },
372
  "css": [
 
 
373
  "forms.less",
374
  "buttons.less",
375
  "responsive-utilities.less",
@@ -377,10 +391,14 @@
377
  "navs.less",
378
  "badges.less",
379
  "alerts.less",
 
380
  "panels.less",
381
- "component-animations.less"
 
 
382
  ],
383
  "js": [
 
384
  "tab.js",
385
  "transition.js"
386
  ]
11
  "@brand-info": "#5bc0de",
12
  "@brand-warning": "#f0ad4e",
13
  "@brand-danger": "#d9534f",
14
+ "@body-bg": "#fff",
15
+ "@text-color": "@gray-dark",
16
+ "@link-color": "@brand-primary",
17
  "@link-hover-color": "darken(@link-color, 15%)",
18
  "@link-hover-decoration": "underline",
19
+ "@font-family-sans-serif": "\"Helvetica Neue\", Helvetica, Arial, sans-serif",
20
+ "@font-family-serif": "Georgia, \"Times New Roman\", Times, serif",
21
+ "@font-family-monospace": "Menlo, Monaco, Consolas, \"Courier New\", monospace",
22
+ "@font-family-base": "@font-family-sans-serif",
23
+ "@font-size-base": "14px",
24
+ "@font-size-large": "ceil((@font-size-base * 1.25))",
25
+ "@font-size-small": "ceil((@font-size-base * .85))",
26
+ "@font-size-h1": "floor((@font-size-base * 2.6))",
27
+ "@font-size-h2": "floor((@font-size-base * 2.15))",
28
  "@font-size-h3": "ceil((@font-size-base * 1.7))",
29
  "@font-size-h4": "ceil((@font-size-base * 1.25))",
30
  "@font-size-h5": "@font-size-base",
382
  "@hr-border": "@gray-lighter"
383
  },
384
  "css": [
385
+ "grid.less",
386
+ "tables.less",
387
  "forms.less",
388
  "buttons.less",
389
  "responsive-utilities.less",
391
  "navs.less",
392
  "badges.less",
393
  "alerts.less",
394
+ "progress-bars.less",
395
  "panels.less",
396
+ "close.less",
397
+ "component-animations.less",
398
+ "dropdowns.less"
399
  ],
400
  "js": [
401
+ "dropdown.js",
402
  "tab.js",
403
  "transition.js"
404
  ]
assets/bootstrap/css/bootstrap-theme.css CHANGED
@@ -6,584 +6,585 @@
6
  * Copyright 2011-2019 Twitter, Inc.
7
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
8
  */
9
- .btn-default,
10
- .btn-primary,
11
- .btn-success,
12
- .btn-info,
13
- .btn-warning,
14
- .btn-danger {
15
- text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);
16
- -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
17
- box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
18
- }
19
- .btn-default:active,
20
- .btn-primary:active,
21
- .btn-success:active,
22
- .btn-info:active,
23
- .btn-warning:active,
24
- .btn-danger:active,
25
- .btn-default.active,
26
- .btn-primary.active,
27
- .btn-success.active,
28
- .btn-info.active,
29
- .btn-warning.active,
30
- .btn-danger.active {
31
- -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
32
- box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
33
- }
34
- .btn-default.disabled,
35
- .btn-primary.disabled,
36
- .btn-success.disabled,
37
- .btn-info.disabled,
38
- .btn-warning.disabled,
39
- .btn-danger.disabled,
40
- .btn-default[disabled],
41
- .btn-primary[disabled],
42
- .btn-success[disabled],
43
- .btn-info[disabled],
44
- .btn-warning[disabled],
45
- .btn-danger[disabled],
46
- fieldset[disabled] .btn-default,
47
- fieldset[disabled] .btn-primary,
48
- fieldset[disabled] .btn-success,
49
- fieldset[disabled] .btn-info,
50
- fieldset[disabled] .btn-warning,
51
- fieldset[disabled] .btn-danger {
52
- -webkit-box-shadow: none;
53
- box-shadow: none;
54
- }
55
- .btn-default .badge,
56
- .btn-primary .badge,
57
- .btn-success .badge,
58
- .btn-info .badge,
59
- .btn-warning .badge,
60
- .btn-danger .badge {
61
- text-shadow: none;
62
- }
63
- .btn:active,
64
- .btn.active {
65
- background-image: none;
66
- }
67
- .btn-default {
68
- background-image: -webkit-linear-gradient(top, #ffffff 0%, #e0e0e0 100%);
69
- background-image: -o-linear-gradient(top, #ffffff 0%, #e0e0e0 100%);
70
- background-image: -webkit-gradient(linear, left top, left bottom, from(#ffffff), to(#e0e0e0));
71
- background-image: linear-gradient(to bottom, #ffffff 0%, #e0e0e0 100%);
72
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);
73
- filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
74
- background-repeat: repeat-x;
75
- border-color: #dbdbdb;
76
- text-shadow: 0 1px 0 #fff;
77
- border-color: #ccc;
78
- }
79
- .btn-default:hover,
80
- .btn-default:focus {
81
- background-color: #e0e0e0;
82
- background-position: 0 -15px;
83
- }
84
- .btn-default:active,
85
- .btn-default.active {
86
- background-color: #e0e0e0;
87
- border-color: #dbdbdb;
88
- }
89
- .btn-default.disabled,
90
- .btn-default[disabled],
91
- fieldset[disabled] .btn-default,
92
- .btn-default.disabled:hover,
93
- .btn-default[disabled]:hover,
94
- fieldset[disabled] .btn-default:hover,
95
- .btn-default.disabled:focus,
96
- .btn-default[disabled]:focus,
97
- fieldset[disabled] .btn-default:focus,
98
- .btn-default.disabled.focus,
99
- .btn-default[disabled].focus,
100
- fieldset[disabled] .btn-default.focus,
101
- .btn-default.disabled:active,
102
- .btn-default[disabled]:active,
103
- fieldset[disabled] .btn-default:active,
104
- .btn-default.disabled.active,
105
- .btn-default[disabled].active,
106
- fieldset[disabled] .btn-default.active {
107
- background-color: #e0e0e0;
108
- background-image: none;
109
- }
110
- .btn-primary {
111
- background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%);
112
- background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%);
113
- background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88));
114
- background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%);
115
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);
116
- filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
117
- background-repeat: repeat-x;
118
- border-color: #245580;
119
- }
120
- .btn-primary:hover,
121
- .btn-primary:focus {
122
- background-color: #265a88;
123
- background-position: 0 -15px;
124
- }
125
- .btn-primary:active,
126
- .btn-primary.active {
127
- background-color: #265a88;
128
- border-color: #245580;
129
- }
130
- .btn-primary.disabled,
131
- .btn-primary[disabled],
132
- fieldset[disabled] .btn-primary,
133
- .btn-primary.disabled:hover,
134
- .btn-primary[disabled]:hover,
135
- fieldset[disabled] .btn-primary:hover,
136
- .btn-primary.disabled:focus,
137
- .btn-primary[disabled]:focus,
138
- fieldset[disabled] .btn-primary:focus,
139
- .btn-primary.disabled.focus,
140
- .btn-primary[disabled].focus,
141
- fieldset[disabled] .btn-primary.focus,
142
- .btn-primary.disabled:active,
143
- .btn-primary[disabled]:active,
144
- fieldset[disabled] .btn-primary:active,
145
- .btn-primary.disabled.active,
146
- .btn-primary[disabled].active,
147
- fieldset[disabled] .btn-primary.active {
148
- background-color: #265a88;
149
- background-image: none;
150
- }
151
- .btn-success {
152
- background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);
153
- background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);
154
- background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641));
155
- background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);
156
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);
157
- filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
158
- background-repeat: repeat-x;
159
- border-color: #3e8f3e;
160
- }
161
- .btn-success:hover,
162
- .btn-success:focus {
163
- background-color: #419641;
164
- background-position: 0 -15px;
165
- }
166
- .btn-success:active,
167
- .btn-success.active {
168
- background-color: #419641;
169
- border-color: #3e8f3e;
170
- }
171
- .btn-success.disabled,
172
- .btn-success[disabled],
173
- fieldset[disabled] .btn-success,
174
- .btn-success.disabled:hover,
175
- .btn-success[disabled]:hover,
176
- fieldset[disabled] .btn-success:hover,
177
- .btn-success.disabled:focus,
178
- .btn-success[disabled]:focus,
179
- fieldset[disabled] .btn-success:focus,
180
- .btn-success.disabled.focus,
181
- .btn-success[disabled].focus,
182
- fieldset[disabled] .btn-success.focus,
183
- .btn-success.disabled:active,
184
- .btn-success[disabled]:active,
185
- fieldset[disabled] .btn-success:active,
186
- .btn-success.disabled.active,
187
- .btn-success[disabled].active,
188
- fieldset[disabled] .btn-success.active {
189
- background-color: #419641;
190
- background-image: none;
191
- }
192
- .btn-info {
193
- background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
194
- background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
195
- background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2));
196
- background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);
197
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);
198
- filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
199
- background-repeat: repeat-x;
200
- border-color: #28a4c9;
201
- }
202
- .btn-info:hover,
203
- .btn-info:focus {
204
- background-color: #2aabd2;
205
- background-position: 0 -15px;
206
- }
207
- .btn-info:active,
208
- .btn-info.active {
209
- background-color: #2aabd2;
210
- border-color: #28a4c9;
211
- }
212
- .btn-info.disabled,
213
- .btn-info[disabled],
214
- fieldset[disabled] .btn-info,
215
- .btn-info.disabled:hover,
216
- .btn-info[disabled]:hover,
217
- fieldset[disabled] .btn-info:hover,
218
- .btn-info.disabled:focus,
219
- .btn-info[disabled]:focus,
220
- fieldset[disabled] .btn-info:focus,
221
- .btn-info.disabled.focus,
222
- .btn-info[disabled].focus,
223
- fieldset[disabled] .btn-info.focus,
224
- .btn-info.disabled:active,
225
- .btn-info[disabled]:active,
226
- fieldset[disabled] .btn-info:active,
227
- .btn-info.disabled.active,
228
- .btn-info[disabled].active,
229
- fieldset[disabled] .btn-info.active {
230
- background-color: #2aabd2;
231
- background-image: none;
232
- }
233
- .btn-warning {
234
- background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
235
- background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
236
- background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316));
237
- background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);
238
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);
239
- filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
240
- background-repeat: repeat-x;
241
- border-color: #e38d13;
242
- }
243
- .btn-warning:hover,
244
- .btn-warning:focus {
245
- background-color: #eb9316;
246
- background-position: 0 -15px;
247
- }
248
- .btn-warning:active,
249
- .btn-warning.active {
250
- background-color: #eb9316;
251
- border-color: #e38d13;
252
- }
253
- .btn-warning.disabled,
254
- .btn-warning[disabled],
255
- fieldset[disabled] .btn-warning,
256
- .btn-warning.disabled:hover,
257
- .btn-warning[disabled]:hover,
258
- fieldset[disabled] .btn-warning:hover,
259
- .btn-warning.disabled:focus,
260
- .btn-warning[disabled]:focus,
261
- fieldset[disabled] .btn-warning:focus,
262
- .btn-warning.disabled.focus,
263
- .btn-warning[disabled].focus,
264
- fieldset[disabled] .btn-warning.focus,
265
- .btn-warning.disabled:active,
266
- .btn-warning[disabled]:active,
267
- fieldset[disabled] .btn-warning:active,
268
- .btn-warning.disabled.active,
269
- .btn-warning[disabled].active,
270
- fieldset[disabled] .btn-warning.active {
271
- background-color: #eb9316;
272
- background-image: none;
273
- }
274
- .btn-danger {
275
- background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
276
- background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
277
- background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a));
278
- background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);
279
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);
280
- filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
281
- background-repeat: repeat-x;
282
- border-color: #b92c28;
283
- }
284
- .btn-danger:hover,
285
- .btn-danger:focus {
286
- background-color: #c12e2a;
287
- background-position: 0 -15px;
288
- }
289
- .btn-danger:active,
290
- .btn-danger.active {
291
- background-color: #c12e2a;
292
- border-color: #b92c28;
293
- }
294
- .btn-danger.disabled,
295
- .btn-danger[disabled],
296
- fieldset[disabled] .btn-danger,
297
- .btn-danger.disabled:hover,
298
- .btn-danger[disabled]:hover,
299
- fieldset[disabled] .btn-danger:hover,
300
- .btn-danger.disabled:focus,
301
- .btn-danger[disabled]:focus,
302
- fieldset[disabled] .btn-danger:focus,
303
- .btn-danger.disabled.focus,
304
- .btn-danger[disabled].focus,
305
- fieldset[disabled] .btn-danger.focus,
306
- .btn-danger.disabled:active,
307
- .btn-danger[disabled]:active,
308
- fieldset[disabled] .btn-danger:active,
309
- .btn-danger.disabled.active,
310
- .btn-danger[disabled].active,
311
- fieldset[disabled] .btn-danger.active {
312
- background-color: #c12e2a;
313
- background-image: none;
314
- }
315
- .thumbnail,
316
- .img-thumbnail {
317
- -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
318
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
319
- }
320
- .dropdown-menu > li > a:hover,
321
- .dropdown-menu > li > a:focus {
322
- background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
323
- background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
324
- background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
325
- background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
326
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
327
- background-repeat: repeat-x;
328
- background-color: #e8e8e8;
329
- }
330
- .dropdown-menu > .active > a,
331
- .dropdown-menu > .active > a:hover,
332
- .dropdown-menu > .active > a:focus {
333
- background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
334
- background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
335
- background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
336
- background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
337
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
338
- background-repeat: repeat-x;
339
- background-color: #2e6da4;
340
- }
341
- .navbar-default {
342
- background-image: -webkit-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);
343
- background-image: -o-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);
344
- background-image: -webkit-gradient(linear, left top, left bottom, from(#ffffff), to(#f8f8f8));
345
- background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%);
346
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
347
- background-repeat: repeat-x;
348
- filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
349
- border-radius: 4px;
350
- -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);
351
- box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);
352
- }
353
- .navbar-default .navbar-nav > .open > a,
354
- .navbar-default .navbar-nav > .active > a {
355
- background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
356
- background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
357
- background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2));
358
- background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);
359
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);
360
- background-repeat: repeat-x;
361
- -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);
362
- box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);
363
- }
364
- .navbar-brand,
365
- .navbar-nav > li > a {
366
- text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);
367
- }
368
- .navbar-inverse {
369
- background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222222 100%);
370
- background-image: -o-linear-gradient(top, #3c3c3c 0%, #222222 100%);
371
- background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222222));
372
- background-image: linear-gradient(to bottom, #3c3c3c 0%, #222222 100%);
373
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
374
- background-repeat: repeat-x;
375
- filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
376
- border-radius: 4px;
377
- }
378
- .navbar-inverse .navbar-nav > .open > a,
379
- .navbar-inverse .navbar-nav > .active > a {
380
- background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);
381
- background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);
382
- background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f));
383
- background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);
384
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);
385
- background-repeat: repeat-x;
386
- -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);
387
- box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);
388
- }
389
- .navbar-inverse .navbar-brand,
390
- .navbar-inverse .navbar-nav > li > a {
391
- text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
392
- }
393
- .navbar-static-top,
394
- .navbar-fixed-top,
395
- .navbar-fixed-bottom {
396
- border-radius: 0;
397
- }
398
- @media (max-width: 767px) {
399
- .navbar .navbar-nav .open .dropdown-menu > .active > a,
400
- .navbar .navbar-nav .open .dropdown-menu > .active > a:hover,
401
- .navbar .navbar-nav .open .dropdown-menu > .active > a:focus {
402
- color: #fff;
403
- background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
404
- background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
405
- background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
406
- background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
407
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
408
- background-repeat: repeat-x;
409
- }
410
- }
411
- .alert {
412
- text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);
413
- -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
414
- box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
415
- }
416
- .alert-success {
417
- background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
418
- background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
419
- background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc));
420
- background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
421
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
422
- background-repeat: repeat-x;
423
- border-color: #b2dba1;
424
- }
425
- .alert-info {
426
- background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
427
- background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
428
- background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0));
429
- background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
430
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
431
- background-repeat: repeat-x;
432
- border-color: #9acfea;
433
- }
434
- .alert-warning {
435
- background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
436
- background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
437
- background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0));
438
- background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
439
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
440
- background-repeat: repeat-x;
441
- border-color: #f5e79e;
442
- }
443
- .alert-danger {
444
- background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
445
- background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
446
- background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3));
447
- background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
448
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
449
- background-repeat: repeat-x;
450
- border-color: #dca7a7;
451
- }
452
- .progress {
453
- background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
454
- background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
455
- background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5));
456
- background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
457
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
458
- background-repeat: repeat-x;
459
- }
460
- .progress-bar {
461
- background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%);
462
- background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%);
463
- background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090));
464
- background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%);
465
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);
466
- background-repeat: repeat-x;
467
- }
468
- .progress-bar-success {
469
- background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);
470
- background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);
471
- background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44));
472
- background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
473
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
474
- background-repeat: repeat-x;
475
- }
476
- .progress-bar-info {
477
- background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
478
- background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
479
- background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5));
480
- background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
481
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
482
- background-repeat: repeat-x;
483
- }
484
- .progress-bar-warning {
485
- background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
486
- background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
487
- background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f));
488
- background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
489
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
490
- background-repeat: repeat-x;
491
- }
492
- .progress-bar-danger {
493
- background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);
494
- background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);
495
- background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c));
496
- background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
497
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
498
- background-repeat: repeat-x;
499
- }
500
- .progress-bar-striped {
501
- background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
502
- background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
503
- background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
504
- }
505
- .list-group {
506
- border-radius: 4px;
507
- -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
508
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
509
- }
510
- .list-group-item.active,
511
- .list-group-item.active:hover,
512
- .list-group-item.active:focus {
513
- text-shadow: 0 -1px 0 #286090;
514
- background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%);
515
- background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);
516
- background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a));
517
- background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);
518
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);
519
- background-repeat: repeat-x;
520
- border-color: #2b669a;
521
- }
522
- .list-group-item.active .badge,
523
- .list-group-item.active:hover .badge,
524
- .list-group-item.active:focus .badge {
525
- text-shadow: none;
526
- }
527
- .panel {
528
- -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
529
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
530
- }
531
- .panel-default > .panel-heading {
532
- background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
533
- background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
534
- background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
535
- background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
536
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
537
- background-repeat: repeat-x;
538
- }
539
- .panel-primary > .panel-heading {
540
- background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
541
- background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
542
- background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
543
- background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
544
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
545
- background-repeat: repeat-x;
546
- }
547
- .panel-success > .panel-heading {
548
- background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
549
- background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
550
- background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6));
551
- background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
552
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
553
- background-repeat: repeat-x;
554
- }
555
- .panel-info > .panel-heading {
556
- background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
557
- background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
558
- background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3));
559
- background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
560
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
561
- background-repeat: repeat-x;
562
- }
563
- .panel-warning > .panel-heading {
564
- background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
565
- background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
566
- background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc));
567
- background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
568
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
569
- background-repeat: repeat-x;
570
- }
571
- .panel-danger > .panel-heading {
572
- background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
573
- background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
574
- background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc));
575
- background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
576
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
577
- background-repeat: repeat-x;
578
- }
579
- .well {
580
- background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
581
- background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
582
- background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5));
583
- background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
584
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
585
- background-repeat: repeat-x;
586
- border-color: #dcdcdc;
587
- -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);
588
- box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);
589
- }
 
6
  * Copyright 2011-2019 Twitter, Inc.
7
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
8
  */
9
+ .btn-default,
10
+ .btn-primary,
11
+ .btn-success,
12
+ .btn-info,
13
+ .btn-warning,
14
+ .btn-danger {
15
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);
16
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
17
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
18
+ }
19
+ .btn-default:active,
20
+ .btn-primary:active,
21
+ .btn-success:active,
22
+ .btn-info:active,
23
+ .btn-warning:active,
24
+ .btn-danger:active,
25
+ .btn-default.active,
26
+ .btn-primary.active,
27
+ .btn-success.active,
28
+ .btn-info.active,
29
+ .btn-warning.active,
30
+ .btn-danger.active {
31
+ -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
32
+ box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
33
+ }
34
+ .btn-default.disabled,
35
+ .btn-primary.disabled,
36
+ .btn-success.disabled,
37
+ .btn-info.disabled,
38
+ .btn-warning.disabled,
39
+ .btn-danger.disabled,
40
+ .btn-default[disabled],
41
+ .btn-primary[disabled],
42
+ .btn-success[disabled],
43
+ .btn-info[disabled],
44
+ .btn-warning[disabled],
45
+ .btn-danger[disabled],
46
+ fieldset[disabled] .btn-default,
47
+ fieldset[disabled] .btn-primary,
48
+ fieldset[disabled] .btn-success,
49
+ fieldset[disabled] .btn-info,
50
+ fieldset[disabled] .btn-warning,
51
+ fieldset[disabled] .btn-danger {
52
+ -webkit-box-shadow: none;
53
+ box-shadow: none;
54
+ }
55
+ .btn-default .badge,
56
+ .btn-primary .badge,
57
+ .btn-success .badge,
58
+ .btn-info .badge,
59
+ .btn-warning .badge,
60
+ .btn-danger .badge {
61
+ text-shadow: none;
62
+ }
63
+ .btn:active,
64
+ .btn.active {
65
+ background-image: none;
66
+ }
67
+ .btn-default {
68
+ background-image: -webkit-linear-gradient(top, #ffffff 0%, #e0e0e0 100%);
69
+ background-image: -o-linear-gradient(top, #ffffff 0%, #e0e0e0 100%);
70
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#ffffff), to(#e0e0e0));
71
+ background-image: linear-gradient(to bottom, #ffffff 0%, #e0e0e0 100%);
72
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);
73
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
74
+ background-repeat: repeat-x;
75
+ border-color: #dbdbdb;
76
+ text-shadow: 0 1px 0 #fff;
77
+ border-color: #ccc;
78
+ }
79
+ .btn-default:hover,
80
+ .btn-default:focus {
81
+ background-color: #e0e0e0;
82
+ background-position: 0 -15px;
83
+ }
84
+ .btn-default:active,
85
+ .btn-default.active {
86
+ background-color: #e0e0e0;
87
+ border-color: #dbdbdb;
88
+ }
89
+ .btn-default.disabled,
90
+ .btn-default[disabled],
91
+ fieldset[disabled] .btn-default,
92
+ .btn-default.disabled:hover,
93
+ .btn-default[disabled]:hover,
94
+ fieldset[disabled] .btn-default:hover,
95
+ .btn-default.disabled:focus,
96
+ .btn-default[disabled]:focus,
97
+ fieldset[disabled] .btn-default:focus,
98
+ .btn-default.disabled.focus,
99
+ .btn-default[disabled].focus,
100
+ fieldset[disabled] .btn-default.focus,
101
+ .btn-default.disabled:active,
102
+ .btn-default[disabled]:active,
103
+ fieldset[disabled] .btn-default:active,
104
+ .btn-default.disabled.active,
105
+ .btn-default[disabled].active,
106
+ fieldset[disabled] .btn-default.active {
107
+ background-color: #e0e0e0;
108
+ background-image: none;
109
+ }
110
+ .btn-primary {
111
+ background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%);
112
+ background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%);
113
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88));
114
+ background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%);
115
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);
116
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
117
+ background-repeat: repeat-x;
118
+ border-color: #245580;
119
+ }
120
+ .btn-primary:hover,
121
+ .btn-primary:focus {
122
+ background-color: #265a88;
123
+ background-position: 0 -15px;
124
+ }
125
+ .btn-primary:active,
126
+ .btn-primary.active {
127
+ background-color: #265a88;
128
+ border-color: #245580;
129
+ }
130
+ .btn-primary.disabled,
131
+ .btn-primary[disabled],
132
+ fieldset[disabled] .btn-primary,
133
+ .btn-primary.disabled:hover,
134
+ .btn-primary[disabled]:hover,
135
+ fieldset[disabled] .btn-primary:hover,
136
+ .btn-primary.disabled:focus,
137
+ .btn-primary[disabled]:focus,
138
+ fieldset[disabled] .btn-primary:focus,
139
+ .btn-primary.disabled.focus,
140
+ .btn-primary[disabled].focus,
141
+ fieldset[disabled] .btn-primary.focus,
142
+ .btn-primary.disabled:active,
143
+ .btn-primary[disabled]:active,
144
+ fieldset[disabled] .btn-primary:active,
145
+ .btn-primary.disabled.active,
146
+ .btn-primary[disabled].active,
147
+ fieldset[disabled] .btn-primary.active {
148
+ background-color: #265a88;
149
+ background-image: none;
150
+ }
151
+ .btn-success {
152
+ background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);
153
+ background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);
154
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641));
155
+ background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);
156
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);
157
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
158
+ background-repeat: repeat-x;
159
+ border-color: #3e8f3e;
160
+ }
161
+ .btn-success:hover,
162
+ .btn-success:focus {
163
+ background-color: #419641;
164
+ background-position: 0 -15px;
165
+ }
166
+ .btn-success:active,
167
+ .btn-success.active {
168
+ background-color: #419641;
169
+ border-color: #3e8f3e;
170
+ }
171
+ .btn-success.disabled,
172
+ .btn-success[disabled],
173
+ fieldset[disabled] .btn-success,
174
+ .btn-success.disabled:hover,
175
+ .btn-success[disabled]:hover,
176
+ fieldset[disabled] .btn-success:hover,
177
+ .btn-success.disabled:focus,
178
+ .btn-success[disabled]:focus,
179
+ fieldset[disabled] .btn-success:focus,
180
+ .btn-success.disabled.focus,
181
+ .btn-success[disabled].focus,
182
+ fieldset[disabled] .btn-success.focus,
183
+ .btn-success.disabled:active,
184
+ .btn-success[disabled]:active,
185
+ fieldset[disabled] .btn-success:active,
186
+ .btn-success.disabled.active,
187
+ .btn-success[disabled].active,
188
+ fieldset[disabled] .btn-success.active {
189
+ background-color: #419641;
190
+ background-image: none;
191
+ }
192
+ .btn-info {
193
+ background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
194
+ background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
195
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2));
196
+ background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);
197
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);
198
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
199
+ background-repeat: repeat-x;
200
+ border-color: #28a4c9;
201
+ }
202
+ .btn-info:hover,
203
+ .btn-info:focus {
204
+ background-color: #2aabd2;
205
+ background-position: 0 -15px;
206
+ }
207
+ .btn-info:active,
208
+ .btn-info.active {
209
+ background-color: #2aabd2;
210
+ border-color: #28a4c9;
211
+ }
212
+ .btn-info.disabled,
213
+ .btn-info[disabled],
214
+ fieldset[disabled] .btn-info,
215
+ .btn-info.disabled:hover,
216
+ .btn-info[disabled]:hover,
217
+ fieldset[disabled] .btn-info:hover,
218
+ .btn-info.disabled:focus,
219
+ .btn-info[disabled]:focus,
220
+ fieldset[disabled] .btn-info:focus,
221
+ .btn-info.disabled.focus,
222
+ .btn-info[disabled].focus,
223
+ fieldset[disabled] .btn-info.focus,
224
+ .btn-info.disabled:active,
225
+ .btn-info[disabled]:active,
226
+ fieldset[disabled] .btn-info:active,
227
+ .btn-info.disabled.active,
228
+ .btn-info[disabled].active,
229
+ fieldset[disabled] .btn-info.active {
230
+ background-color: #2aabd2;
231
+ background-image: none;
232
+ }
233
+ .btn-warning {
234
+ background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
235
+ background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
236
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316));
237
+ background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);
238
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);
239
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
240
+ background-repeat: repeat-x;
241
+ border-color: #e38d13;
242
+ }
243
+ .btn-warning:hover,
244
+ .btn-warning:focus {
245
+ background-color: #eb9316;
246
+ background-position: 0 -15px;
247
+ }
248
+ .btn-warning:active,
249
+ .btn-warning.active {
250
+ background-color: #eb9316;
251
+ border-color: #e38d13;
252
+ }
253
+ .btn-warning.disabled,
254
+ .btn-warning[disabled],
255
+ fieldset[disabled] .btn-warning,
256
+ .btn-warning.disabled:hover,
257
+ .btn-warning[disabled]:hover,
258
+ fieldset[disabled] .btn-warning:hover,
259
+ .btn-warning.disabled:focus,
260
+ .btn-warning[disabled]:focus,
261
+ fieldset[disabled] .btn-warning:focus,
262
+ .btn-warning.disabled.focus,
263
+ .btn-warning[disabled].focus,
264
+ fieldset[disabled] .btn-warning.focus,
265
+ .btn-warning.disabled:active,
266
+ .btn-warning[disabled]:active,
267
+ fieldset[disabled] .btn-warning:active,
268
+ .btn-warning.disabled.active,
269
+ .btn-warning[disabled].active,
270
+ fieldset[disabled] .btn-warning.active {
271
+ background-color: #eb9316;
272
+ background-image: none;
273
+ }
274
+ .btn-danger {
275
+ background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
276
+ background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
277
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a));
278
+ background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);
279
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);
280
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
281
+ background-repeat: repeat-x;
282
+ border-color: #b92c28;
283
+ }
284
+ .btn-danger:hover,
285
+ .btn-danger:focus {
286
+ background-color: #c12e2a;
287
+ background-position: 0 -15px;
288
+ }
289
+ .btn-danger:active,
290
+ .btn-danger.active {
291
+ background-color: #c12e2a;
292
+ border-color: #b92c28;
293
+ }
294
+ .btn-danger.disabled,
295
+ .btn-danger[disabled],
296
+ fieldset[disabled] .btn-danger,
297
+ .btn-danger.disabled:hover,
298
+ .btn-danger[disabled]:hover,
299
+ fieldset[disabled] .btn-danger:hover,
300
+ .btn-danger.disabled:focus,
301
+ .btn-danger[disabled]:focus,
302
+ fieldset[disabled] .btn-danger:focus,
303
+ .btn-danger.disabled.focus,
304
+ .btn-danger[disabled].focus,
305
+ fieldset[disabled] .btn-danger.focus,
306
+ .btn-danger.disabled:active,
307
+ .btn-danger[disabled]:active,
308
+ fieldset[disabled] .btn-danger:active,
309
+ .btn-danger.disabled.active,
310
+ .btn-danger[disabled].active,
311
+ fieldset[disabled] .btn-danger.active {
312
+ background-color: #c12e2a;
313
+ background-image: none;
314
+ }
315
+ .thumbnail,
316
+ .img-thumbnail {
317
+ -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
318
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
319
+ }
320
+ .dropdown-menu > li > a:hover,
321
+ .dropdown-menu > li > a:focus {
322
+ background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
323
+ background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
324
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
325
+ background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
326
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
327
+ background-repeat: repeat-x;
328
+ background-color: #e8e8e8;
329
+ }
330
+ .dropdown-menu > .active > a,
331
+ .dropdown-menu > .active > a:hover,
332
+ .dropdown-menu > .active > a:focus {
333
+ background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
334
+ background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
335
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
336
+ background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
337
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
338
+ background-repeat: repeat-x;
339
+ background-color: #2e6da4;
340
+ }
341
+ .navbar-default {
342
+ background-image: -webkit-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);
343
+ background-image: -o-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);
344
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#ffffff), to(#f8f8f8));
345
+ background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%);
346
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
347
+ background-repeat: repeat-x;
348
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
349
+ border-radius: 4px;
350
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);
351
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);
352
+ }
353
+ .navbar-default .navbar-nav > .open > a,
354
+ .navbar-default .navbar-nav > .active > a {
355
+ background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
356
+ background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
357
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2));
358
+ background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);
359
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);
360
+ background-repeat: repeat-x;
361
+ -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);
362
+ box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);
363
+ }
364
+ .navbar-brand,
365
+ .navbar-nav > li > a {
366
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);
367
+ }
368
+ .navbar-inverse {
369
+ background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222222 100%);
370
+ background-image: -o-linear-gradient(top, #3c3c3c 0%, #222222 100%);
371
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222222));
372
+ background-image: linear-gradient(to bottom, #3c3c3c 0%, #222222 100%);
373
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
374
+ background-repeat: repeat-x;
375
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
376
+ border-radius: 4px;
377
+ }
378
+ .navbar-inverse .navbar-nav > .open > a,
379
+ .navbar-inverse .navbar-nav > .active > a {
380
+ background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);
381
+ background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);
382
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f));
383
+ background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);
384
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);
385
+ background-repeat: repeat-x;
386
+ -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);
387
+ box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);
388
+ }
389
+ .navbar-inverse .navbar-brand,
390
+ .navbar-inverse .navbar-nav > li > a {
391
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
392
+ }
393
+ .navbar-static-top,
394
+ .navbar-fixed-top,
395
+ .navbar-fixed-bottom {
396
+ border-radius: 0;
397
+ }
398
+ @media (max-width: 767px) {
399
+ .navbar .navbar-nav .open .dropdown-menu > .active > a,
400
+ .navbar .navbar-nav .open .dropdown-menu > .active > a:hover,
401
+ .navbar .navbar-nav .open .dropdown-menu > .active > a:focus {
402
+ color: #fff;
403
+ background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
404
+ background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
405
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
406
+ background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
407
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
408
+ background-repeat: repeat-x;
409
+ }
410
+ }
411
+ .alert {
412
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);
413
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
414
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
415
+ }
416
+ .alert-success {
417
+ background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
418
+ background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
419
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc));
420
+ background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
421
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
422
+ background-repeat: repeat-x;
423
+ border-color: #b2dba1;
424
+ }
425
+ .alert-info {
426
+ background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
427
+ background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
428
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0));
429
+ background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
430
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
431
+ background-repeat: repeat-x;
432
+ border-color: #9acfea;
433
+ }
434
+ .alert-warning {
435
+ background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
436
+ background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
437
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0));
438
+ background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
439
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
440
+ background-repeat: repeat-x;
441
+ border-color: #f5e79e;
442
+ }
443
+ .alert-danger {
444
+ background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
445
+ background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
446
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3));
447
+ background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
448
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
449
+ background-repeat: repeat-x;
450
+ border-color: #dca7a7;
451
+ }
452
+ .progress {
453
+ background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
454
+ background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
455
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5));
456
+ background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
457
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
458
+ background-repeat: repeat-x;
459
+ }
460
+ .progress-bar {
461
+ background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%);
462
+ background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%);
463
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090));
464
+ background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%);
465
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);
466
+ background-repeat: repeat-x;
467
+ }
468
+ .progress-bar-success {
469
+ background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);
470
+ background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);
471
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44));
472
+ background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
473
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
474
+ background-repeat: repeat-x;
475
+ }
476
+ .progress-bar-info {
477
+ background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
478
+ background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
479
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5));
480
+ background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
481
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
482
+ background-repeat: repeat-x;
483
+ }
484
+ .progress-bar-warning {
485
+ background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
486
+ background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
487
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f));
488
+ background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
489
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
490
+ background-repeat: repeat-x;
491
+ }
492
+ .progress-bar-danger {
493
+ background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);
494
+ background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);
495
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c));
496
+ background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
497
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
498
+ background-repeat: repeat-x;
499
+ }
500
+ .progress-bar-striped {
501
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
502
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
503
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
504
+ }
505
+ .list-group {
506
+ border-radius: 4px;
507
+ -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
508
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
509
+ }
510
+ .list-group-item.active,
511
+ .list-group-item.active:hover,
512
+ .list-group-item.active:focus {
513
+ text-shadow: 0 -1px 0 #286090;
514
+ background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%);
515
+ background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);
516
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a));
517
+ background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);
518
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);
519
+ background-repeat: repeat-x;
520
+ border-color: #2b669a;
521
+ }
522
+ .list-group-item.active .badge,
523
+ .list-group-item.active:hover .badge,
524
+ .list-group-item.active:focus .badge {
525
+ text-shadow: none;
526
+ }
527
+ .panel {
528
+ -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
529
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
530
+ }
531
+ .panel-default > .panel-heading {
532
+ background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
533
+ background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
534
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
535
+ background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
536
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
537
+ background-repeat: repeat-x;
538
+ }
539
+ .panel-primary > .panel-heading {
540
+ background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
541
+ background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
542
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
543
+ background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
544
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
545
+ background-repeat: repeat-x;
546
+ }
547
+ .panel-success > .panel-heading {
548
+ background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
549
+ background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
550
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6));
551
+ background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
552
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
553
+ background-repeat: repeat-x;
554
+ }
555
+ .panel-info > .panel-heading {
556
+ background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
557
+ background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
558
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3));
559
+ background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
560
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
561
+ background-repeat: repeat-x;
562
+ }
563
+ .panel-warning > .panel-heading {
564
+ background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
565
+ background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
566
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc));
567
+ background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
568
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
569
+ background-repeat: repeat-x;
570
+ }
571
+ .panel-danger > .panel-heading {
572
+ background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
573
+ background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
574
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc));
575
+ background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
576
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
577
+ background-repeat: repeat-x;
578
+ }
579
+ .well {
580
+ background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
581
+ background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
582
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5));
583
+ background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
584
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
585
+ background-repeat: repeat-x;
586
+ border-color: #dcdcdc;
587
+ -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);
588
+ box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);
589
+ }
590
+
assets/bootstrap/css/bootstrap.css CHANGED
@@ -64,6 +64,10 @@ strong {
64
  dfn {
65
  font-style: italic;
66
  }
 
 
 
 
67
  mark {
68
  background: #ff0;
69
  color: #000;
@@ -1002,6 +1006,17 @@ th {
1002
  -moz-box-sizing: border-box;
1003
  box-sizing: border-box;
1004
  }
 
 
 
 
 
 
 
 
 
 
 
1005
  input,
1006
  button,
1007
  select,
@@ -1081,6 +1096,921 @@ hr {
1081
  [role="button"] {
1082
  cursor: pointer;
1083
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1084
  fieldset {
1085
  min-width: 0;
1086
  padding: 0;
@@ -2064,6 +2994,149 @@ tbody.collapse.in {
2064
  -o-transition-timing-function: ease;
2065
  transition-timing-function: ease;
2066
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2067
  .nav {
2068
  padding-left: 0;
2069
  margin-bottom: 0;
@@ -2377,6 +3450,100 @@ a.badge:focus {
2377
  .alert-danger .alert-link {
2378
  color: #843534;
2379
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2380
  .panel {
2381
  margin-bottom: 20px;
2382
  background-color: #ffffff;
@@ -2720,8 +3887,40 @@ a.badge:focus {
2720
  .panel-danger > .panel-footer + .panel-collapse > .panel-body {
2721
  border-bottom-color: #ebccd1;
2722
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2723
  .clearfix:before,
2724
  .clearfix:after,
 
 
 
 
 
 
2725
  .form-horizontal .form-group:before,
2726
  .form-horizontal .form-group:after,
2727
  .nav:before,
@@ -2732,6 +3931,9 @@ a.badge:focus {
2732
  content: " ";
2733
  }
2734
  .clearfix:after,
 
 
 
2735
  .form-horizontal .form-group:after,
2736
  .nav:after,
2737
  .panel-body:after {
64
  dfn {
65
  font-style: italic;
66
  }
67
+ h1 {
68
+ font-size: 2em;
69
+ margin: 0.67em 0;
70
+ }
71
  mark {
72
  background: #ff0;
73
  color: #000;
1006
  -moz-box-sizing: border-box;
1007
  box-sizing: border-box;
1008
  }
1009
+ html {
1010
+ font-size: 10px;
1011
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
1012
+ }
1013
+ body {
1014
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
1015
+ font-size: 14px;
1016
+ line-height: 1.42857143;
1017
+ color: #333333;
1018
+ background-color: #ffffff;
1019
+ }
1020
  input,
1021
  button,
1022
  select,
1096
  [role="button"] {
1097
  cursor: pointer;
1098
  }
1099
+ .container {
1100
+ padding-right: 15px;
1101
+ padding-left: 15px;
1102
+ margin-right: auto;
1103
+ margin-left: auto;
1104
+ }
1105
+ @media (min-width: 768px) {
1106
+ .container {
1107
+ width: 750px;
1108
+ }
1109
+ }
1110
+ @media (min-width: 992px) {
1111
+ .container {
1112
+ width: 970px;
1113
+ }
1114
+ }
1115
+ @media (min-width: 1200px) {
1116
+ .container {
1117
+ width: 1170px;
1118
+ }
1119
+ }
1120
+ .container-fluid {
1121
+ padding-right: 15px;
1122
+ padding-left: 15px;
1123
+ margin-right: auto;
1124
+ margin-left: auto;
1125
+ }
1126
+ .row {
1127
+ margin-right: -15px;
1128
+ margin-left: -15px;
1129
+ }
1130
+ .row-no-gutters {
1131
+ margin-right: 0;
1132
+ margin-left: 0;
1133
+ }
1134
+ .row-no-gutters [class*="col-"] {
1135
+ padding-right: 0;
1136
+ padding-left: 0;
1137
+ }
1138
+ .col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {
1139
+ position: relative;
1140
+ min-height: 1px;
1141
+ padding-right: 15px;
1142
+ padding-left: 15px;
1143
+ }
1144
+ .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {
1145
+ float: left;
1146
+ }
1147
+ .col-xs-12 {
1148
+ width: 100%;
1149
+ }
1150
+ .col-xs-11 {
1151
+ width: 91.66666667%;
1152
+ }
1153
+ .col-xs-10 {
1154
+ width: 83.33333333%;
1155
+ }
1156
+ .col-xs-9 {
1157
+ width: 75%;
1158
+ }
1159
+ .col-xs-8 {
1160
+ width: 66.66666667%;
1161
+ }
1162
+ .col-xs-7 {
1163
+ width: 58.33333333%;
1164
+ }
1165
+ .col-xs-6 {
1166
+ width: 50%;
1167
+ }
1168
+ .col-xs-5 {
1169
+ width: 41.66666667%;
1170
+ }
1171
+ .col-xs-4 {
1172
+ width: 33.33333333%;
1173
+ }
1174
+ .col-xs-3 {
1175
+ width: 25%;
1176
+ }
1177
+ .col-xs-2 {
1178
+ width: 16.66666667%;
1179
+ }
1180
+ .col-xs-1 {
1181
+ width: 8.33333333%;
1182
+ }
1183
+ .col-xs-pull-12 {
1184
+ right: 100%;
1185
+ }
1186
+ .col-xs-pull-11 {
1187
+ right: 91.66666667%;
1188
+ }
1189
+ .col-xs-pull-10 {
1190
+ right: 83.33333333%;
1191
+ }
1192
+ .col-xs-pull-9 {
1193
+ right: 75%;
1194
+ }
1195
+ .col-xs-pull-8 {
1196
+ right: 66.66666667%;
1197
+ }
1198
+ .col-xs-pull-7 {
1199
+ right: 58.33333333%;
1200
+ }
1201
+ .col-xs-pull-6 {
1202
+ right: 50%;
1203
+ }
1204
+ .col-xs-pull-5 {
1205
+ right: 41.66666667%;
1206
+ }
1207
+ .col-xs-pull-4 {
1208
+ right: 33.33333333%;
1209
+ }
1210
+ .col-xs-pull-3 {
1211
+ right: 25%;
1212
+ }
1213
+ .col-xs-pull-2 {
1214
+ right: 16.66666667%;
1215
+ }
1216
+ .col-xs-pull-1 {
1217
+ right: 8.33333333%;
1218
+ }
1219
+ .col-xs-pull-0 {
1220
+ right: auto;
1221
+ }
1222
+ .col-xs-push-12 {
1223
+ left: 100%;
1224
+ }
1225
+ .col-xs-push-11 {
1226
+ left: 91.66666667%;
1227
+ }
1228
+ .col-xs-push-10 {
1229
+ left: 83.33333333%;
1230
+ }
1231
+ .col-xs-push-9 {
1232
+ left: 75%;
1233
+ }
1234
+ .col-xs-push-8 {
1235
+ left: 66.66666667%;
1236
+ }
1237
+ .col-xs-push-7 {
1238
+ left: 58.33333333%;
1239
+ }
1240
+ .col-xs-push-6 {
1241
+ left: 50%;
1242
+ }
1243
+ .col-xs-push-5 {
1244
+ left: 41.66666667%;
1245
+ }
1246
+ .col-xs-push-4 {
1247
+ left: 33.33333333%;
1248
+ }
1249
+ .col-xs-push-3 {
1250
+ left: 25%;
1251
+ }
1252
+ .col-xs-push-2 {
1253
+ left: 16.66666667%;
1254
+ }
1255
+ .col-xs-push-1 {
1256
+ left: 8.33333333%;
1257
+ }
1258
+ .col-xs-push-0 {
1259
+ left: auto;
1260
+ }
1261
+ .col-xs-offset-12 {
1262
+ margin-left: 100%;
1263
+ }
1264
+ .col-xs-offset-11 {
1265
+ margin-left: 91.66666667%;
1266
+ }
1267
+ .col-xs-offset-10 {
1268
+ margin-left: 83.33333333%;
1269
+ }
1270
+ .col-xs-offset-9 {
1271
+ margin-left: 75%;
1272
+ }
1273
+ .col-xs-offset-8 {
1274
+ margin-left: 66.66666667%;
1275
+ }
1276
+ .col-xs-offset-7 {
1277
+ margin-left: 58.33333333%;
1278
+ }
1279
+ .col-xs-offset-6 {
1280
+ margin-left: 50%;
1281
+ }
1282
+ .col-xs-offset-5 {
1283
+ margin-left: 41.66666667%;
1284
+ }
1285
+ .col-xs-offset-4 {
1286
+ margin-left: 33.33333333%;
1287
+ }
1288
+ .col-xs-offset-3 {
1289
+ margin-left: 25%;
1290
+ }
1291
+ .col-xs-offset-2 {
1292
+ margin-left: 16.66666667%;
1293
+ }
1294
+ .col-xs-offset-1 {
1295
+ margin-left: 8.33333333%;
1296
+ }
1297
+ .col-xs-offset-0 {
1298
+ margin-left: 0%;
1299
+ }
1300
+ @media (min-width: 768px) {
1301
+ .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 {
1302
+ float: left;
1303
+ }
1304
+ .col-sm-12 {
1305
+ width: 100%;
1306
+ }
1307
+ .col-sm-11 {
1308
+ width: 91.66666667%;
1309
+ }
1310
+ .col-sm-10 {
1311
+ width: 83.33333333%;
1312
+ }
1313
+ .col-sm-9 {
1314
+ width: 75%;
1315
+ }
1316
+ .col-sm-8 {
1317
+ width: 66.66666667%;
1318
+ }
1319
+ .col-sm-7 {
1320
+ width: 58.33333333%;
1321
+ }
1322
+ .col-sm-6 {
1323
+ width: 50%;
1324
+ }
1325
+ .col-sm-5 {
1326
+ width: 41.66666667%;
1327
+ }
1328
+ .col-sm-4 {
1329
+ width: 33.33333333%;
1330
+ }
1331
+ .col-sm-3 {
1332
+ width: 25%;
1333
+ }
1334
+ .col-sm-2 {
1335
+ width: 16.66666667%;
1336
+ }
1337
+ .col-sm-1 {
1338
+ width: 8.33333333%;
1339
+ }
1340
+ .col-sm-pull-12 {
1341
+ right: 100%;
1342
+ }
1343
+ .col-sm-pull-11 {
1344
+ right: 91.66666667%;
1345
+ }
1346
+ .col-sm-pull-10 {
1347
+ right: 83.33333333%;
1348
+ }
1349
+ .col-sm-pull-9 {
1350
+ right: 75%;
1351
+ }
1352
+ .col-sm-pull-8 {
1353
+ right: 66.66666667%;
1354
+ }
1355
+ .col-sm-pull-7 {
1356
+ right: 58.33333333%;
1357
+ }
1358
+ .col-sm-pull-6 {
1359
+ right: 50%;
1360
+ }
1361
+ .col-sm-pull-5 {
1362
+ right: 41.66666667%;
1363
+ }
1364
+ .col-sm-pull-4 {
1365
+ right: 33.33333333%;
1366
+ }
1367
+ .col-sm-pull-3 {
1368
+ right: 25%;
1369
+ }
1370
+ .col-sm-pull-2 {
1371
+ right: 16.66666667%;
1372
+ }
1373
+ .col-sm-pull-1 {
1374
+ right: 8.33333333%;
1375
+ }
1376
+ .col-sm-pull-0 {
1377
+ right: auto;
1378
+ }
1379
+ .col-sm-push-12 {
1380
+ left: 100%;
1381
+ }
1382
+ .col-sm-push-11 {
1383
+ left: 91.66666667%;
1384
+ }
1385
+ .col-sm-push-10 {
1386
+ left: 83.33333333%;
1387
+ }
1388
+ .col-sm-push-9 {
1389
+ left: 75%;
1390
+ }
1391
+ .col-sm-push-8 {
1392
+ left: 66.66666667%;
1393
+ }
1394
+ .col-sm-push-7 {
1395
+ left: 58.33333333%;
1396
+ }
1397
+ .col-sm-push-6 {
1398
+ left: 50%;
1399
+ }
1400
+ .col-sm-push-5 {
1401
+ left: 41.66666667%;
1402
+ }
1403
+ .col-sm-push-4 {
1404
+ left: 33.33333333%;
1405
+ }
1406
+ .col-sm-push-3 {
1407
+ left: 25%;
1408
+ }
1409
+ .col-sm-push-2 {
1410
+ left: 16.66666667%;
1411
+ }
1412
+ .col-sm-push-1 {
1413
+ left: 8.33333333%;
1414
+ }
1415
+ .col-sm-push-0 {
1416
+ left: auto;
1417
+ }
1418
+ .col-sm-offset-12 {
1419
+ margin-left: 100%;
1420
+ }
1421
+ .col-sm-offset-11 {
1422
+ margin-left: 91.66666667%;
1423
+ }
1424
+ .col-sm-offset-10 {
1425
+ margin-left: 83.33333333%;
1426
+ }
1427
+ .col-sm-offset-9 {
1428
+ margin-left: 75%;
1429
+ }
1430
+ .col-sm-offset-8 {
1431
+ margin-left: 66.66666667%;
1432
+ }
1433
+ .col-sm-offset-7 {
1434
+ margin-left: 58.33333333%;
1435
+ }
1436
+ .col-sm-offset-6 {
1437
+ margin-left: 50%;
1438
+ }
1439
+ .col-sm-offset-5 {
1440
+ margin-left: 41.66666667%;
1441
+ }
1442
+ .col-sm-offset-4 {
1443
+ margin-left: 33.33333333%;
1444
+ }
1445
+ .col-sm-offset-3 {
1446
+ margin-left: 25%;
1447
+ }
1448
+ .col-sm-offset-2 {
1449
+ margin-left: 16.66666667%;
1450
+ }
1451
+ .col-sm-offset-1 {
1452
+ margin-left: 8.33333333%;
1453
+ }
1454
+ .col-sm-offset-0 {
1455
+ margin-left: 0%;
1456
+ }
1457
+ }
1458
+ @media (min-width: 992px) {
1459
+ .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {
1460
+ float: left;
1461
+ }
1462
+ .col-md-12 {
1463
+ width: 100%;
1464
+ }
1465
+ .col-md-11 {
1466
+ width: 91.66666667%;
1467
+ }
1468
+ .col-md-10 {
1469
+ width: 83.33333333%;
1470
+ }
1471
+ .col-md-9 {
1472
+ width: 75%;
1473
+ }
1474
+ .col-md-8 {
1475
+ width: 66.66666667%;
1476
+ }
1477
+ .col-md-7 {
1478
+ width: 58.33333333%;
1479
+ }
1480
+ .col-md-6 {
1481
+ width: 50%;
1482
+ }
1483
+ .col-md-5 {
1484
+ width: 41.66666667%;
1485
+ }
1486
+ .col-md-4 {
1487
+ width: 33.33333333%;
1488
+ }
1489
+ .col-md-3 {
1490
+ width: 25%;
1491
+ }
1492
+ .col-md-2 {
1493
+ width: 16.66666667%;
1494
+ }
1495
+ .col-md-1 {
1496
+ width: 8.33333333%;
1497
+ }
1498
+ .col-md-pull-12 {
1499
+ right: 100%;
1500
+ }
1501
+ .col-md-pull-11 {
1502
+ right: 91.66666667%;
1503
+ }
1504
+ .col-md-pull-10 {
1505
+ right: 83.33333333%;
1506
+ }
1507
+ .col-md-pull-9 {
1508
+ right: 75%;
1509
+ }
1510
+ .col-md-pull-8 {
1511
+ right: 66.66666667%;
1512
+ }
1513
+ .col-md-pull-7 {
1514
+ right: 58.33333333%;
1515
+ }
1516
+ .col-md-pull-6 {
1517
+ right: 50%;
1518
+ }
1519
+ .col-md-pull-5 {
1520
+ right: 41.66666667%;
1521
+ }
1522
+ .col-md-pull-4 {
1523
+ right: 33.33333333%;
1524
+ }
1525
+ .col-md-pull-3 {
1526
+ right: 25%;
1527
+ }
1528
+ .col-md-pull-2 {
1529
+ right: 16.66666667%;
1530
+ }
1531
+ .col-md-pull-1 {
1532
+ right: 8.33333333%;
1533
+ }
1534
+ .col-md-pull-0 {
1535
+ right: auto;
1536
+ }
1537
+ .col-md-push-12 {
1538
+ left: 100%;
1539
+ }
1540
+ .col-md-push-11 {
1541
+ left: 91.66666667%;
1542
+ }
1543
+ .col-md-push-10 {
1544
+ left: 83.33333333%;
1545
+ }
1546
+ .col-md-push-9 {
1547
+ left: 75%;
1548
+ }
1549
+ .col-md-push-8 {
1550
+ left: 66.66666667%;
1551
+ }
1552
+ .col-md-push-7 {
1553
+ left: 58.33333333%;
1554
+ }
1555
+ .col-md-push-6 {
1556
+ left: 50%;
1557
+ }
1558
+ .col-md-push-5 {
1559
+ left: 41.66666667%;
1560
+ }
1561
+ .col-md-push-4 {
1562
+ left: 33.33333333%;
1563
+ }
1564
+ .col-md-push-3 {
1565
+ left: 25%;
1566
+ }
1567
+ .col-md-push-2 {
1568
+ left: 16.66666667%;
1569
+ }
1570
+ .col-md-push-1 {
1571
+ left: 8.33333333%;
1572
+ }
1573
+ .col-md-push-0 {
1574
+ left: auto;
1575
+ }
1576
+ .col-md-offset-12 {
1577
+ margin-left: 100%;
1578
+ }
1579
+ .col-md-offset-11 {
1580
+ margin-left: 91.66666667%;
1581
+ }
1582
+ .col-md-offset-10 {
1583
+ margin-left: 83.33333333%;
1584
+ }
1585
+ .col-md-offset-9 {
1586
+ margin-left: 75%;
1587
+ }
1588
+ .col-md-offset-8 {
1589
+ margin-left: 66.66666667%;
1590
+ }
1591
+ .col-md-offset-7 {
1592
+ margin-left: 58.33333333%;
1593
+ }
1594
+ .col-md-offset-6 {
1595
+ margin-left: 50%;
1596
+ }
1597
+ .col-md-offset-5 {
1598
+ margin-left: 41.66666667%;
1599
+ }
1600
+ .col-md-offset-4 {
1601
+ margin-left: 33.33333333%;
1602
+ }
1603
+ .col-md-offset-3 {
1604
+ margin-left: 25%;
1605
+ }
1606
+ .col-md-offset-2 {
1607
+ margin-left: 16.66666667%;
1608
+ }
1609
+ .col-md-offset-1 {
1610
+ margin-left: 8.33333333%;
1611
+ }
1612
+ .col-md-offset-0 {
1613
+ margin-left: 0%;
1614
+ }
1615
+ }
1616
+ @media (min-width: 1200px) {
1617
+ .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 {
1618
+ float: left;
1619
+ }
1620
+ .col-lg-12 {
1621
+ width: 100%;
1622
+ }
1623
+ .col-lg-11 {
1624
+ width: 91.66666667%;
1625
+ }
1626
+ .col-lg-10 {
1627
+ width: 83.33333333%;
1628
+ }
1629
+ .col-lg-9 {
1630
+ width: 75%;
1631
+ }
1632
+ .col-lg-8 {
1633
+ width: 66.66666667%;
1634
+ }
1635
+ .col-lg-7 {
1636
+ width: 58.33333333%;
1637
+ }
1638
+ .col-lg-6 {
1639
+ width: 50%;
1640
+ }
1641
+ .col-lg-5 {
1642
+ width: 41.66666667%;
1643
+ }
1644
+ .col-lg-4 {
1645
+ width: 33.33333333%;
1646
+ }
1647
+ .col-lg-3 {
1648
+ width: 25%;
1649
+ }
1650
+ .col-lg-2 {
1651
+ width: 16.66666667%;
1652
+ }
1653
+ .col-lg-1 {
1654
+ width: 8.33333333%;
1655
+ }
1656
+ .col-lg-pull-12 {
1657
+ right: 100%;
1658
+ }
1659
+ .col-lg-pull-11 {
1660
+ right: 91.66666667%;
1661
+ }
1662
+ .col-lg-pull-10 {
1663
+ right: 83.33333333%;
1664
+ }
1665
+ .col-lg-pull-9 {
1666
+ right: 75%;
1667
+ }
1668
+ .col-lg-pull-8 {
1669
+ right: 66.66666667%;
1670
+ }
1671
+ .col-lg-pull-7 {
1672
+ right: 58.33333333%;
1673
+ }
1674
+ .col-lg-pull-6 {
1675
+ right: 50%;
1676
+ }
1677
+ .col-lg-pull-5 {
1678
+ right: 41.66666667%;
1679
+ }
1680
+ .col-lg-pull-4 {
1681
+ right: 33.33333333%;
1682
+ }
1683
+ .col-lg-pull-3 {
1684
+ right: 25%;
1685
+ }
1686
+ .col-lg-pull-2 {
1687
+ right: 16.66666667%;
1688
+ }
1689
+ .col-lg-pull-1 {
1690
+ right: 8.33333333%;
1691
+ }
1692
+ .col-lg-pull-0 {
1693
+ right: auto;
1694
+ }
1695
+ .col-lg-push-12 {
1696
+ left: 100%;
1697
+ }
1698
+ .col-lg-push-11 {
1699
+ left: 91.66666667%;
1700
+ }
1701
+ .col-lg-push-10 {
1702
+ left: 83.33333333%;
1703
+ }
1704
+ .col-lg-push-9 {
1705
+ left: 75%;
1706
+ }
1707
+ .col-lg-push-8 {
1708
+ left: 66.66666667%;
1709
+ }
1710
+ .col-lg-push-7 {
1711
+ left: 58.33333333%;
1712
+ }
1713
+ .col-lg-push-6 {
1714
+ left: 50%;
1715
+ }
1716
+ .col-lg-push-5 {
1717
+ left: 41.66666667%;
1718
+ }
1719
+ .col-lg-push-4 {
1720
+ left: 33.33333333%;
1721
+ }
1722
+ .col-lg-push-3 {
1723
+ left: 25%;
1724
+ }
1725
+ .col-lg-push-2 {
1726
+ left: 16.66666667%;
1727
+ }
1728
+ .col-lg-push-1 {
1729
+ left: 8.33333333%;
1730
+ }
1731
+ .col-lg-push-0 {
1732
+ left: auto;
1733
+ }
1734
+ .col-lg-offset-12 {
1735
+ margin-left: 100%;
1736
+ }
1737
+ .col-lg-offset-11 {
1738
+ margin-left: 91.66666667%;
1739
+ }
1740
+ .col-lg-offset-10 {
1741
+ margin-left: 83.33333333%;
1742
+ }
1743
+ .col-lg-offset-9 {
1744
+ margin-left: 75%;
1745
+ }
1746
+ .col-lg-offset-8 {
1747
+ margin-left: 66.66666667%;
1748
+ }
1749
+ .col-lg-offset-7 {
1750
+ margin-left: 58.33333333%;
1751
+ }
1752
+ .col-lg-offset-6 {
1753
+ margin-left: 50%;
1754
+ }
1755
+ .col-lg-offset-5 {
1756
+ margin-left: 41.66666667%;
1757
+ }
1758
+ .col-lg-offset-4 {
1759
+ margin-left: 33.33333333%;
1760
+ }
1761
+ .col-lg-offset-3 {
1762
+ margin-left: 25%;
1763
+ }
1764
+ .col-lg-offset-2 {
1765
+ margin-left: 16.66666667%;
1766
+ }
1767
+ .col-lg-offset-1 {
1768
+ margin-left: 8.33333333%;
1769
+ }
1770
+ .col-lg-offset-0 {
1771
+ margin-left: 0%;
1772
+ }
1773
+ }
1774
+ table {
1775
+ background-color: transparent;
1776
+ }
1777
+ table col[class*="col-"] {
1778
+ position: static;
1779
+ display: table-column;
1780
+ float: none;
1781
+ }
1782
+ table td[class*="col-"],
1783
+ table th[class*="col-"] {
1784
+ position: static;
1785
+ display: table-cell;
1786
+ float: none;
1787
+ }
1788
+ caption {
1789
+ padding-top: 8px;
1790
+ padding-bottom: 8px;
1791
+ color: #777777;
1792
+ text-align: left;
1793
+ }
1794
+ th {
1795
+ text-align: left;
1796
+ }
1797
+ .table {
1798
+ width: 100%;
1799
+ max-width: 100%;
1800
+ margin-bottom: 20px;
1801
+ }
1802
+ .table > thead > tr > th,
1803
+ .table > tbody > tr > th,
1804
+ .table > tfoot > tr > th,
1805
+ .table > thead > tr > td,
1806
+ .table > tbody > tr > td,
1807
+ .table > tfoot > tr > td {
1808
+ padding: 8px;
1809
+ line-height: 1.42857143;
1810
+ vertical-align: top;
1811
+ border-top: 1px solid #dddddd;
1812
+ }
1813
+ .table > thead > tr > th {
1814
+ vertical-align: bottom;
1815
+ border-bottom: 2px solid #dddddd;
1816
+ }
1817
+ .table > caption + thead > tr:first-child > th,
1818
+ .table > colgroup + thead > tr:first-child > th,
1819
+ .table > thead:first-child > tr:first-child > th,
1820
+ .table > caption + thead > tr:first-child > td,
1821
+ .table > colgroup + thead > tr:first-child > td,
1822
+ .table > thead:first-child > tr:first-child > td {
1823
+ border-top: 0;
1824
+ }
1825
+ .table > tbody + tbody {
1826
+ border-top: 2px solid #dddddd;
1827
+ }
1828
+ .table .table {
1829
+ background-color: #ffffff;
1830
+ }
1831
+ .table-condensed > thead > tr > th,
1832
+ .table-condensed > tbody > tr > th,
1833
+ .table-condensed > tfoot > tr > th,
1834
+ .table-condensed > thead > tr > td,
1835
+ .table-condensed > tbody > tr > td,
1836
+ .table-condensed > tfoot > tr > td {
1837
+ padding: 5px;
1838
+ }
1839
+ .table-bordered {
1840
+ border: 1px solid #dddddd;
1841
+ }
1842
+ .table-bordered > thead > tr > th,
1843
+ .table-bordered > tbody > tr > th,
1844
+ .table-bordered > tfoot > tr > th,
1845
+ .table-bordered > thead > tr > td,
1846
+ .table-bordered > tbody > tr > td,
1847
+ .table-bordered > tfoot > tr > td {
1848
+ border: 1px solid #dddddd;
1849
+ }
1850
+ .table-bordered > thead > tr > th,
1851
+ .table-bordered > thead > tr > td {
1852
+ border-bottom-width: 2px;
1853
+ }
1854
+ .table-striped > tbody > tr:nth-of-type(odd) {
1855
+ background-color: #f9f9f9;
1856
+ }
1857
+ .table-hover > tbody > tr:hover {
1858
+ background-color: #f5f5f5;
1859
+ }
1860
+ .table > thead > tr > td.active,
1861
+ .table > tbody > tr > td.active,
1862
+ .table > tfoot > tr > td.active,
1863
+ .table > thead > tr > th.active,
1864
+ .table > tbody > tr > th.active,
1865
+ .table > tfoot > tr > th.active,
1866
+ .table > thead > tr.active > td,
1867
+ .table > tbody > tr.active > td,
1868
+ .table > tfoot > tr.active > td,
1869
+ .table > thead > tr.active > th,
1870
+ .table > tbody > tr.active > th,
1871
+ .table > tfoot > tr.active > th {
1872
+ background-color: #f5f5f5;
1873
+ }
1874
+ .table-hover > tbody > tr > td.active:hover,
1875
+ .table-hover > tbody > tr > th.active:hover,
1876
+ .table-hover > tbody > tr.active:hover > td,
1877
+ .table-hover > tbody > tr:hover > .active,
1878
+ .table-hover > tbody > tr.active:hover > th {
1879
+ background-color: #e8e8e8;
1880
+ }
1881
+ .table > thead > tr > td.success,
1882
+ .table > tbody > tr > td.success,
1883
+ .table > tfoot > tr > td.success,
1884
+ .table > thead > tr > th.success,
1885
+ .table > tbody > tr > th.success,
1886
+ .table > tfoot > tr > th.success,
1887
+ .table > thead > tr.success > td,
1888
+ .table > tbody > tr.success > td,
1889
+ .table > tfoot > tr.success > td,
1890
+ .table > thead > tr.success > th,
1891
+ .table > tbody > tr.success > th,
1892
+ .table > tfoot > tr.success > th {
1893
+ background-color: #dff0d8;
1894
+ }
1895
+ .table-hover > tbody > tr > td.success:hover,
1896
+ .table-hover > tbody > tr > th.success:hover,
1897
+ .table-hover > tbody > tr.success:hover > td,
1898
+ .table-hover > tbody > tr:hover > .success,
1899
+ .table-hover > tbody > tr.success:hover > th {
1900
+ background-color: #d0e9c6;
1901
+ }
1902
+ .table > thead > tr > td.info,
1903
+ .table > tbody > tr > td.info,
1904
+ .table > tfoot > tr > td.info,
1905
+ .table > thead > tr > th.info,
1906
+ .table > tbody > tr > th.info,
1907
+ .table > tfoot > tr > th.info,
1908
+ .table > thead > tr.info > td,
1909
+ .table > tbody > tr.info > td,
1910
+ .table > tfoot > tr.info > td,
1911
+ .table > thead > tr.info > th,
1912
+ .table > tbody > tr.info > th,
1913
+ .table > tfoot > tr.info > th {
1914
+ background-color: #d9edf7;
1915
+ }
1916
+ .table-hover > tbody > tr > td.info:hover,
1917
+ .table-hover > tbody > tr > th.info:hover,
1918
+ .table-hover > tbody > tr.info:hover > td,
1919
+ .table-hover > tbody > tr:hover > .info,
1920
+ .table-hover > tbody > tr.info:hover > th {
1921
+ background-color: #c4e3f3;
1922
+ }
1923
+ .table > thead > tr > td.warning,
1924
+ .table > tbody > tr > td.warning,
1925
+ .table > tfoot > tr > td.warning,
1926
+ .table > thead > tr > th.warning,
1927
+ .table > tbody > tr > th.warning,
1928
+ .table > tfoot > tr > th.warning,
1929
+ .table > thead > tr.warning > td,
1930
+ .table > tbody > tr.warning > td,
1931
+ .table > tfoot > tr.warning > td,
1932
+ .table > thead > tr.warning > th,
1933
+ .table > tbody > tr.warning > th,
1934
+ .table > tfoot > tr.warning > th {
1935
+ background-color: #fcf8e3;
1936
+ }
1937
+ .table-hover > tbody > tr > td.warning:hover,
1938
+ .table-hover > tbody > tr > th.warning:hover,
1939
+ .table-hover > tbody > tr.warning:hover > td,
1940
+ .table-hover > tbody > tr:hover > .warning,
1941
+ .table-hover > tbody > tr.warning:hover > th {
1942
+ background-color: #faf2cc;
1943
+ }
1944
+ .table > thead > tr > td.danger,
1945
+ .table > tbody > tr > td.danger,
1946
+ .table > tfoot > tr > td.danger,
1947
+ .table > thead > tr > th.danger,
1948
+ .table > tbody > tr > th.danger,
1949
+ .table > tfoot > tr > th.danger,
1950
+ .table > thead > tr.danger > td,
1951
+ .table > tbody > tr.danger > td,
1952
+ .table > tfoot > tr.danger > td,
1953
+ .table > thead > tr.danger > th,
1954
+ .table > tbody > tr.danger > th,
1955
+ .table > tfoot > tr.danger > th {
1956
+ background-color: #f2dede;
1957
+ }
1958
+ .table-hover > tbody > tr > td.danger:hover,
1959
+ .table-hover > tbody > tr > th.danger:hover,
1960
+ .table-hover > tbody > tr.danger:hover > td,
1961
+ .table-hover > tbody > tr:hover > .danger,
1962
+ .table-hover > tbody > tr.danger:hover > th {
1963
+ background-color: #ebcccc;
1964
+ }
1965
+ .table-responsive {
1966
+ min-height: .01%;
1967
+ overflow-x: auto;
1968
+ }
1969
+ @media screen and (max-width: 767px) {
1970
+ .table-responsive {
1971
+ width: 100%;
1972
+ margin-bottom: 15px;
1973
+ overflow-y: hidden;
1974
+ -ms-overflow-style: -ms-autohiding-scrollbar;
1975
+ border: 1px solid #dddddd;
1976
+ }
1977
+ .table-responsive > .table {
1978
+ margin-bottom: 0;
1979
+ }
1980
+ .table-responsive > .table > thead > tr > th,
1981
+ .table-responsive > .table > tbody > tr > th,
1982
+ .table-responsive > .table > tfoot > tr > th,
1983
+ .table-responsive > .table > thead > tr > td,
1984
+ .table-responsive > .table > tbody > tr > td,
1985
+ .table-responsive > .table > tfoot > tr > td {
1986
+ white-space: nowrap;
1987
+ }
1988
+ .table-responsive > .table-bordered {
1989
+ border: 0;
1990
+ }
1991
+ .table-responsive > .table-bordered > thead > tr > th:first-child,
1992
+ .table-responsive > .table-bordered > tbody > tr > th:first-child,
1993
+ .table-responsive > .table-bordered > tfoot > tr > th:first-child,
1994
+ .table-responsive > .table-bordered > thead > tr > td:first-child,
1995
+ .table-responsive > .table-bordered > tbody > tr > td:first-child,
1996
+ .table-responsive > .table-bordered > tfoot > tr > td:first-child {
1997
+ border-left: 0;
1998
+ }
1999
+ .table-responsive > .table-bordered > thead > tr > th:last-child,
2000
+ .table-responsive > .table-bordered > tbody > tr > th:last-child,
2001
+ .table-responsive > .table-bordered > tfoot > tr > th:last-child,
2002
+ .table-responsive > .table-bordered > thead > tr > td:last-child,
2003
+ .table-responsive > .table-bordered > tbody > tr > td:last-child,
2004
+ .table-responsive > .table-bordered > tfoot > tr > td:last-child {
2005
+ border-right: 0;
2006
+ }
2007
+ .table-responsive > .table-bordered > tbody > tr:last-child > th,
2008
+ .table-responsive > .table-bordered > tfoot > tr:last-child > th,
2009
+ .table-responsive > .table-bordered > tbody > tr:last-child > td,
2010
+ .table-responsive > .table-bordered > tfoot > tr:last-child > td {
2011
+ border-bottom: 0;
2012
+ }
2013
+ }
2014
  fieldset {
2015
  min-width: 0;
2016
  padding: 0;
2994
  -o-transition-timing-function: ease;
2995
  transition-timing-function: ease;
2996
  }
2997
+ .caret {
2998
+ display: inline-block;
2999
+ width: 0;
3000
+ height: 0;
3001
+ margin-left: 2px;
3002
+ vertical-align: middle;
3003
+ border-top: 4px dashed;
3004
+ border-top: 4px solid \9;
3005
+ border-right: 4px solid transparent;
3006
+ border-left: 4px solid transparent;
3007
+ }
3008
+ .dropup,
3009
+ .dropdown {
3010
+ position: relative;
3011
+ }
3012
+ .dropdown-toggle:focus {
3013
+ outline: 0;
3014
+ }
3015
+ .dropdown-menu {
3016
+ position: absolute;
3017
+ top: 100%;
3018
+ left: 0;
3019
+ z-index: 1000;
3020
+ display: none;
3021
+ float: left;
3022
+ min-width: 160px;
3023
+ padding: 5px 0;
3024
+ margin: 2px 0 0;
3025
+ font-size: 14px;
3026
+ text-align: left;
3027
+ list-style: none;
3028
+ background-color: #ffffff;
3029
+ -webkit-background-clip: padding-box;
3030
+ background-clip: padding-box;
3031
+ border: 1px solid #cccccc;
3032
+ border: 1px solid rgba(0, 0, 0, 0.15);
3033
+ border-radius: 4px;
3034
+ -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
3035
+ box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
3036
+ }
3037
+ .dropdown-menu.pull-right {
3038
+ right: 0;
3039
+ left: auto;
3040
+ }
3041
+ .dropdown-menu .divider {
3042
+ height: 1px;
3043
+ margin: 9px 0;
3044
+ overflow: hidden;
3045
+ background-color: #e5e5e5;
3046
+ }
3047
+ .dropdown-menu > li > a {
3048
+ display: block;
3049
+ padding: 3px 20px;
3050
+ clear: both;
3051
+ font-weight: 400;
3052
+ line-height: 1.42857143;
3053
+ color: #333333;
3054
+ white-space: nowrap;
3055
+ }
3056
+ .dropdown-menu > li > a:hover,
3057
+ .dropdown-menu > li > a:focus {
3058
+ color: #262626;
3059
+ text-decoration: none;
3060
+ background-color: #f5f5f5;
3061
+ }
3062
+ .dropdown-menu > .active > a,
3063
+ .dropdown-menu > .active > a:hover,
3064
+ .dropdown-menu > .active > a:focus {
3065
+ color: #ffffff;
3066
+ text-decoration: none;
3067
+ background-color: #337ab7;
3068
+ outline: 0;
3069
+ }
3070
+ .dropdown-menu > .disabled > a,
3071
+ .dropdown-menu > .disabled > a:hover,
3072
+ .dropdown-menu > .disabled > a:focus {
3073
+ color: #777777;
3074
+ }
3075
+ .dropdown-menu > .disabled > a:hover,
3076
+ .dropdown-menu > .disabled > a:focus {
3077
+ text-decoration: none;
3078
+ cursor: not-allowed;
3079
+ background-color: transparent;
3080
+ background-image: none;
3081
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
3082
+ }
3083
+ .open > .dropdown-menu {
3084
+ display: block;
3085
+ }
3086
+ .open > a {
3087
+ outline: 0;
3088
+ }
3089
+ .dropdown-menu-right {
3090
+ right: 0;
3091
+ left: auto;
3092
+ }
3093
+ .dropdown-menu-left {
3094
+ right: auto;
3095
+ left: 0;
3096
+ }
3097
+ .dropdown-header {
3098
+ display: block;
3099
+ padding: 3px 20px;
3100
+ font-size: 12px;
3101
+ line-height: 1.42857143;
3102
+ color: #777777;
3103
+ white-space: nowrap;
3104
+ }
3105
+ .dropdown-backdrop {
3106
+ position: fixed;
3107
+ top: 0;
3108
+ right: 0;
3109
+ bottom: 0;
3110
+ left: 0;
3111
+ z-index: 990;
3112
+ }
3113
+ .pull-right > .dropdown-menu {
3114
+ right: 0;
3115
+ left: auto;
3116
+ }
3117
+ .dropup .caret,
3118
+ .navbar-fixed-bottom .dropdown .caret {
3119
+ content: "";
3120
+ border-top: 0;
3121
+ border-bottom: 4px dashed;
3122
+ border-bottom: 4px solid \9;
3123
+ }
3124
+ .dropup .dropdown-menu,
3125
+ .navbar-fixed-bottom .dropdown .dropdown-menu {
3126
+ top: auto;
3127
+ bottom: 100%;
3128
+ margin-bottom: 2px;
3129
+ }
3130
+ @media (min-width: 768px) {
3131
+ .navbar-right .dropdown-menu {
3132
+ right: 0;
3133
+ left: auto;
3134
+ }
3135
+ .navbar-right .dropdown-menu-left {
3136
+ right: auto;
3137
+ left: 0;
3138
+ }
3139
+ }
3140
  .nav {
3141
  padding-left: 0;
3142
  margin-bottom: 0;
3450
  .alert-danger .alert-link {
3451
  color: #843534;
3452
  }
3453
+ @-webkit-keyframes progress-bar-stripes {
3454
+ from {
3455
+ background-position: 40px 0;
3456
+ }
3457
+ to {
3458
+ background-position: 0 0;
3459
+ }
3460
+ }
3461
+ @-o-keyframes progress-bar-stripes {
3462
+ from {
3463
+ background-position: 40px 0;
3464
+ }
3465
+ to {
3466
+ background-position: 0 0;
3467
+ }
3468
+ }
3469
+ @keyframes progress-bar-stripes {
3470
+ from {
3471
+ background-position: 40px 0;
3472
+ }
3473
+ to {
3474
+ background-position: 0 0;
3475
+ }
3476
+ }
3477
+ .progress {
3478
+ height: 20px;
3479
+ margin-bottom: 20px;
3480
+ overflow: hidden;
3481
+ background-color: #f5f5f5;
3482
+ border-radius: 4px;
3483
+ -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
3484
+ box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
3485
+ }
3486
+ .progress-bar {
3487
+ float: left;
3488
+ width: 0%;
3489
+ height: 100%;
3490
+ font-size: 12px;
3491
+ line-height: 20px;
3492
+ color: #ffffff;
3493
+ text-align: center;
3494
+ background-color: #337ab7;
3495
+ -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
3496
+ box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
3497
+ -webkit-transition: width 0.6s ease;
3498
+ -o-transition: width 0.6s ease;
3499
+ transition: width 0.6s ease;
3500
+ }
3501
+ .progress-striped .progress-bar,
3502
+ .progress-bar-striped {
3503
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
3504
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
3505
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
3506
+ -webkit-background-size: 40px 40px;
3507
+ background-size: 40px 40px;
3508
+ }
3509
+ .progress.active .progress-bar,
3510
+ .progress-bar.active {
3511
+ -webkit-animation: progress-bar-stripes 2s linear infinite;
3512
+ -o-animation: progress-bar-stripes 2s linear infinite;
3513
+ animation: progress-bar-stripes 2s linear infinite;
3514
+ }
3515
+ .progress-bar-success {
3516
+ background-color: #5cb85c;
3517
+ }
3518
+ .progress-striped .progress-bar-success {
3519
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
3520
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
3521
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
3522
+ }
3523
+ .progress-bar-info {
3524
+ background-color: #5bc0de;
3525
+ }
3526
+ .progress-striped .progress-bar-info {
3527
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
3528
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
3529
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
3530
+ }
3531
+ .progress-bar-warning {
3532
+ background-color: #f0ad4e;
3533
+ }
3534
+ .progress-striped .progress-bar-warning {
3535
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
3536
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
3537
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
3538
+ }
3539
+ .progress-bar-danger {
3540
+ background-color: #d9534f;
3541
+ }
3542
+ .progress-striped .progress-bar-danger {
3543
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
3544
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
3545
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
3546
+ }
3547
  .panel {
3548
  margin-bottom: 20px;
3549
  background-color: #ffffff;
3887
  .panel-danger > .panel-footer + .panel-collapse > .panel-body {
3888
  border-bottom-color: #ebccd1;
3889
  }
3890
+ .close {
3891
+ float: right;
3892
+ font-size: 21px;
3893
+ font-weight: bold;
3894
+ line-height: 1;
3895
+ color: #000000;
3896
+ text-shadow: 0 1px 0 #ffffff;
3897
+ filter: alpha(opacity=20);
3898
+ opacity: 0.2;
3899
+ }
3900
+ .close:hover,
3901
+ .close:focus {
3902
+ color: #000000;
3903
+ text-decoration: none;
3904
+ cursor: pointer;
3905
+ filter: alpha(opacity=50);
3906
+ opacity: 0.5;
3907
+ }
3908
+ button.close {
3909
+ padding: 0;
3910
+ cursor: pointer;
3911
+ background: transparent;
3912
+ border: 0;
3913
+ -webkit-appearance: none;
3914
+ appearance: none;
3915
+ }
3916
  .clearfix:before,
3917
  .clearfix:after,
3918
+ .container:before,
3919
+ .container:after,
3920
+ .container-fluid:before,
3921
+ .container-fluid:after,
3922
+ .row:before,
3923
+ .row:after,
3924
  .form-horizontal .form-group:before,
3925
  .form-horizontal .form-group:after,
3926
  .nav:before,
3931
  content: " ";
3932
  }
3933
  .clearfix:after,
3934
+ .container:after,
3935
+ .container-fluid:after,
3936
+ .row:after,
3937
  .form-horizontal .form-group:after,
3938
  .nav:after,
3939
  .panel-body:after {
assets/bootstrap/css/bootstrap.min.css CHANGED
@@ -4,4 +4,4 @@
4
  * Bootstrap v3.4.1 (https://getbootstrap.com/)
5
  * Copyright 2011-2019 Twitter, Inc.
6
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
7
- *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}@font-face{font-family:"Glyphicons Halflings";src:url("../fonts/glyphicons-halflings-regular.eot");src:url("../fonts/glyphicons-halflings-regular.eot?#iefix") format("embedded-opentype"),url("../fonts/glyphicons-halflings-regular.woff2") format("woff2"),url("../fonts/glyphicons-halflings-regular.woff") format("woff"),url("../fonts/glyphicons-halflings-regular.ttf") format("truetype"),url("../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular") format("svg")}.glyphicon{position:relative;top:1px;display:inline-block;font-family:"Glyphicons Halflings";font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-euro:before,.glyphicon-eur:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:hover,a:focus{color:#23527c;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role="button"]{cursor:pointer}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-appearance:none;appearance:none}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"].disabled,input[type="checkbox"].disabled,fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"]{cursor:not-allowed}input[type="file"]{display:block}input[type="range"]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, 0.6);box-shadow:inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, 0.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{background-color:transparent;border:0}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}@media screen and (-webkit-min-device-pixel-ratio:0){input[type="date"].form-control,input[type="time"].form-control,input[type="datetime-local"].form-control,input[type="month"].form-control{line-height:34px}input[type="date"].input-sm,input[type="time"].input-sm,input[type="datetime-local"].input-sm,input[type="month"].input-sm,.input-group-sm input[type="date"],.input-group-sm input[type="time"],.input-group-sm input[type="datetime-local"],.input-group-sm input[type="month"]{line-height:30px}input[type="date"].input-lg,input[type="time"].input-lg,input[type="datetime-local"].input-lg,input[type="month"].input-lg,.input-group-lg input[type="date"],.input-group-lg input[type="time"],.input-group-lg input[type="datetime-local"],.input-group-lg input[type="month"]{line-height:46px}}.form-group{margin-bottom:15px}.radio,.checkbox{position:relative;display:block;margin-top:10px;margin-bottom:10px}.radio.disabled label,.checkbox.disabled label,fieldset[disabled] .radio label,fieldset[disabled] .checkbox label{cursor:not-allowed}.radio label,.checkbox label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{position:absolute;margin-top:4px \9;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.radio-inline.disabled,.checkbox-inline.disabled,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm,select[multiple].input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm textarea.form-control,.form-group-sm select[multiple].form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}textarea.input-lg,select[multiple].input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg textarea.form-control,.form-group-lg select[multiple].form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.input-lg+.form-control-feedback,.input-group-lg+.form-control-feedback,.form-group-lg .form-control+.form-control-feedback{width:46px;height:46px;line-height:46px}.input-sm+.form-control-feedback,.input-group-sm+.form-control-feedback,.form-group-sm .form-control+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline,.has-success.radio label,.has-success.checkbox label,.has-success.radio-inline label,.has-success.checkbox-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline,.has-warning.radio label,.has-warning.checkbox label,.has-warning.radio-inline label,.has-warning.checkbox-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline,.has-error.radio label,.has-error.checkbox label,.has-error.radio-inline label,.has-error.checkbox-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn,.form-inline .input-group .form-control{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .radio label,.form-inline .checkbox label{padding-left:0}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:active:focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn.active.focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus,.btn.focus{color:#333;text-decoration:none}.btn:active,.btn.active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);opacity:.65;-webkit-box-shadow:none;box-shadow:none}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:focus,.btn-default.focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;background-image:none;border-color:#adadad}.btn-default:active:hover,.btn-default.active:hover,.open>.dropdown-toggle.btn-default:hover,.btn-default:active:focus,.btn-default.active:focus,.open>.dropdown-toggle.btn-default:focus,.btn-default:active.focus,.btn-default.active.focus,.open>.dropdown-toggle.btn-default.focus{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled.focus,.btn-default[disabled].focus,fieldset[disabled] .btn-default.focus{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary:focus,.btn-primary.focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;background-image:none;border-color:#204d74}.btn-primary:active:hover,.btn-primary.active:hover,.open>.dropdown-toggle.btn-primary:hover,.btn-primary:active:focus,.btn-primary.active:focus,.open>.dropdown-toggle.btn-primary:focus,.btn-primary:active.focus,.btn-primary.active.focus,.open>.dropdown-toggle.btn-primary.focus{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled.focus,.btn-primary[disabled].focus,fieldset[disabled] .btn-primary.focus{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:focus,.btn-success.focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;background-image:none;border-color:#398439}.btn-success:active:hover,.btn-success.active:hover,.open>.dropdown-toggle.btn-success:hover,.btn-success:active:focus,.btn-success.active:focus,.open>.dropdown-toggle.btn-success:focus,.btn-success:active.focus,.btn-success.active.focus,.open>.dropdown-toggle.btn-success.focus{color:#fff;background-color:#398439;border-color:#255625}.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled.focus,.btn-success[disabled].focus,fieldset[disabled] .btn-success.focus{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:focus,.btn-info.focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;background-image:none;border-color:#269abc}.btn-info:active:hover,.btn-info.active:hover,.open>.dropdown-toggle.btn-info:hover,.btn-info:active:focus,.btn-info.active:focus,.open>.dropdown-toggle.btn-info:focus,.btn-info:active.focus,.btn-info.active.focus,.open>.dropdown-toggle.btn-info.focus{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled.focus,.btn-info[disabled].focus,fieldset[disabled] .btn-info.focus{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:focus,.btn-warning.focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;background-image:none;border-color:#d58512}.btn-warning:active:hover,.btn-warning.active:hover,.open>.dropdown-toggle.btn-warning:hover,.btn-warning:active:focus,.btn-warning.active:focus,.open>.dropdown-toggle.btn-warning:focus,.btn-warning:active.focus,.btn-warning.active.focus,.open>.dropdown-toggle.btn-warning.focus{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled.focus,.btn-warning[disabled].focus,fieldset[disabled] .btn-warning.focus{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:focus,.btn-danger.focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;background-image:none;border-color:#ac2925}.btn-danger:active:hover,.btn-danger.active:hover,.open>.dropdown-toggle.btn-danger:hover,.btn-danger:active:focus,.btn-danger.active:focus,.open>.dropdown-toggle.btn-danger:focus,.btn-danger:active.focus,.btn-danger.active.focus,.open>.dropdown-toggle.btn-danger.focus{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled.focus,.btn-danger[disabled].focus,fieldset[disabled] .btn-danger.focus{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link:active,.btn-link.active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#777;text-decoration:none}.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-property:height, visibility;-o-transition-property:height, visibility;transition-property:height, visibility;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge,.btn-group-xs>.btn .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.05);box-shadow:0 1px 1px rgba(0,0,0,0.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a,.panel-title>small,.panel-title>.small,.panel-title>small>a,.panel-title>.small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.table,.panel>.table-responsive>.table,.panel>.panel-collapse>.table{margin-bottom:0}.panel>.table caption,.panel>.table-responsive>.table caption,.panel>.panel-collapse>.table caption{padding-right:15px;padding-left:15px}.panel>.table:first-child,.panel>.table-responsive:first-child>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child,.panel>.table-responsive:last-child>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.panel-body,.panel-group .panel-heading+.panel-collapse>.list-group{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.clearfix:before,.clearfix:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.nav:before,.nav:after,.panel-body:before,.panel-body:after{display:table;content:" "}.clearfix:after,.form-horizontal .form-group:after,.nav:after,.panel-body:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right !important}.pull-left{float:left !important}.hide{display:none !important}.show{display:block !important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none !important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none !important}.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block{display:none !important}@media (max-width:767px){.visible-xs{display:block !important}table.visible-xs{display:table !important}tr.visible-xs{display:table-row !important}th.visible-xs,td.visible-xs{display:table-cell !important}}@media (max-width:767px){.visible-xs-block{display:block !important}}@media (max-width:767px){.visible-xs-inline{display:inline !important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block !important}table.visible-sm{display:table !important}tr.visible-sm{display:table-row !important}th.visible-sm,td.visible-sm{display:table-cell !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block !important}table.visible-md{display:table !important}tr.visible-md{display:table-row !important}th.visible-md,td.visible-md{display:table-cell !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block !important}}@media (min-width:1200px){.visible-lg{display:block !important}table.visible-lg{display:table !important}tr.visible-lg{display:table-row !important}th.visible-lg,td.visible-lg{display:table-cell !important}}@media (min-width:1200px){.visible-lg-block{display:block !important}}@media (min-width:1200px){.visible-lg-inline{display:inline !important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block !important}}@media (max-width:767px){.hidden-xs{display:none !important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none !important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none !important}}@media (min-width:1200px){.hidden-lg{display:none !important}}.visible-print{display:none !important}@media print{.visible-print{display:block !important}table.visible-print{display:table !important}tr.visible-print{display:table-row !important}th.visible-print,td.visible-print{display:table-cell !important}}.visible-print-block{display:none !important}@media print{.visible-print-block{display:block !important}}.visible-print-inline{display:none !important}@media print{.visible-print-inline{display:inline !important}}.visible-print-inline-block{display:none !important}@media print{.visible-print-inline-block{display:inline-block !important}}@media print{.hidden-print{display:none !important}}
4
  * Bootstrap v3.4.1 (https://getbootstrap.com/)
5
  * Copyright 2011-2019 Twitter, Inc.
6
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
7
+ *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}@font-face{font-family:"Glyphicons Halflings";src:url("../fonts/glyphicons-halflings-regular.eot");src:url("../fonts/glyphicons-halflings-regular.eot?#iefix") format("embedded-opentype"),url("../fonts/glyphicons-halflings-regular.woff2") format("woff2"),url("../fonts/glyphicons-halflings-regular.woff") format("woff"),url("../fonts/glyphicons-halflings-regular.ttf") format("truetype"),url("../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular") format("svg")}.glyphicon{position:relative;top:1px;display:inline-block;font-family:"Glyphicons Halflings";font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-euro:before,.glyphicon-eur:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:hover,a:focus{color:#23527c;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role="button"]{cursor:pointer}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-appearance:none;appearance:none}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"].disabled,input[type="checkbox"].disabled,fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"]{cursor:not-allowed}input[type="file"]{display:block}input[type="range"]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, 0.6);box-shadow:inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, 0.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{background-color:transparent;border:0}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}@media screen and (-webkit-min-device-pixel-ratio:0){input[type="date"].form-control,input[type="time"].form-control,input[type="datetime-local"].form-control,input[type="month"].form-control{line-height:34px}input[type="date"].input-sm,input[type="time"].input-sm,input[type="datetime-local"].input-sm,input[type="month"].input-sm,.input-group-sm input[type="date"],.input-group-sm input[type="time"],.input-group-sm input[type="datetime-local"],.input-group-sm input[type="month"]{line-height:30px}input[type="date"].input-lg,input[type="time"].input-lg,input[type="datetime-local"].input-lg,input[type="month"].input-lg,.input-group-lg input[type="date"],.input-group-lg input[type="time"],.input-group-lg input[type="datetime-local"],.input-group-lg input[type="month"]{line-height:46px}}.form-group{margin-bottom:15px}.radio,.checkbox{position:relative;display:block;margin-top:10px;margin-bottom:10px}.radio.disabled label,.checkbox.disabled label,fieldset[disabled] .radio label,fieldset[disabled] .checkbox label{cursor:not-allowed}.radio label,.checkbox label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{position:absolute;margin-top:4px \9;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.radio-inline.disabled,.checkbox-inline.disabled,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm,select[multiple].input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm textarea.form-control,.form-group-sm select[multiple].form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}textarea.input-lg,select[multiple].input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg textarea.form-control,.form-group-lg select[multiple].form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.input-lg+.form-control-feedback,.input-group-lg+.form-control-feedback,.form-group-lg .form-control+.form-control-feedback{width:46px;height:46px;line-height:46px}.input-sm+.form-control-feedback,.input-group-sm+.form-control-feedback,.form-group-sm .form-control+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline,.has-success.radio label,.has-success.checkbox label,.has-success.radio-inline label,.has-success.checkbox-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline,.has-warning.radio label,.has-warning.checkbox label,.has-warning.radio-inline label,.has-warning.checkbox-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline,.has-error.radio label,.has-error.checkbox label,.has-error.radio-inline label,.has-error.checkbox-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn,.form-inline .input-group .form-control{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .radio label,.form-inline .checkbox label{padding-left:0}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:active:focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn.active.focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus,.btn.focus{color:#333;text-decoration:none}.btn:active,.btn.active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);opacity:.65;-webkit-box-shadow:none;box-shadow:none}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:focus,.btn-default.focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;background-image:none;border-color:#adadad}.btn-default:active:hover,.btn-default.active:hover,.open>.dropdown-toggle.btn-default:hover,.btn-default:active:focus,.btn-default.active:focus,.open>.dropdown-toggle.btn-default:focus,.btn-default:active.focus,.btn-default.active.focus,.open>.dropdown-toggle.btn-default.focus{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled.focus,.btn-default[disabled].focus,fieldset[disabled] .btn-default.focus{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary:focus,.btn-primary.focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;background-image:none;border-color:#204d74}.btn-primary:active:hover,.btn-primary.active:hover,.open>.dropdown-toggle.btn-primary:hover,.btn-primary:active:focus,.btn-primary.active:focus,.open>.dropdown-toggle.btn-primary:focus,.btn-primary:active.focus,.btn-primary.active.focus,.open>.dropdown-toggle.btn-primary.focus{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled.focus,.btn-primary[disabled].focus,fieldset[disabled] .btn-primary.focus{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:focus,.btn-success.focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;background-image:none;border-color:#398439}.btn-success:active:hover,.btn-success.active:hover,.open>.dropdown-toggle.btn-success:hover,.btn-success:active:focus,.btn-success.active:focus,.open>.dropdown-toggle.btn-success:focus,.btn-success:active.focus,.btn-success.active.focus,.open>.dropdown-toggle.btn-success.focus{color:#fff;background-color:#398439;border-color:#255625}.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled.focus,.btn-success[disabled].focus,fieldset[disabled] .btn-success.focus{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:focus,.btn-info.focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;background-image:none;border-color:#269abc}.btn-info:active:hover,.btn-info.active:hover,.open>.dropdown-toggle.btn-info:hover,.btn-info:active:focus,.btn-info.active:focus,.open>.dropdown-toggle.btn-info:focus,.btn-info:active.focus,.btn-info.active.focus,.open>.dropdown-toggle.btn-info.focus{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled.focus,.btn-info[disabled].focus,fieldset[disabled] .btn-info.focus{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:focus,.btn-warning.focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;background-image:none;border-color:#d58512}.btn-warning:active:hover,.btn-warning.active:hover,.open>.dropdown-toggle.btn-warning:hover,.btn-warning:active:focus,.btn-warning.active:focus,.open>.dropdown-toggle.btn-warning:focus,.btn-warning:active.focus,.btn-warning.active.focus,.open>.dropdown-toggle.btn-warning.focus{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled.focus,.btn-warning[disabled].focus,fieldset[disabled] .btn-warning.focus{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:focus,.btn-danger.focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;background-image:none;border-color:#ac2925}.btn-danger:active:hover,.btn-danger.active:hover,.open>.dropdown-toggle.btn-danger:hover,.btn-danger:active:focus,.btn-danger.active:focus,.open>.dropdown-toggle.btn-danger:focus,.btn-danger:active.focus,.btn-danger.active.focus,.open>.dropdown-toggle.btn-danger.focus{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled.focus,.btn-danger[disabled].focus,fieldset[disabled] .btn-danger.focus{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link:active,.btn-link.active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#777;text-decoration:none}.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-property:height, visibility;-o-transition-property:height, visibility;transition-property:height, visibility;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid \9;border-right:4px solid transparent;border-left:4px solid transparent}.dropup,.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.175);box-shadow:0 6px 12px rgba(0,0,0,0.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#777}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid \9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge,.btn-group-xs>.btn .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.05);box-shadow:0 1px 1px rgba(0,0,0,0.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a,.panel-title>small,.panel-title>.small,.panel-title>small>a,.panel-title>.small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.table,.panel>.table-responsive>.table,.panel>.panel-collapse>.table{margin-bottom:0}.panel>.table caption,.panel>.table-responsive>.table caption,.panel>.panel-collapse>.table caption{padding-right:15px;padding-left:15px}.panel>.table:first-child,.panel>.table-responsive:first-child>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child,.panel>.table-responsive:last-child>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.panel-body,.panel-group .panel-heading+.panel-collapse>.list-group{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.clearfix:before,.clearfix:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.nav:before,.nav:after,.panel-body:before,.panel-body:after{display:table;content:" "}.clearfix:after,.form-horizontal .form-group:after,.nav:after,.panel-body:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right !important}.pull-left{float:left !important}.hide{display:none !important}.show{display:block !important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none !important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none !important}.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block{display:none !important}@media (max-width:767px){.visible-xs{display:block !important}table.visible-xs{display:table !important}tr.visible-xs{display:table-row !important}th.visible-xs,td.visible-xs{display:table-cell !important}}@media (max-width:767px){.visible-xs-block{display:block !important}}@media (max-width:767px){.visible-xs-inline{display:inline !important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block !important}table.visible-sm{display:table !important}tr.visible-sm{display:table-row !important}th.visible-sm,td.visible-sm{display:table-cell !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block !important}table.visible-md{display:table !important}tr.visible-md{display:table-row !important}th.visible-md,td.visible-md{display:table-cell !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block !important}}@media (min-width:1200px){.visible-lg{display:block !important}table.visible-lg{display:table !important}tr.visible-lg{display:table-row !important}th.visible-lg,td.visible-lg{display:table-cell !important}}@media (min-width:1200px){.visible-lg-block{display:block !important}}@media (min-width:1200px){.visible-lg-inline{display:inline !important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block !important}}@media (max-width:767px){.hidden-xs{display:none !important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none !important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none !important}}@media (min-width:1200px){.hidden-lg{display:none !important}}.visible-print{display:none !important}@media print{.visible-print{display:block !important}table.visible-print{display:table !important}tr.visible-print{display:table-row !important}th.visible-print,td.visible-print{display:table-cell !important}}.visible-print-block{display:none !important}@media print{.visible-print-block{display:block !important}}.visible-print-inline{display:none !important}@media print{.visible-print-inline{display:inline !important}}.visible-print-inline-block{display:none !important}@media print{.visible-print-inline-block{display:inline-block !important}}@media print{.hidden-print{display:none !important}}
assets/bootstrap/js/bootstrap.js CHANGED
@@ -4,7 +4,7 @@
4
 
5
  /*!
6
  * Bootstrap v3.4.1 (https://getbootstrap.com/)
7
- * Copyright 2011-2021 Twitter, Inc.
8
  * Licensed under the MIT license
9
  */
10
 
@@ -19,6 +19,172 @@ if (typeof jQuery === 'undefined') {
19
  }
20
  }(jQuery);
21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  /* ========================================================================
23
  * Bootstrap: tab.js v3.4.1
24
  * https://getbootstrap.com/docs/3.4/javascript/#tabs
4
 
5
  /*!
6
  * Bootstrap v3.4.1 (https://getbootstrap.com/)
7
+ * Copyright 2011-2022 Twitter, Inc.
8
  * Licensed under the MIT license
9
  */
10
 
19
  }
20
  }(jQuery);
21
 
22
+ /* ========================================================================
23
+ * Bootstrap: dropdown.js v3.4.1
24
+ * https://getbootstrap.com/docs/3.4/javascript/#dropdowns
25
+ * ========================================================================
26
+ * Copyright 2011-2019 Twitter, Inc.
27
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
28
+ * ======================================================================== */
29
+
30
+
31
+ +function ($) {
32
+ 'use strict';
33
+
34
+ // DROPDOWN CLASS DEFINITION
35
+ // =========================
36
+
37
+ var backdrop = '.dropdown-backdrop'
38
+ var toggle = '[data-toggle="dropdown"]'
39
+ var Dropdown = function (element) {
40
+ $(element).on('click.bs.dropdown', this.toggle)
41
+ }
42
+
43
+ Dropdown.VERSION = '3.4.1'
44
+
45
+ function getParent($this) {
46
+ var selector = $this.attr('data-target')
47
+
48
+ if (!selector) {
49
+ selector = $this.attr('href')
50
+ selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
51
+ }
52
+
53
+ var $parent = selector !== '#' ? $(document).find(selector) : null
54
+
55
+ return $parent && $parent.length ? $parent : $this.parent()
56
+ }
57
+
58
+ function clearMenus(e) {
59
+ if (e && e.which === 3) return
60
+ $(backdrop).remove()
61
+ $(toggle).each(function () {
62
+ var $this = $(this)
63
+ var $parent = getParent($this)
64
+ var relatedTarget = { relatedTarget: this }
65
+
66
+ if (!$parent.hasClass('open')) return
67
+
68
+ if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return
69
+
70
+ $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
71
+
72
+ if (e.isDefaultPrevented()) return
73
+
74
+ $this.attr('aria-expanded', 'false')
75
+ $parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget))
76
+ })
77
+ }
78
+
79
+ Dropdown.prototype.toggle = function (e) {
80
+ var $this = $(this)
81
+
82
+ if ($this.is('.disabled, :disabled')) return
83
+
84
+ var $parent = getParent($this)
85
+ var isActive = $parent.hasClass('open')
86
+
87
+ clearMenus()
88
+
89
+ if (!isActive) {
90
+ if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
91
+ // if mobile we use a backdrop because click events don't delegate
92
+ $(document.createElement('div'))
93
+ .addClass('dropdown-backdrop')
94
+ .insertAfter($(this))
95
+ .on('click', clearMenus)
96
+ }
97
+
98
+ var relatedTarget = { relatedTarget: this }
99
+ $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
100
+
101
+ if (e.isDefaultPrevented()) return
102
+
103
+ $this
104
+ .trigger('focus')
105
+ .attr('aria-expanded', 'true')
106
+
107
+ $parent
108
+ .toggleClass('open')
109
+ .trigger($.Event('shown.bs.dropdown', relatedTarget))
110
+ }
111
+
112
+ return false
113
+ }
114
+
115
+ Dropdown.prototype.keydown = function (e) {
116
+ if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
117
+
118
+ var $this = $(this)
119
+
120
+ e.preventDefault()
121
+ e.stopPropagation()
122
+
123
+ if ($this.is('.disabled, :disabled')) return
124
+
125
+ var $parent = getParent($this)
126
+ var isActive = $parent.hasClass('open')
127
+
128
+ if (!isActive && e.which != 27 || isActive && e.which == 27) {
129
+ if (e.which == 27) $parent.find(toggle).trigger('focus')
130
+ return $this.trigger('click')
131
+ }
132
+
133
+ var desc = ' li:not(.disabled):visible a'
134
+ var $items = $parent.find('.dropdown-menu' + desc)
135
+
136
+ if (!$items.length) return
137
+
138
+ var index = $items.index(e.target)
139
+
140
+ if (e.which == 38 && index > 0) index-- // up
141
+ if (e.which == 40 && index < $items.length - 1) index++ // down
142
+ if (!~index) index = 0
143
+
144
+ $items.eq(index).trigger('focus')
145
+ }
146
+
147
+
148
+ // DROPDOWN PLUGIN DEFINITION
149
+ // ==========================
150
+
151
+ function Plugin(option) {
152
+ return this.each(function () {
153
+ var $this = $(this)
154
+ var data = $this.data('bs.dropdown')
155
+
156
+ if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
157
+ if (typeof option == 'string') data[option].call($this)
158
+ })
159
+ }
160
+
161
+ var old = $.fn.dropdown
162
+
163
+ $.fn.dropdown = Plugin
164
+ $.fn.dropdown.Constructor = Dropdown
165
+
166
+
167
+ // DROPDOWN NO CONFLICT
168
+ // ====================
169
+
170
+ $.fn.dropdown.noConflict = function () {
171
+ $.fn.dropdown = old
172
+ return this
173
+ }
174
+
175
+
176
+ // APPLY TO STANDARD DROPDOWN ELEMENTS
177
+ // ===================================
178
+
179
+ $(document)
180
+ .on('click.bs.dropdown.data-api', clearMenus)
181
+ .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
182
+ .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
183
+ .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
184
+ .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown)
185
+
186
+ }(jQuery);
187
+
188
  /* ========================================================================
189
  * Bootstrap: tab.js v3.4.1
190
  * https://getbootstrap.com/docs/3.4/javascript/#tabs
assets/css/admin/a2-optimized.css ADDED
@@ -0,0 +1,972 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #wpwrap {
2
+ background-color: #FFF;
3
+ }
4
+
5
+ #a2-optimized-wrapper {
6
+ font-family: Poppins;
7
+ /*
8
+ * The following styles are auto-applied to elements with
9
+ * transition="modal" when their visibility is toggled
10
+ * by Vue.js.
11
+ *
12
+ * You can easily play with the modal transition by editing
13
+ * these styles.
14
+ */
15
+ /* checkboxes */
16
+ /* Spinner */
17
+ /* Animations */
18
+ /* The flip card container - set the width and height to whatever you want. We have added the border property to demonstrate that the flip itself goes out of the box on hover (remove perspective if you don't want the 3D effect */
19
+ /* This container is needed to position the front and back side */
20
+ /* Style the back side */
21
+ /* when bootstrap 'lg' becomes 'md' */
22
+ /* added for the hosting matchup graphs that can't quite wait for 'md' to kick in to still look ok */
23
+ }
24
+ #a2-optimized-wrapper h1,
25
+ #a2-optimized-wrapper h2,
26
+ #a2-optimized-wrapper h3,
27
+ #a2-optimized-wrapper h4,
28
+ #a2-optimized-wrapper h5,
29
+ #a2-optimized-wrapper h6 {
30
+ font-family: Raleway;
31
+ font-weight: 900;
32
+ }
33
+ #a2-optimized-wrapper h1 .normal, #a2-optimized-wrapper h1.normal,
34
+ #a2-optimized-wrapper h2 .normal,
35
+ #a2-optimized-wrapper h2.normal,
36
+ #a2-optimized-wrapper h3 .normal,
37
+ #a2-optimized-wrapper h3.normal,
38
+ #a2-optimized-wrapper h4 .normal,
39
+ #a2-optimized-wrapper h4.normal,
40
+ #a2-optimized-wrapper h5 .normal,
41
+ #a2-optimized-wrapper h5.normal,
42
+ #a2-optimized-wrapper h6 .normal,
43
+ #a2-optimized-wrapper h6.normal {
44
+ font-weight: 500;
45
+ }
46
+ #a2-optimized-wrapper h1.upper,
47
+ #a2-optimized-wrapper h2.upper,
48
+ #a2-optimized-wrapper h3.upper,
49
+ #a2-optimized-wrapper h4.upper,
50
+ #a2-optimized-wrapper h5.upper,
51
+ #a2-optimized-wrapper h6.upper {
52
+ text-transform: uppercase;
53
+ }
54
+ #a2-optimized-wrapper h2 {
55
+ font-size: 45px;
56
+ }
57
+ #a2-optimized-wrapper h3 {
58
+ font-size: 30px;
59
+ }
60
+ #a2-optimized-wrapper h3.less-vertical-space {
61
+ margin-top: 5px;
62
+ margin-bottom: 5px;
63
+ }
64
+ #a2-optimized-wrapper h4 {
65
+ font-size: 26px;
66
+ font-weight: 500;
67
+ }
68
+ #a2-optimized-wrapper h4.less-vertical-space {
69
+ margin-top: 5px;
70
+ margin-bottom: 5px;
71
+ }
72
+ #a2-optimized-wrapper #a2-optimized-header .search input {
73
+ width: 100%;
74
+ margin-top: 40px;
75
+ }
76
+ #a2-optimized-wrapper #a2-optimized-header .search p.small {
77
+ margin-top: 0;
78
+ }
79
+ #a2-optimized-wrapper #a2-optimized-header .title img {
80
+ padding-bottom: 50px;
81
+ }
82
+ #a2-optimized-wrapper .a2-optimized-navigation {
83
+ /*margin-bottom: 100px; trying out other values */
84
+ margin-bottom: 20px;
85
+ }
86
+ #a2-optimized-wrapper ul.bullet-points {
87
+ list-style-type: disc;
88
+ }
89
+ #a2-optimized-wrapper .navlink-button {
90
+ text-align: center;
91
+ width: 100%;
92
+ color: #1c1c1c;
93
+ padding-top: 10px;
94
+ padding-bottom: 10px;
95
+ border-color: transparent;
96
+ border-width: 2px;
97
+ border-style: solid;
98
+ border-radius: 10px;
99
+ border-spacing: 5px;
100
+ background-color: transparent;
101
+ cursor: pointer;
102
+ text-decoration: none;
103
+ font-size: 20px;
104
+ font-family: Raleway;
105
+ font-weight: 700;
106
+ }
107
+ #a2-optimized-wrapper .navlink-button:hover {
108
+ border-color: #e0e0e0;
109
+ background-color: #e0e0e0;
110
+ }
111
+ #a2-optimized-wrapper .navlink-button.current {
112
+ background-color: #128413;
113
+ border-color: #128413;
114
+ color: white;
115
+ }
116
+ #a2-optimized-wrapper .side-nav .navlink-button {
117
+ font-size: 16px;
118
+ padding-top: 20px;
119
+ padding-bottom: 20px;
120
+ padding-left: 0px;
121
+ padding-right: 0px;
122
+ }
123
+ #a2-optimized-wrapper .side-nav .navlink-button:hover {
124
+ background-color: transparent;
125
+ }
126
+ #a2-optimized-wrapper .side-nav .navlink-button.current {
127
+ background-color: transparent;
128
+ color: #1c1c1c;
129
+ }
130
+ #a2-optimized-wrapper .side-nav .navlink-wrapper {
131
+ padding-left: 0px;
132
+ padding-right: 0px;
133
+ }
134
+ #a2-optimized-wrapper .cta-btn-green {
135
+ background-color: #128413;
136
+ color: #FFF;
137
+ }
138
+ #a2-optimized-wrapper .cta-btn-green:hover {
139
+ box-shadow: 0px 4px 10px rgba(28, 28, 28, 0.25), 0px 4px 4px rgba(28, 28, 28, 0.25);
140
+ color: #FFF !important;
141
+ }
142
+ #a2-optimized-wrapper .btn-xlg {
143
+ padding: 15px 60px;
144
+ }
145
+ #a2-optimized-wrapper .bg-green, #a2-optimized-wrapper .bg-empty {
146
+ background-color: #128413;
147
+ padding-top: 15px;
148
+ padding-bottom: 5px;
149
+ border-radius: 10px;
150
+ }
151
+ #a2-optimized-wrapper .bg-empty {
152
+ background-color: #333;
153
+ }
154
+ #a2-optimized-wrapper .border-left {
155
+ border-left: 1px solid #1c1c1c;
156
+ }
157
+ #a2-optimized-wrapper .box-element {
158
+ position: relative;
159
+ background: #FFF;
160
+ border: 2px solid rgba(93, 89, 89, 0.4);
161
+ box-shadow: 0px 4px 10px rgba(28, 28, 28, 0.25), 0px 4px 4px rgba(28, 28, 28, 0.25);
162
+ border-radius: 10px;
163
+ margin-bottom: 15px;
164
+ }
165
+ #a2-optimized-wrapper .box-element h3 {
166
+ color: #1c1c1c;
167
+ text-transform: uppercase;
168
+ }
169
+ #a2-optimized-wrapper .box-element .box-element {
170
+ border-width: 1px;
171
+ box-shadow: 0px 4px 4px rgba(28, 28, 28, 0.25);
172
+ margin-bottom: 25px;
173
+ }
174
+ #a2-optimized-wrapper .box-element .padding-15 {
175
+ padding-left: 15px;
176
+ padding-right: 15px;
177
+ }
178
+ #a2-optimized-wrapper .box-element .padding-top-30 {
179
+ padding-top: 30px;
180
+ }
181
+ #a2-optimized-wrapper .box-element .row.header {
182
+ margin-left: 0;
183
+ margin-right: 15px;
184
+ }
185
+ #a2-optimized-wrapper .box-element .box-title {
186
+ text-transform: uppercase;
187
+ font-style: normal;
188
+ font-weight: 500;
189
+ }
190
+ #a2-optimized-wrapper .box-element.danger {
191
+ border-color: rgba(237, 17, 17, 0.35);
192
+ }
193
+ #a2-optimized-wrapper .box-element.success {
194
+ border-color: rgba(18, 132, 19, 0.35);
195
+ }
196
+ #a2-optimized-wrapper .box-element.warn {
197
+ border-color: rgba(252, 140, 30, 0.35);
198
+ }
199
+ #a2-optimized-wrapper .box-element.empty {
200
+ border-color: rgba(51, 51, 51, 0.35);
201
+ }
202
+ #a2-optimized-wrapper .box-element.clear {
203
+ border: none;
204
+ box-shadow: none;
205
+ }
206
+ #a2-optimized-wrapper .box-element div.best-practices-status {
207
+ font-size: 14px;
208
+ margin-bottom: 1em;
209
+ }
210
+ #a2-optimized-wrapper #a2-optimized-optstatus .box-element .box-element {
211
+ padding: 10px 0;
212
+ }
213
+ #a2-optimized-wrapper #a2-optimized-serverperformance .box-element .row {
214
+ padding: 0 10px;
215
+ }
216
+ #a2-optimized-wrapper #a2-optimized-serverperformance .box-element h4 {
217
+ margin-bottom: 0;
218
+ }
219
+ #a2-optimized-wrapper #a2-optimized-serverperformance .flip-card-front .wave-bg.success {
220
+ background: url("../../images/admin/wave-success.png") no-repeat bottom;
221
+ background-size: 110%, 75%;
222
+ }
223
+ #a2-optimized-wrapper #a2-optimized-serverperformance .flip-card-front .wave-bg.warn {
224
+ background: url("../../images/admin/wave-warn.png") no-repeat bottom;
225
+ background-size: 110%;
226
+ }
227
+ #a2-optimized-wrapper #a2-optimized-serverperformance .flip-card-front .wave-bg.danger {
228
+ background: url("../../images/admin/wave-danger.png") no-repeat bottom;
229
+ background-size: 110%;
230
+ }
231
+ #a2-optimized-wrapper #a2-optimized-serverperformance .flip-card-front .wave-bg.empty {
232
+ background: url("../../images/admin/wave-empty.png") no-repeat bottom;
233
+ background-size: 110%, 75%;
234
+ }
235
+ #a2-optimized-wrapper #a2-optimized-serverperformance .flip-card-back .wave-bg {
236
+ background: none;
237
+ }
238
+ #a2-optimized-wrapper .opt-extra-settings-items h4 {
239
+ font-size: 22px;
240
+ }
241
+ #a2-optimized-wrapper .opt-extra-settings-items .setting-item {
242
+ padding-left: 10px;
243
+ }
244
+ #a2-optimized-wrapper .opt-extra-settings-items .setting-item h4 {
245
+ font-size: 20px;
246
+ }
247
+ #a2-optimized-wrapper .opt-extra-settings-items .row {
248
+ margin-bottom: 10px;
249
+ }
250
+ #a2-optimized-wrapper .opt-extra-settings-items .desc {
251
+ color: #128413;
252
+ }
253
+ #a2-optimized-wrapper span.small {
254
+ padding-top: 0px;
255
+ font-size: 50%;
256
+ }
257
+ #a2-optimized-wrapper .circles-text {
258
+ font-weight: 700;
259
+ }
260
+ #a2-optimized-wrapper .text-center,
261
+ #a2-optimized-wrapper .circle {
262
+ text-align: center;
263
+ }
264
+ #a2-optimized-wrapper .line-graph {
265
+ position: relative;
266
+ height: 40px;
267
+ width: 100%;
268
+ }
269
+ #a2-optimized-wrapper .graph-card p.sub-heading {
270
+ margin-top: 0px;
271
+ }
272
+ #a2-optimized-wrapper .graph-card-centered {
273
+ text-align: center;
274
+ }
275
+ #a2-optimized-wrapper .graph-legend .graph-legend-header {
276
+ font-size: 0.5em;
277
+ white-space: nowrap;
278
+ color: #ffffff;
279
+ }
280
+ #a2-optimized-wrapper .graph-legend .graph-legend-header .danger {
281
+ background-color: #ED1111;
282
+ }
283
+ #a2-optimized-wrapper .graph-legend .graph-legend-header .success {
284
+ background-color: #128413;
285
+ }
286
+ #a2-optimized-wrapper .graph-legend .graph-legend-header .warn {
287
+ background-color: #FC8C1E;
288
+ }
289
+ #a2-optimized-wrapper .graph-legend .left-label {
290
+ border-left: 1px solid black;
291
+ padding: 0px;
292
+ text-align: left;
293
+ }
294
+ #a2-optimized-wrapper .graph-legend .left-label span {
295
+ left: -30px;
296
+ }
297
+ #a2-optimized-wrapper .info-toggle-button {
298
+ position: absolute;
299
+ right: 5px;
300
+ top: 5px;
301
+ font-size: 20px;
302
+ z-index: 100;
303
+ cursor: pointer;
304
+ }
305
+ #a2-optimized-wrapper .text-left {
306
+ text-align: left;
307
+ }
308
+ #a2-optimized-wrapper .text-right {
309
+ text-align: right;
310
+ }
311
+ #a2-optimized-wrapper .text-center {
312
+ text-align: center;
313
+ }
314
+ #a2-optimized-wrapper .line-height-15 {
315
+ line-height: 15px;
316
+ }
317
+ #a2-optimized-wrapper span.danger {
318
+ color: #ED1111;
319
+ }
320
+ #a2-optimized-wrapper span.success {
321
+ color: #128413;
322
+ }
323
+ #a2-optimized-wrapper span.warn {
324
+ color: #FC8C1E;
325
+ }
326
+ #a2-optimized-wrapper span.thishost {
327
+ color: #009aca;
328
+ }
329
+ #a2-optimized-wrapper span.empty {
330
+ color: #333;
331
+ }
332
+ #a2-optimized-wrapper .padding-bottom {
333
+ padding-bottom: 15px;
334
+ }
335
+ #a2-optimized-wrapper a.toggle {
336
+ color: #1c1c1c;
337
+ text-decoration: none;
338
+ }
339
+ #a2-optimized-wrapper a.toggle:hover {
340
+ color: #5d5959;
341
+ cursor: pointer;
342
+ }
343
+ #a2-optimized-wrapper .opt-completed {
344
+ text-align: center;
345
+ }
346
+ #a2-optimized-wrapper .opt-completed h4 {
347
+ font-size: 20px;
348
+ font-weight: 700;
349
+ line-height: 24px;
350
+ }
351
+ #a2-optimized-wrapper .opt-completed span {
352
+ color: #FC8C1E;
353
+ }
354
+ #a2-optimized-wrapper input[type=text] {
355
+ max-width: 100%;
356
+ }
357
+ #a2-optimized-wrapper input[type=number] {
358
+ max-width: 100%;
359
+ }
360
+ #a2-optimized-wrapper input.opt-setting-input {
361
+ margin-left: 20px;
362
+ width: 90%;
363
+ }
364
+ #a2-optimized-wrapper #circles-ttfb .circles-text,
365
+ #a2-optimized-wrapper #circles-cls .circles-text {
366
+ left: -32px;
367
+ top: -10px;
368
+ font-size: 39px;
369
+ }
370
+ #a2-optimized-wrapper #circles-overall_score .circles-text {
371
+ left: -32px;
372
+ top: -10px;
373
+ font-size: 39px;
374
+ }
375
+ #a2-optimized-wrapper .modal-mask {
376
+ position: fixed;
377
+ z-index: 9998;
378
+ top: 0;
379
+ left: 0;
380
+ width: 100%;
381
+ height: 100%;
382
+ background-color: rgba(0, 0, 0, 0.5);
383
+ display: table;
384
+ transition: opacity 0.3s ease;
385
+ }
386
+ #a2-optimized-wrapper .modal-wrapper {
387
+ display: table-cell;
388
+ vertical-align: middle;
389
+ }
390
+ #a2-optimized-wrapper .modal-container {
391
+ width: 500px;
392
+ max-width: 90%;
393
+ margin: 0px auto;
394
+ padding: 20px 30px;
395
+ background-color: #fff;
396
+ border-radius: 2px;
397
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.33);
398
+ transition: all 0.3s ease;
399
+ font-family: Helvetica, Arial, sans-serif;
400
+ }
401
+ #a2-optimized-wrapper .modal-top-bar {
402
+ text-align: right;
403
+ }
404
+ #a2-optimized-wrapper .modal-header h3 {
405
+ margin-top: 0;
406
+ }
407
+ #a2-optimized-wrapper .modal-body {
408
+ margin: 20px 0;
409
+ }
410
+ #a2-optimized-wrapper .modal-dialog-text {
411
+ color: #128413;
412
+ }
413
+ #a2-optimized-wrapper .modal-default-button {
414
+ float: right;
415
+ }
416
+ #a2-optimized-wrapper .modal-footer {
417
+ text-align: right;
418
+ }
419
+ #a2-optimized-wrapper .modal-enter {
420
+ opacity: 0;
421
+ }
422
+ #a2-optimized-wrapper .modal-leave-active {
423
+ opacity: 0;
424
+ }
425
+ #a2-optimized-wrapper .modal-enter .modal-container,
426
+ #a2-optimized-wrapper .modal-leave-active .modal-container {
427
+ -webkit-transform: scale(1.1);
428
+ transform: scale(1.1);
429
+ }
430
+ #a2-optimized-wrapper .utility-icon {
431
+ width: 25px;
432
+ height: 25px;
433
+ display: inline;
434
+ float: right;
435
+ }
436
+ #a2-optimized-wrapper .utility-icon .dropdown-menu {
437
+ padding: 5px;
438
+ border-color: #128413;
439
+ right: 0;
440
+ left: auto;
441
+ }
442
+ #a2-optimized-wrapper #menu-bell {
443
+ right: 0;
444
+ left: initial;
445
+ }
446
+ #a2-optimized-wrapper .tg-list-item {
447
+ margin: 0 10px;
448
+ list-style: none;
449
+ }
450
+ #a2-optimized-wrapper .tgl {
451
+ display: none;
452
+ }
453
+ #a2-optimized-wrapper .tgl, #a2-optimized-wrapper .tgl:after, #a2-optimized-wrapper .tgl:before, #a2-optimized-wrapper .tgl *, #a2-optimized-wrapper .tgl *:after, #a2-optimized-wrapper .tgl *:before, #a2-optimized-wrapper .tgl + .tgl-btn {
454
+ box-sizing: border-box;
455
+ }
456
+ #a2-optimized-wrapper .tgl::selection, #a2-optimized-wrapper .tgl:after::selection, #a2-optimized-wrapper .tgl:before::selection, #a2-optimized-wrapper .tgl *::selection, #a2-optimized-wrapper .tgl *:after::selection, #a2-optimized-wrapper .tgl *:before::selection, #a2-optimized-wrapper .tgl + .tgl-btn::selection {
457
+ background: none;
458
+ }
459
+ #a2-optimized-wrapper .tgl + .tgl-btn {
460
+ outline: 0;
461
+ display: block;
462
+ width: 4em;
463
+ height: 2em;
464
+ position: relative;
465
+ cursor: pointer;
466
+ user-select: none;
467
+ }
468
+ #a2-optimized-wrapper .tgl + .tgl-btn:after, #a2-optimized-wrapper .tgl + .tgl-btn:before {
469
+ position: relative;
470
+ display: block;
471
+ content: "";
472
+ width: 50%;
473
+ height: 100%;
474
+ }
475
+ #a2-optimized-wrapper .tgl + .tgl-btn:after {
476
+ left: 0;
477
+ }
478
+ #a2-optimized-wrapper .tgl + .tgl-btn:before {
479
+ display: none;
480
+ }
481
+ #a2-optimized-wrapper .tgl:checked + .tgl-btn:after {
482
+ left: 50%;
483
+ }
484
+ #a2-optimized-wrapper .tgl-light + .tgl-btn {
485
+ background: #f0f0f0;
486
+ border-radius: 2em;
487
+ padding: 2px;
488
+ transition: all 0.4s ease;
489
+ }
490
+ #a2-optimized-wrapper .tgl-light + .tgl-btn:after {
491
+ border-radius: 50%;
492
+ background: #fff;
493
+ transition: all 0.2s ease;
494
+ }
495
+ #a2-optimized-wrapper .tgl-light:checked + .tgl-btn {
496
+ background: #9FD6AE;
497
+ }
498
+ #a2-optimized-wrapper .tgl-ios + .tgl-btn {
499
+ background: #fbfbfb;
500
+ border-radius: 2em;
501
+ padding: 2px;
502
+ transition: all 0.4s ease;
503
+ border: 1px solid #e8eae9;
504
+ }
505
+ #a2-optimized-wrapper .tgl-ios + .tgl-btn:after {
506
+ border-radius: 2em;
507
+ background: #fbfbfb;
508
+ transition: left 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275), padding 0.3s ease, margin 0.3s ease;
509
+ box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1), 0 4px 0 rgba(0, 0, 0, 0.08);
510
+ }
511
+ #a2-optimized-wrapper .tgl-ios + .tgl-btn:hover:after {
512
+ will-change: padding;
513
+ }
514
+ #a2-optimized-wrapper .tgl-ios + .tgl-btn:active {
515
+ box-shadow: inset 0 0 0 2em #e8eae9;
516
+ }
517
+ #a2-optimized-wrapper .tgl-ios + .tgl-btn:active:after {
518
+ padding-right: 0.8em;
519
+ }
520
+ #a2-optimized-wrapper .tgl-ios:checked + .tgl-btn {
521
+ background: #86d993;
522
+ }
523
+ #a2-optimized-wrapper .tgl-ios:checked + .tgl-btn:active {
524
+ box-shadow: none;
525
+ }
526
+ #a2-optimized-wrapper .tgl-ios:checked + .tgl-btn:active:after {
527
+ margin-left: -0.8em;
528
+ }
529
+ #a2-optimized-wrapper .tgl-skewed + .tgl-btn {
530
+ overflow: hidden;
531
+ transform: skew(-10deg);
532
+ backface-visibility: hidden;
533
+ transition: all 0.2s ease;
534
+ font-family: sans-serif;
535
+ background: #888;
536
+ }
537
+ #a2-optimized-wrapper .tgl-skewed + .tgl-btn:after, #a2-optimized-wrapper .tgl-skewed + .tgl-btn:before {
538
+ transform: skew(10deg);
539
+ display: inline-block;
540
+ transition: all 0.2s ease;
541
+ width: 100%;
542
+ text-align: center;
543
+ position: absolute;
544
+ line-height: 2em;
545
+ font-weight: bold;
546
+ color: #fff;
547
+ text-shadow: 0 1px 0 rgba(0, 0, 0, 0.4);
548
+ }
549
+ #a2-optimized-wrapper .tgl-skewed + .tgl-btn:after {
550
+ left: 100%;
551
+ content: attr(data-tg-on);
552
+ }
553
+ #a2-optimized-wrapper .tgl-skewed + .tgl-btn:before {
554
+ left: 0;
555
+ content: attr(data-tg-off);
556
+ }
557
+ #a2-optimized-wrapper .tgl-skewed + .tgl-btn:active {
558
+ background: #888;
559
+ }
560
+ #a2-optimized-wrapper .tgl-skewed + .tgl-btn:active:before {
561
+ left: -10%;
562
+ }
563
+ #a2-optimized-wrapper .tgl-skewed:checked + .tgl-btn {
564
+ background: #86d993;
565
+ }
566
+ #a2-optimized-wrapper .tgl-skewed:checked + .tgl-btn:before {
567
+ left: -100%;
568
+ }
569
+ #a2-optimized-wrapper .tgl-skewed:checked + .tgl-btn:after {
570
+ left: 0;
571
+ }
572
+ #a2-optimized-wrapper .tgl-skewed:checked + .tgl-btn:active:after {
573
+ left: 10%;
574
+ }
575
+ #a2-optimized-wrapper .tgl-flat + .tgl-btn {
576
+ padding: 2px;
577
+ transition: all 0.2s ease;
578
+ background: #fff;
579
+ border: 4px solid #f2f2f2;
580
+ border-radius: 2em;
581
+ }
582
+ #a2-optimized-wrapper .tgl-flat + .tgl-btn:after {
583
+ transition: all 0.2s ease;
584
+ background: #f2f2f2;
585
+ content: "";
586
+ border-radius: 1em;
587
+ }
588
+ #a2-optimized-wrapper .tgl-flat:checked + .tgl-btn {
589
+ border: 4px solid #7FC6A6;
590
+ }
591
+ #a2-optimized-wrapper .tgl-flat:checked + .tgl-btn:after {
592
+ left: 50%;
593
+ background: #7FC6A6;
594
+ }
595
+ #a2-optimized-wrapper .tgl-flip + .tgl-btn {
596
+ padding: 2px;
597
+ transition: all 0.2s ease;
598
+ font-family: sans-serif;
599
+ perspective: 100px;
600
+ }
601
+ #a2-optimized-wrapper .tgl-flip + .tgl-btn:after, #a2-optimized-wrapper .tgl-flip + .tgl-btn:before {
602
+ display: inline-block;
603
+ transition: all 0.4s ease;
604
+ width: 100%;
605
+ text-align: center;
606
+ position: absolute;
607
+ line-height: 2em;
608
+ font-weight: bold;
609
+ color: #fff;
610
+ position: absolute;
611
+ top: 0;
612
+ left: 0;
613
+ backface-visibility: hidden;
614
+ border-radius: 4px;
615
+ }
616
+ #a2-optimized-wrapper .tgl-flip + .tgl-btn:after {
617
+ content: attr(data-tg-on);
618
+ background: #02C66F;
619
+ transform: rotateY(-180deg);
620
+ }
621
+ #a2-optimized-wrapper .tgl-flip + .tgl-btn:before {
622
+ background: #FF3A19;
623
+ content: attr(data-tg-off);
624
+ }
625
+ #a2-optimized-wrapper .tgl-flip + .tgl-btn:active:before {
626
+ transform: rotateY(-20deg);
627
+ }
628
+ #a2-optimized-wrapper .tgl-flip:checked + .tgl-btn:before {
629
+ transform: rotateY(180deg);
630
+ }
631
+ #a2-optimized-wrapper .tgl-flip:checked + .tgl-btn:after {
632
+ transform: rotateY(0);
633
+ left: 0;
634
+ background: #7FC6A6;
635
+ }
636
+ #a2-optimized-wrapper .tgl-flip:checked + .tgl-btn:active:after {
637
+ transform: rotateY(20deg);
638
+ }
639
+ #a2-optimized-wrapper .la-line-spin-fade-rotating,
640
+ #a2-optimized-wrapper .la-line-spin-fade-rotating > div {
641
+ position: relative;
642
+ -webkit-box-sizing: border-box;
643
+ -moz-box-sizing: border-box;
644
+ box-sizing: border-box;
645
+ }
646
+ #a2-optimized-wrapper .la-line-spin-fade-rotating {
647
+ display: block;
648
+ font-size: 0;
649
+ color: #fff;
650
+ }
651
+ #a2-optimized-wrapper .la-line-spin-fade-rotating.la-dark {
652
+ color: #333;
653
+ }
654
+ #a2-optimized-wrapper .la-line-spin-fade-rotating > div {
655
+ display: inline-block;
656
+ float: none;
657
+ background-color: currentColor;
658
+ border: 0 solid currentColor;
659
+ }
660
+ #a2-optimized-wrapper .la-line-spin-fade-rotating {
661
+ width: 32px;
662
+ height: 32px;
663
+ -webkit-animation: ball-spin-fade-rotating-rotate 6s infinite linear;
664
+ -moz-animation: ball-spin-fade-rotating-rotate 6s infinite linear;
665
+ -o-animation: ball-spin-fade-rotating-rotate 6s infinite linear;
666
+ animation: ball-spin-fade-rotating-rotate 6s infinite linear;
667
+ }
668
+ #a2-optimized-wrapper .la-line-spin-fade-rotating > div {
669
+ position: absolute;
670
+ width: 2px;
671
+ height: 10px;
672
+ margin: 2px;
673
+ margin-top: -5px;
674
+ margin-left: -1px;
675
+ border-radius: 0;
676
+ -webkit-animation: line-spin-fade-rotating 1s infinite ease-in-out;
677
+ -moz-animation: line-spin-fade-rotating 1s infinite ease-in-out;
678
+ -o-animation: line-spin-fade-rotating 1s infinite ease-in-out;
679
+ animation: line-spin-fade-rotating 1s infinite ease-in-out;
680
+ }
681
+ #a2-optimized-wrapper .la-line-spin-fade-rotating > div:nth-child(1) {
682
+ top: 15%;
683
+ left: 50%;
684
+ -webkit-transform: rotate(0deg);
685
+ -moz-transform: rotate(0deg);
686
+ -ms-transform: rotate(0deg);
687
+ -o-transform: rotate(0deg);
688
+ transform: rotate(0deg);
689
+ -webkit-animation-delay: -1.125s;
690
+ -moz-animation-delay: -1.125s;
691
+ -o-animation-delay: -1.125s;
692
+ animation-delay: -1.125s;
693
+ }
694
+ #a2-optimized-wrapper .la-line-spin-fade-rotating > div:nth-child(2) {
695
+ top: 25.2512626585%;
696
+ left: 74.7487373415%;
697
+ -webkit-transform: rotate(45deg);
698
+ -moz-transform: rotate(45deg);
699
+ -ms-transform: rotate(45deg);
700
+ -o-transform: rotate(45deg);
701
+ transform: rotate(45deg);
702
+ -webkit-animation-delay: -1.25s;
703
+ -moz-animation-delay: -1.25s;
704
+ -o-animation-delay: -1.25s;
705
+ animation-delay: -1.25s;
706
+ }
707
+ #a2-optimized-wrapper .la-line-spin-fade-rotating > div:nth-child(3) {
708
+ top: 50%;
709
+ left: 85%;
710
+ -webkit-transform: rotate(90deg);
711
+ -moz-transform: rotate(90deg);
712
+ -ms-transform: rotate(90deg);
713
+ -o-transform: rotate(90deg);
714
+ transform: rotate(90deg);
715
+ -webkit-animation-delay: -1.375s;
716
+ -moz-animation-delay: -1.375s;
717
+ -o-animation-delay: -1.375s;
718
+ animation-delay: -1.375s;
719
+ }
720
+ #a2-optimized-wrapper .la-line-spin-fade-rotating > div:nth-child(4) {
721
+ top: 74.7487373415%;
722
+ left: 74.7487373415%;
723
+ -webkit-transform: rotate(135deg);
724
+ -moz-transform: rotate(135deg);
725
+ -ms-transform: rotate(135deg);
726
+ -o-transform: rotate(135deg);
727
+ transform: rotate(135deg);
728
+ -webkit-animation-delay: -1.5s;
729
+ -moz-animation-delay: -1.5s;
730
+ -o-animation-delay: -1.5s;
731
+ animation-delay: -1.5s;
732
+ }
733
+ #a2-optimized-wrapper .la-line-spin-fade-rotating > div:nth-child(5) {
734
+ top: 84.9999999974%;
735
+ left: 50.0000000004%;
736
+ -webkit-transform: rotate(180deg);
737
+ -moz-transform: rotate(180deg);
738
+ -ms-transform: rotate(180deg);
739
+ -o-transform: rotate(180deg);
740
+ transform: rotate(180deg);
741
+ -webkit-animation-delay: -1.625s;
742
+ -moz-animation-delay: -1.625s;
743
+ -o-animation-delay: -1.625s;
744
+ animation-delay: -1.625s;
745
+ }
746
+ #a2-optimized-wrapper .la-line-spin-fade-rotating > div:nth-child(6) {
747
+ top: 74.7487369862%;
748
+ left: 25.2512627193%;
749
+ -webkit-transform: rotate(225deg);
750
+ -moz-transform: rotate(225deg);
751
+ -ms-transform: rotate(225deg);
752
+ -o-transform: rotate(225deg);
753
+ transform: rotate(225deg);
754
+ -webkit-animation-delay: -1.75s;
755
+ -moz-animation-delay: -1.75s;
756
+ -o-animation-delay: -1.75s;
757
+ animation-delay: -1.75s;
758
+ }
759
+ #a2-optimized-wrapper .la-line-spin-fade-rotating > div:nth-child(7) {
760
+ top: 49.9999806189%;
761
+ left: 15.0000039834%;
762
+ -webkit-transform: rotate(270deg);
763
+ -moz-transform: rotate(270deg);
764
+ -ms-transform: rotate(270deg);
765
+ -o-transform: rotate(270deg);
766
+ transform: rotate(270deg);
767
+ -webkit-animation-delay: -1.875s;
768
+ -moz-animation-delay: -1.875s;
769
+ -o-animation-delay: -1.875s;
770
+ animation-delay: -1.875s;
771
+ }
772
+ #a2-optimized-wrapper .la-line-spin-fade-rotating > div:nth-child(8) {
773
+ top: 25.2506949798%;
774
+ left: 25.2513989292%;
775
+ -webkit-transform: rotate(315deg);
776
+ -moz-transform: rotate(315deg);
777
+ -ms-transform: rotate(315deg);
778
+ -o-transform: rotate(315deg);
779
+ transform: rotate(315deg);
780
+ -webkit-animation-delay: -2s;
781
+ -moz-animation-delay: -2s;
782
+ -o-animation-delay: -2s;
783
+ animation-delay: -2s;
784
+ }
785
+ #a2-optimized-wrapper .la-line-spin-fade-rotating.la-sm {
786
+ width: 16px;
787
+ height: 16px;
788
+ }
789
+ #a2-optimized-wrapper .la-line-spin-fade-rotating.la-sm > div {
790
+ width: 1px;
791
+ height: 4px;
792
+ margin-top: -2px;
793
+ margin-left: 0;
794
+ }
795
+ #a2-optimized-wrapper .la-line-spin-fade-rotating.la-2x {
796
+ width: 64px;
797
+ height: 64px;
798
+ }
799
+ #a2-optimized-wrapper .la-line-spin-fade-rotating.la-2x > div {
800
+ width: 4px;
801
+ height: 20px;
802
+ margin-top: -10px;
803
+ margin-left: -2px;
804
+ }
805
+ #a2-optimized-wrapper .la-line-spin-fade-rotating.la-3x {
806
+ width: 96px;
807
+ height: 96px;
808
+ }
809
+ #a2-optimized-wrapper .la-line-spin-fade-rotating.la-3x > div {
810
+ width: 6px;
811
+ height: 30px;
812
+ margin-top: -15px;
813
+ margin-left: -3px;
814
+ }
815
+ @-webkit-keyframes ball-spin-fade-rotating-rotate {
816
+ 100% {
817
+ -webkit-transform: rotate(360deg);
818
+ transform: rotate(360deg);
819
+ }
820
+ }
821
+ @-moz-keyframes ball-spin-fade-rotating-rotate {
822
+ 100% {
823
+ -moz-transform: rotate(360deg);
824
+ transform: rotate(360deg);
825
+ }
826
+ }
827
+ @-o-keyframes ball-spin-fade-rotating-rotate {
828
+ 100% {
829
+ -o-transform: rotate(360deg);
830
+ transform: rotate(360deg);
831
+ }
832
+ }
833
+ @keyframes ball-spin-fade-rotating-rotate {
834
+ 100% {
835
+ -webkit-transform: rotate(360deg);
836
+ -moz-transform: rotate(360deg);
837
+ -o-transform: rotate(360deg);
838
+ transform: rotate(360deg);
839
+ }
840
+ }
841
+ @-webkit-keyframes line-spin-fade-rotating {
842
+ 50% {
843
+ opacity: 0.2;
844
+ }
845
+ 100% {
846
+ opacity: 1;
847
+ }
848
+ }
849
+ @-moz-keyframes line-spin-fade-rotating {
850
+ 50% {
851
+ opacity: 0.2;
852
+ }
853
+ 100% {
854
+ opacity: 1;
855
+ }
856
+ }
857
+ @-o-keyframes line-spin-fade-rotating {
858
+ 50% {
859
+ opacity: 0.2;
860
+ }
861
+ 100% {
862
+ opacity: 1;
863
+ }
864
+ }
865
+ @keyframes line-spin-fade-rotating {
866
+ 50% {
867
+ opacity: 0.2;
868
+ }
869
+ 100% {
870
+ opacity: 1;
871
+ }
872
+ }
873
+ #a2-optimized-wrapper .flip-card-inner.flip-start {
874
+ animation-duration: 0.25s;
875
+ animation-name: flipToFront1;
876
+ animation-iteration-count: 1;
877
+ animation-fill-mode: forwards;
878
+ }
879
+ #a2-optimized-wrapper .flip-card-inner.flip-finish {
880
+ animation-duration: 0.25s;
881
+ animation-name: flipToFront2;
882
+ animation-iteration-count: 1;
883
+ animation-fill-mode: forwards;
884
+ }
885
+ #a2-optimized-wrapper .flip-card-inner.flipped.flip-start {
886
+ animation-duration: 0.25s;
887
+ animation-name: flipToFront3;
888
+ animation-iteration-count: 1;
889
+ animation-fill-mode: forwards;
890
+ }
891
+ #a2-optimized-wrapper .flip-card-inner.flipped.flip-finish {
892
+ animation-duration: 0.25s;
893
+ animation-name: flipToFront4;
894
+ animation-iteration-count: 1;
895
+ animation-fill-mode: forwards;
896
+ }
897
+ @keyframes flipToFront1 {
898
+ from {
899
+ transform: rotateY(0deg);
900
+ }
901
+ to {
902
+ transform: rotateY(90deg);
903
+ }
904
+ }
905
+ @keyframes flipToFront2 {
906
+ from {
907
+ transform: rotateY(90deg);
908
+ }
909
+ to {
910
+ transform: rotateY(180deg);
911
+ }
912
+ }
913
+ @keyframes flipToFront3 {
914
+ from {
915
+ transform: rotateY(180deg);
916
+ }
917
+ to {
918
+ transform: rotateY(270deg);
919
+ }
920
+ }
921
+ @keyframes flipToFront4 {
922
+ from {
923
+ transform: rotateY(270deg);
924
+ }
925
+ to {
926
+ transform: rotateY(360deg);
927
+ }
928
+ }
929
+ #a2-optimized-wrapper .flip-card {
930
+ background-color: transparent;
931
+ perspective: 1000px;
932
+ }
933
+ #a2-optimized-wrapper .flip-card-inner {
934
+ position: relative;
935
+ transition: transform 0.8s;
936
+ transform-style: preserve-3d;
937
+ }
938
+ #a2-optimized-wrapper .flip-card-back {
939
+ transform: rotateY(180deg);
940
+ }
941
+ #a2-optimized-wrapper .flipped.flip-card-inner {
942
+ transform: rotateY(180deg);
943
+ }
944
+ @media (max-width: 1366px) {
945
+ #a2-optimized-wrapper .box-element.hide-small {
946
+ border: none;
947
+ box-shadow: none;
948
+ }
949
+ #a2-optimized-wrapper .navlink-button {
950
+ font-size: 14px;
951
+ }
952
+ #a2-optimized-wrapper .side-nav {
953
+ margin-bottom: 20px;
954
+ }
955
+ #a2-optimized-wrapper .side-nav .navlink-button {
956
+ font-size: 16px;
957
+ }
958
+ #a2-optimized-wrapper .border-left {
959
+ border: none;
960
+ }
961
+ #a2-optimized-wrapper #a2-optimized-optstatus,
962
+ #a2-optimized-wrapper #a2-optimized-pagespeed {
963
+ min-width: 600px;
964
+ }
965
+ }
966
+ @media (max-width: 1440px) {
967
+ #a2-optimized-wrapper .hosting-matchup-graph-container {
968
+ min-width: 500px;
969
+ }
970
+ }
971
+
972
+ /*# sourceMappingURL=a2-optimized.css.map */
assets/css/admin/a2-optimized.css.map ADDED
@@ -0,0 +1 @@
 
1
+ {"version":3,"sourceRoot":"","sources":["../../scss/a2-optimized.scss"],"names":[],"mappings":"AAaA;EACI,kBARI;;;AAWR;EACI;AAogBA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA0CA;AAuQA;AAqMA;AA4IA;AAMA;AAOA;AAYA;AA4BA;;AAzrCA;AAAA;AAAA;AAAA;AAAA;AAAA;EAMI;EACA;;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EAEI;;AAGJ;AAAA;AAAA;AAAA;AAAA;AAAA;EACI;;AAIR;EACI;;AAGJ;EACI;;AAEA;EACI;EACA;;AAIR;EACI;EACA;;AAEA;EACI;EACA;;AAMA;EACI;EACA;;AAGJ;EACI;;AAIJ;EACI;;AAKZ;AACI;EACA;;AAGJ;EACI;;AAGJ;EACI;EACA;EACA,OA1FD;EA2FC;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EAEA;EACA;EACA;;AAEA;EACI,cA1GA;EA2GA,kBA3GA;;AA+GJ;EACI,kBArHJ;EAsHI,cAtHJ;EAwHI;;AAMJ;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAGJ;EACI;EACA,OAzIT;;AA+IC;EACI;EACA;;AAMR;EACI,kBA1JA;EA2JA,OArJA;;AAwJJ;EACI;EACA;;AAGJ;EACI;;AAGJ;EACI,kBAxKA;EAyKA;EACA;EACA;;AAGJ;EACI,kBA5KG;;AA+KP;EACI;;AAGJ;EACI;EACA,YAlLA;EAmLA;EACA;EACA;EACA;;AAEA;EACI,OA7LL;EA8LK;;AAGJ;EACI;EACA;EACA;;AAGJ;EACI;EACA;;AAGJ;EACI;;AAGJ;EACI;EACA;;AAGJ;EACI;EACA;EACA;;AAGJ;EACI;;AAGJ;EACI;;AAGJ;EACI;;AAGJ;EACI;;AAGJ;EACI;EACA;;AAGJ;EACI;EACA;;AAKJ;EACI;;AAMA;EACI;;AAGJ;EACI;;AAMA;EACI;EACA;;AAGJ;EACI;EACA;;AAGJ;EACI;EACA;;AAEJ;EACI;EACA;;AAMR;EACI;;AAMR;EACI;;AAGJ;EACI;;AAEA;EACI;;AAIR;EACI;;AAGJ;EACI,OAzTJ;;AA6TJ;EACI;EACA;;AAGJ;EACI;;AAGJ;AAAA;EAEI;;AAGJ;EACI;EACA;EACA;;AAIA;EACI;;AAIR;EACI;;AAIA;EACI;EACA;EACA;;AAEA;EACI,kBA1VP;;AA6VG;EACI,kBAtWR;;AAyWI;EACI,kBAzWP;;AA8WD;EACI;EACA;EACA;;AAEA;EACI;;AAKZ;EACI;EACA;EACA;EACA;EACA;EACA;;AAGJ;EACI;;AAGJ;EACI;;AAGJ;EACI;;AAGJ;EACI;;AAGJ;EACI,OA5YC;;AA+YL;EACI,OAxZA;;AA2ZJ;EACI,OA3ZC;;AA8ZL;EACI,OArZG;;AAwZP;EACI,OAjaG;;AAoaP;EACI;;AAGJ;EACI,OA1aD;EA2aC;;AAEA;EACI,OA5aH;EA6aG;;AAIR;EACI;;AAEA;EACI;EACA;EACA;;AAGJ;EACI,OA9bH;;AAkcL;EACI;;AAGJ;EACI;;AAGJ;EACI;EACA;;AAKA;AAAA;EACI;EACA;EACA;;AAKJ;EACI;EACA;EACA;;AAIR;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGJ;EACI;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGJ;EACI;;AAGJ;EACI;;AAGJ;EACI;;AAGJ;EACI,OA3gBA;;AA8gBJ;EACI;;AAGJ;EACI;;AAYJ;EACI;;AAGJ;EACI;;AAGJ;AAAA;EAEI;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAEA;EACI;EACA,cArjBJ;EAsjBI;EACA;;AAIR;EACI;EACA;;AAIJ;EACI;EACA;;AAGJ;EACI;;AAGA;EAOI;;AAEA;EACI;;AAIR;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EAEI;EACA;EACA;EACA;EACA;;AAGJ;EACI;;AAGJ;EACI;;AAIR;EACI;;AAMJ;EACI;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;;AAIR;EACI;;AAKJ;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA,YACI;EAEJ,YACI;;AAIR;EACI;;AAGJ;EACI;;AAEA;EACI;;AAKZ;EACI;;AAEA;EACI;;AAEA;EACI;;AAOZ;EACI;EACA;EACA;EACA;EACA;EACA;;AAEA;EAEI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGJ;EACI;EACA;;AAGJ;EACI;EACA;;AAGJ;EACI;;AAEA;EACI;;AAKZ;EACI;;AAEA;EACI;;AAGJ;EACI;;AAGJ;EACI;;AAMR;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;;AAIR;EACI;;AAEA;EACI;EACA;;AAMR;EACI;EACA;EACA;EACA;;AAEA;EAEI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;;AAGJ;EACI;EACA;;AAGJ;EACI;;AAKJ;EACI;;AAGJ;EACI;EACA;EACA;;AAGJ;EACI;;AAMZ;AAAA;EAEI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;;AAGJ;EACI;;AAGJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGJ;EACI;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAIJ;EACI;IACI;IACA;;;AAIR;EACI;IACI;IACA;;;AAIR;EACI;IACI;IACA;;;AAIR;EACI;IACI;IACA;IACA;IACA;;;AAIR;EACI;IACI;;EAGJ;IACI;;;AAIR;EACI;IACI;;EAGJ;IACI;;;AAIR;EACI;IACI;;EAGJ;IACI;;;AAIR;EACI;IACI;;EAGJ;IACI;;;AAIR;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAIJ;EACI;IACI;;EAGJ;IACI;;;AAIR;EACI;IACI;;EAGJ;IACI;;;AAIR;EACI;IACI;;EAGJ;IACI;;;AAIR;EACI;IACI;;EAGJ;IACI;;;AAKR;EACI;EACA;;AAIJ;EACI;EACA;EACA;;AAIJ;EAEI;;AAIA;EACI;;AAKR;EACI;IACI;IACA;;EAEJ;IACI;;EAGJ;IACI;;EACA;IACI;;EAIR;IACI;;EAGJ;AAAA;IAEI;;;AAMR;EACI;IACI","file":"a2-optimized.css"}
assets/css/admin/animate.min.css ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ @charset "UTF-8";/*!
2
+ * animate.css - https://animate.style/
3
+ * Version - 4.1.1
4
+ * Licensed under the MIT license - http://opensource.org/licenses/MIT
5
+ *
6
+ * Copyright (c) 2020 Animate.css
7
+ */:root{--animate-duration:1s;--animate-delay:1s;--animate-repeat:1}.animate__animated{-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-duration:var(--animate-duration);animation-duration:var(--animate-duration);-webkit-animation-fill-mode:both;animation-fill-mode:both}.animate__animated.animate__infinite{-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.animate__animated.animate__repeat-1{-webkit-animation-iteration-count:1;animation-iteration-count:1;-webkit-animation-iteration-count:var(--animate-repeat);animation-iteration-count:var(--animate-repeat)}.animate__animated.animate__repeat-2{-webkit-animation-iteration-count:2;animation-iteration-count:2;-webkit-animation-iteration-count:calc(var(--animate-repeat)*2);animation-iteration-count:calc(var(--animate-repeat)*2)}.animate__animated.animate__repeat-3{-webkit-animation-iteration-count:3;animation-iteration-count:3;-webkit-animation-iteration-count:calc(var(--animate-repeat)*3);animation-iteration-count:calc(var(--animate-repeat)*3)}.animate__animated.animate__delay-1s{-webkit-animation-delay:1s;animation-delay:1s;-webkit-animation-delay:var(--animate-delay);animation-delay:var(--animate-delay)}.animate__animated.animate__delay-2s{-webkit-animation-delay:2s;animation-delay:2s;-webkit-animation-delay:calc(var(--animate-delay)*2);animation-delay:calc(var(--animate-delay)*2)}.animate__animated.animate__delay-3s{-webkit-animation-delay:3s;animation-delay:3s;-webkit-animation-delay:calc(var(--animate-delay)*3);animation-delay:calc(var(--animate-delay)*3)}.animate__animated.animate__delay-4s{-webkit-animation-delay:4s;animation-delay:4s;-webkit-animation-delay:calc(var(--animate-delay)*4);animation-delay:calc(var(--animate-delay)*4)}.animate__animated.animate__delay-5s{-webkit-animation-delay:5s;animation-delay:5s;-webkit-animation-delay:calc(var(--animate-delay)*5);animation-delay:calc(var(--animate-delay)*5)}.animate__animated.animate__faster{-webkit-animation-duration:.5s;animation-duration:.5s;-webkit-animation-duration:calc(var(--animate-duration)/2);animation-duration:calc(var(--animate-duration)/2)}.animate__animated.animate__fast{-webkit-animation-duration:.8s;animation-duration:.8s;-webkit-animation-duration:calc(var(--animate-duration)*0.8);animation-duration:calc(var(--animate-duration)*0.8)}.animate__animated.animate__slow{-webkit-animation-duration:2s;animation-duration:2s;-webkit-animation-duration:calc(var(--animate-duration)*2);animation-duration:calc(var(--animate-duration)*2)}.animate__animated.animate__slower{-webkit-animation-duration:3s;animation-duration:3s;-webkit-animation-duration:calc(var(--animate-duration)*3);animation-duration:calc(var(--animate-duration)*3)}@media (prefers-reduced-motion:reduce),print{.animate__animated{-webkit-animation-duration:1ms!important;animation-duration:1ms!important;-webkit-transition-duration:1ms!important;transition-duration:1ms!important;-webkit-animation-iteration-count:1!important;animation-iteration-count:1!important}.animate__animated[class*=Out]{opacity:0}}@-webkit-keyframes bounce{0%,20%,53%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1);-webkit-transform:translateZ(0);transform:translateZ(0)}40%,43%{-webkit-animation-timing-function:cubic-bezier(.755,.05,.855,.06);animation-timing-function:cubic-bezier(.755,.05,.855,.06);-webkit-transform:translate3d(0,-30px,0) scaleY(1.1);transform:translate3d(0,-30px,0) scaleY(1.1)}70%{-webkit-animation-timing-function:cubic-bezier(.755,.05,.855,.06);animation-timing-function:cubic-bezier(.755,.05,.855,.06);-webkit-transform:translate3d(0,-15px,0) scaleY(1.05);transform:translate3d(0,-15px,0) scaleY(1.05)}80%{-webkit-transition-timing-function:cubic-bezier(.215,.61,.355,1);transition-timing-function:cubic-bezier(.215,.61,.355,1);-webkit-transform:translateZ(0) scaleY(.95);transform:translateZ(0) scaleY(.95)}90%{-webkit-transform:translate3d(0,-4px,0) scaleY(1.02);transform:translate3d(0,-4px,0) scaleY(1.02)}}@keyframes bounce{0%,20%,53%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1);-webkit-transform:translateZ(0);transform:translateZ(0)}40%,43%{-webkit-animation-timing-function:cubic-bezier(.755,.05,.855,.06);animation-timing-function:cubic-bezier(.755,.05,.855,.06);-webkit-transform:translate3d(0,-30px,0) scaleY(1.1);transform:translate3d(0,-30px,0) scaleY(1.1)}70%{-webkit-animation-timing-function:cubic-bezier(.755,.05,.855,.06);animation-timing-function:cubic-bezier(.755,.05,.855,.06);-webkit-transform:translate3d(0,-15px,0) scaleY(1.05);transform:translate3d(0,-15px,0) scaleY(1.05)}80%{-webkit-transition-timing-function:cubic-bezier(.215,.61,.355,1);transition-timing-function:cubic-bezier(.215,.61,.355,1);-webkit-transform:translateZ(0) scaleY(.95);transform:translateZ(0) scaleY(.95)}90%{-webkit-transform:translate3d(0,-4px,0) scaleY(1.02);transform:translate3d(0,-4px,0) scaleY(1.02)}}.animate__bounce{-webkit-animation-name:bounce;animation-name:bounce;-webkit-transform-origin:center bottom;transform-origin:center bottom}@-webkit-keyframes flash{0%,50%,to{opacity:1}25%,75%{opacity:0}}@keyframes flash{0%,50%,to{opacity:1}25%,75%{opacity:0}}.animate__flash{-webkit-animation-name:flash;animation-name:flash}@-webkit-keyframes pulse{0%{-webkit-transform:scaleX(1);transform:scaleX(1)}50%{-webkit-transform:scale3d(1.05,1.05,1.05);transform:scale3d(1.05,1.05,1.05)}to{-webkit-transform:scaleX(1);transform:scaleX(1)}}@keyframes pulse{0%{-webkit-transform:scaleX(1);transform:scaleX(1)}50%{-webkit-transform:scale3d(1.05,1.05,1.05);transform:scale3d(1.05,1.05,1.05)}to{-webkit-transform:scaleX(1);transform:scaleX(1)}}.animate__pulse{-webkit-animation-name:pulse;animation-name:pulse;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}@-webkit-keyframes rubberBand{0%{-webkit-transform:scaleX(1);transform:scaleX(1)}30%{-webkit-transform:scale3d(1.25,.75,1);transform:scale3d(1.25,.75,1)}40%{-webkit-transform:scale3d(.75,1.25,1);transform:scale3d(.75,1.25,1)}50%{-webkit-transform:scale3d(1.15,.85,1);transform:scale3d(1.15,.85,1)}65%{-webkit-transform:scale3d(.95,1.05,1);transform:scale3d(.95,1.05,1)}75%{-webkit-transform:scale3d(1.05,.95,1);transform:scale3d(1.05,.95,1)}to{-webkit-transform:scaleX(1);transform:scaleX(1)}}@keyframes rubberBand{0%{-webkit-transform:scaleX(1);transform:scaleX(1)}30%{-webkit-transform:scale3d(1.25,.75,1);transform:scale3d(1.25,.75,1)}40%{-webkit-transform:scale3d(.75,1.25,1);transform:scale3d(.75,1.25,1)}50%{-webkit-transform:scale3d(1.15,.85,1);transform:scale3d(1.15,.85,1)}65%{-webkit-transform:scale3d(.95,1.05,1);transform:scale3d(.95,1.05,1)}75%{-webkit-transform:scale3d(1.05,.95,1);transform:scale3d(1.05,.95,1)}to{-webkit-transform:scaleX(1);transform:scaleX(1)}}.animate__rubberBand{-webkit-animation-name:rubberBand;animation-name:rubberBand}@-webkit-keyframes shakeX{0%,to{-webkit-transform:translateZ(0);transform:translateZ(0)}10%,30%,50%,70%,90%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}20%,40%,60%,80%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}}@keyframes shakeX{0%,to{-webkit-transform:translateZ(0);transform:translateZ(0)}10%,30%,50%,70%,90%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}20%,40%,60%,80%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}}.animate__shakeX{-webkit-animation-name:shakeX;animation-name:shakeX}@-webkit-keyframes shakeY{0%,to{-webkit-transform:translateZ(0);transform:translateZ(0)}10%,30%,50%,70%,90%{-webkit-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}20%,40%,60%,80%{-webkit-transform:translate3d(0,10px,0);transform:translate3d(0,10px,0)}}@keyframes shakeY{0%,to{-webkit-transform:translateZ(0);transform:translateZ(0)}10%,30%,50%,70%,90%{-webkit-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}20%,40%,60%,80%{-webkit-transform:translate3d(0,10px,0);transform:translate3d(0,10px,0)}}.animate__shakeY{-webkit-animation-name:shakeY;animation-name:shakeY}@-webkit-keyframes headShake{0%{-webkit-transform:translateX(0);transform:translateX(0)}6.5%{-webkit-transform:translateX(-6px) rotateY(-9deg);transform:translateX(-6px) rotateY(-9deg)}18.5%{-webkit-transform:translateX(5px) rotateY(7deg);transform:translateX(5px) rotateY(7deg)}31.5%{-webkit-transform:translateX(-3px) rotateY(-5deg);transform:translateX(-3px) rotateY(-5deg)}43.5%{-webkit-transform:translateX(2px) rotateY(3deg);transform:translateX(2px) rotateY(3deg)}50%{-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes headShake{0%{-webkit-transform:translateX(0);transform:translateX(0)}6.5%{-webkit-transform:translateX(-6px) rotateY(-9deg);transform:translateX(-6px) rotateY(-9deg)}18.5%{-webkit-transform:translateX(5px) rotateY(7deg);transform:translateX(5px) rotateY(7deg)}31.5%{-webkit-transform:translateX(-3px) rotateY(-5deg);transform:translateX(-3px) rotateY(-5deg)}43.5%{-webkit-transform:translateX(2px) rotateY(3deg);transform:translateX(2px) rotateY(3deg)}50%{-webkit-transform:translateX(0);transform:translateX(0)}}.animate__headShake{-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-name:headShake;animation-name:headShake}@-webkit-keyframes swing{20%{-webkit-transform:rotate(15deg);transform:rotate(15deg)}40%{-webkit-transform:rotate(-10deg);transform:rotate(-10deg)}60%{-webkit-transform:rotate(5deg);transform:rotate(5deg)}80%{-webkit-transform:rotate(-5deg);transform:rotate(-5deg)}to{-webkit-transform:rotate(0deg);transform:rotate(0deg)}}@keyframes swing{20%{-webkit-transform:rotate(15deg);transform:rotate(15deg)}40%{-webkit-transform:rotate(-10deg);transform:rotate(-10deg)}60%{-webkit-transform:rotate(5deg);transform:rotate(5deg)}80%{-webkit-transform:rotate(-5deg);transform:rotate(-5deg)}to{-webkit-transform:rotate(0deg);transform:rotate(0deg)}}.animate__swing{-webkit-transform-origin:top center;transform-origin:top center;-webkit-animation-name:swing;animation-name:swing}@-webkit-keyframes tada{0%{-webkit-transform:scaleX(1);transform:scaleX(1)}10%,20%{-webkit-transform:scale3d(.9,.9,.9) rotate(-3deg);transform:scale3d(.9,.9,.9) rotate(-3deg)}30%,50%,70%,90%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate(3deg);transform:scale3d(1.1,1.1,1.1) rotate(3deg)}40%,60%,80%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate(-3deg);transform:scale3d(1.1,1.1,1.1) rotate(-3deg)}to{-webkit-transform:scaleX(1);transform:scaleX(1)}}@keyframes tada{0%{-webkit-transform:scaleX(1);transform:scaleX(1)}10%,20%{-webkit-transform:scale3d(.9,.9,.9) rotate(-3deg);transform:scale3d(.9,.9,.9) rotate(-3deg)}30%,50%,70%,90%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate(3deg);transform:scale3d(1.1,1.1,1.1) rotate(3deg)}40%,60%,80%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate(-3deg);transform:scale3d(1.1,1.1,1.1) rotate(-3deg)}to{-webkit-transform:scaleX(1);transform:scaleX(1)}}.animate__tada{-webkit-animation-name:tada;animation-name:tada}@-webkit-keyframes wobble{0%{-webkit-transform:translateZ(0);transform:translateZ(0)}15%{-webkit-transform:translate3d(-25%,0,0) rotate(-5deg);transform:translate3d(-25%,0,0) rotate(-5deg)}30%{-webkit-transform:translate3d(20%,0,0) rotate(3deg);transform:translate3d(20%,0,0) rotate(3deg)}45%{-webkit-transform:translate3d(-15%,0,0) rotate(-3deg);transform:translate3d(-15%,0,0) rotate(-3deg)}60%{-webkit-transform:translate3d(10%,0,0) rotate(2deg);transform:translate3d(10%,0,0) rotate(2deg)}75%{-webkit-transform:translate3d(-5%,0,0) rotate(-1deg);transform:translate3d(-5%,0,0) rotate(-1deg)}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes wobble{0%{-webkit-transform:translateZ(0);transform:translateZ(0)}15%{-webkit-transform:translate3d(-25%,0,0) rotate(-5deg);transform:translate3d(-25%,0,0) rotate(-5deg)}30%{-webkit-transform:translate3d(20%,0,0) rotate(3deg);transform:translate3d(20%,0,0) rotate(3deg)}45%{-webkit-transform:translate3d(-15%,0,0) rotate(-3deg);transform:translate3d(-15%,0,0) rotate(-3deg)}60%{-webkit-transform:translate3d(10%,0,0) rotate(2deg);transform:translate3d(10%,0,0) rotate(2deg)}75%{-webkit-transform:translate3d(-5%,0,0) rotate(-1deg);transform:translate3d(-5%,0,0) rotate(-1deg)}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}.animate__wobble{-webkit-animation-name:wobble;animation-name:wobble}@-webkit-keyframes jello{0%,11.1%,to{-webkit-transform:translateZ(0);transform:translateZ(0)}22.2%{-webkit-transform:skewX(-12.5deg) skewY(-12.5deg);transform:skewX(-12.5deg) skewY(-12.5deg)}33.3%{-webkit-transform:skewX(6.25deg) skewY(6.25deg);transform:skewX(6.25deg) skewY(6.25deg)}44.4%{-webkit-transform:skewX(-3.125deg) skewY(-3.125deg);transform:skewX(-3.125deg) skewY(-3.125deg)}55.5%{-webkit-transform:skewX(1.5625deg) skewY(1.5625deg);transform:skewX(1.5625deg) skewY(1.5625deg)}66.6%{-webkit-transform:skewX(-.78125deg) skewY(-.78125deg);transform:skewX(-.78125deg) skewY(-.78125deg)}77.7%{-webkit-transform:skewX(.390625deg) skewY(.390625deg);transform:skewX(.390625deg) skewY(.390625deg)}88.8%{-webkit-transform:skewX(-.1953125deg) skewY(-.1953125deg);transform:skewX(-.1953125deg) skewY(-.1953125deg)}}@keyframes jello{0%,11.1%,to{-webkit-transform:translateZ(0);transform:translateZ(0)}22.2%{-webkit-transform:skewX(-12.5deg) skewY(-12.5deg);transform:skewX(-12.5deg) skewY(-12.5deg)}33.3%{-webkit-transform:skewX(6.25deg) skewY(6.25deg);transform:skewX(6.25deg) skewY(6.25deg)}44.4%{-webkit-transform:skewX(-3.125deg) skewY(-3.125deg);transform:skewX(-3.125deg) skewY(-3.125deg)}55.5%{-webkit-transform:skewX(1.5625deg) skewY(1.5625deg);transform:skewX(1.5625deg) skewY(1.5625deg)}66.6%{-webkit-transform:skewX(-.78125deg) skewY(-.78125deg);transform:skewX(-.78125deg) skewY(-.78125deg)}77.7%{-webkit-transform:skewX(.390625deg) skewY(.390625deg);transform:skewX(.390625deg) skewY(.390625deg)}88.8%{-webkit-transform:skewX(-.1953125deg) skewY(-.1953125deg);transform:skewX(-.1953125deg) skewY(-.1953125deg)}}.animate__jello{-webkit-animation-name:jello;animation-name:jello;-webkit-transform-origin:center;transform-origin:center}@-webkit-keyframes heartBeat{0%{-webkit-transform:scale(1);transform:scale(1)}14%{-webkit-transform:scale(1.3);transform:scale(1.3)}28%{-webkit-transform:scale(1);transform:scale(1)}42%{-webkit-transform:scale(1.3);transform:scale(1.3)}70%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes heartBeat{0%{-webkit-transform:scale(1);transform:scale(1)}14%{-webkit-transform:scale(1.3);transform:scale(1.3)}28%{-webkit-transform:scale(1);transform:scale(1)}42%{-webkit-transform:scale(1.3);transform:scale(1.3)}70%{-webkit-transform:scale(1);transform:scale(1)}}.animate__heartBeat{-webkit-animation-name:heartBeat;animation-name:heartBeat;-webkit-animation-duration:1.3s;animation-duration:1.3s;-webkit-animation-duration:calc(var(--animate-duration)*1.3);animation-duration:calc(var(--animate-duration)*1.3);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}@-webkit-keyframes backInDown{0%{-webkit-transform:translateY(-1200px) scale(.7);transform:translateY(-1200px) scale(.7);opacity:.7}80%{-webkit-transform:translateY(0) scale(.7);transform:translateY(0) scale(.7);opacity:.7}to{-webkit-transform:scale(1);transform:scale(1);opacity:1}}@keyframes backInDown{0%{-webkit-transform:translateY(-1200px) scale(.7);transform:translateY(-1200px) scale(.7);opacity:.7}80%{-webkit-transform:translateY(0) scale(.7);transform:translateY(0) scale(.7);opacity:.7}to{-webkit-transform:scale(1);transform:scale(1);opacity:1}}.animate__backInDown{-webkit-animation-name:backInDown;animation-name:backInDown}@-webkit-keyframes backInLeft{0%{-webkit-transform:translateX(-2000px) scale(.7);transform:translateX(-2000px) scale(.7);opacity:.7}80%{-webkit-transform:translateX(0) scale(.7);transform:translateX(0) scale(.7);opacity:.7}to{-webkit-transform:scale(1);transform:scale(1);opacity:1}}@keyframes backInLeft{0%{-webkit-transform:translateX(-2000px) scale(.7);transform:translateX(-2000px) scale(.7);opacity:.7}80%{-webkit-transform:translateX(0) scale(.7);transform:translateX(0) scale(.7);opacity:.7}to{-webkit-transform:scale(1);transform:scale(1);opacity:1}}.animate__backInLeft{-webkit-animation-name:backInLeft;animation-name:backInLeft}@-webkit-keyframes backInRight{0%{-webkit-transform:translateX(2000px) scale(.7);transform:translateX(2000px) scale(.7);opacity:.7}80%{-webkit-transform:translateX(0) scale(.7);transform:translateX(0) scale(.7);opacity:.7}to{-webkit-transform:scale(1);transform:scale(1);opacity:1}}@keyframes backInRight{0%{-webkit-transform:translateX(2000px) scale(.7);transform:translateX(2000px) scale(.7);opacity:.7}80%{-webkit-transform:translateX(0) scale(.7);transform:translateX(0) scale(.7);opacity:.7}to{-webkit-transform:scale(1);transform:scale(1);opacity:1}}.animate__backInRight{-webkit-animation-name:backInRight;animation-name:backInRight}@-webkit-keyframes backInUp{0%{-webkit-transform:translateY(1200px) scale(.7);transform:translateY(1200px) scale(.7);opacity:.7}80%{-webkit-transform:translateY(0) scale(.7);transform:translateY(0) scale(.7);opacity:.7}to{-webkit-transform:scale(1);transform:scale(1);opacity:1}}@keyframes backInUp{0%{-webkit-transform:translateY(1200px) scale(.7);transform:translateY(1200px) scale(.7);opacity:.7}80%{-webkit-transform:translateY(0) scale(.7);transform:translateY(0) scale(.7);opacity:.7}to{-webkit-transform:scale(1);transform:scale(1);opacity:1}}.animate__backInUp{-webkit-animation-name:backInUp;animation-name:backInUp}@-webkit-keyframes backOutDown{0%{-webkit-transform:scale(1);transform:scale(1);opacity:1}20%{-webkit-transform:translateY(0) scale(.7);transform:translateY(0) scale(.7);opacity:.7}to{-webkit-transform:translateY(700px) scale(.7);transform:translateY(700px) scale(.7);opacity:.7}}@keyframes backOutDown{0%{-webkit-transform:scale(1);transform:scale(1);opacity:1}20%{-webkit-transform:translateY(0) scale(.7);transform:translateY(0) scale(.7);opacity:.7}to{-webkit-transform:translateY(700px) scale(.7);transform:translateY(700px) scale(.7);opacity:.7}}.animate__backOutDown{-webkit-animation-name:backOutDown;animation-name:backOutDown}@-webkit-keyframes backOutLeft{0%{-webkit-transform:scale(1);transform:scale(1);opacity:1}20%{-webkit-transform:translateX(0) scale(.7);transform:translateX(0) scale(.7);opacity:.7}to{-webkit-transform:translateX(-2000px) scale(.7);transform:translateX(-2000px) scale(.7);opacity:.7}}@keyframes backOutLeft{0%{-webkit-transform:scale(1);transform:scale(1);opacity:1}20%{-webkit-transform:translateX(0) scale(.7);transform:translateX(0) scale(.7);opacity:.7}to{-webkit-transform:translateX(-2000px) scale(.7);transform:translateX(-2000px) scale(.7);opacity:.7}}.animate__backOutLeft{-webkit-animation-name:backOutLeft;animation-name:backOutLeft}@-webkit-keyframes backOutRight{0%{-webkit-transform:scale(1);transform:scale(1);opacity:1}20%{-webkit-transform:translateX(0) scale(.7);transform:translateX(0) scale(.7);opacity:.7}to{-webkit-transform:translateX(2000px) scale(.7);transform:translateX(2000px) scale(.7);opacity:.7}}@keyframes backOutRight{0%{-webkit-transform:scale(1);transform:scale(1);opacity:1}20%{-webkit-transform:translateX(0) scale(.7);transform:translateX(0) scale(.7);opacity:.7}to{-webkit-transform:translateX(2000px) scale(.7);transform:translateX(2000px) scale(.7);opacity:.7}}.animate__backOutRight{-webkit-animation-name:backOutRight;animation-name:backOutRight}@-webkit-keyframes backOutUp{0%{-webkit-transform:scale(1);transform:scale(1);opacity:1}20%{-webkit-transform:translateY(0) scale(.7);transform:translateY(0) scale(.7);opacity:.7}to{-webkit-transform:translateY(-700px) scale(.7);transform:translateY(-700px) scale(.7);opacity:.7}}@keyframes backOutUp{0%{-webkit-transform:scale(1);transform:scale(1);opacity:1}20%{-webkit-transform:translateY(0) scale(.7);transform:translateY(0) scale(.7);opacity:.7}to{-webkit-transform:translateY(-700px) scale(.7);transform:translateY(-700px) scale(.7);opacity:.7}}.animate__backOutUp{-webkit-animation-name:backOutUp;animation-name:backOutUp}@-webkit-keyframes bounceIn{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}20%{-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}40%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}60%{opacity:1;-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}80%{-webkit-transform:scale3d(.97,.97,.97);transform:scale3d(.97,.97,.97)}to{opacity:1;-webkit-transform:scaleX(1);transform:scaleX(1)}}@keyframes bounceIn{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}20%{-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}40%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}60%{opacity:1;-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}80%{-webkit-transform:scale3d(.97,.97,.97);transform:scale3d(.97,.97,.97)}to{opacity:1;-webkit-transform:scaleX(1);transform:scaleX(1)}}.animate__bounceIn{-webkit-animation-duration:.75s;animation-duration:.75s;-webkit-animation-duration:calc(var(--animate-duration)*0.75);animation-duration:calc(var(--animate-duration)*0.75);-webkit-animation-name:bounceIn;animation-name:bounceIn}@-webkit-keyframes bounceInDown{0%,60%,75%,90%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(0,-3000px,0) scaleY(3);transform:translate3d(0,-3000px,0) scaleY(3)}60%{opacity:1;-webkit-transform:translate3d(0,25px,0) scaleY(.9);transform:translate3d(0,25px,0) scaleY(.9)}75%{-webkit-transform:translate3d(0,-10px,0) scaleY(.95);transform:translate3d(0,-10px,0) scaleY(.95)}90%{-webkit-transform:translate3d(0,5px,0) scaleY(.985);transform:translate3d(0,5px,0) scaleY(.985)}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes bounceInDown{0%,60%,75%,90%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(0,-3000px,0) scaleY(3);transform:translate3d(0,-3000px,0) scaleY(3)}60%{opacity:1;-webkit-transform:translate3d(0,25px,0) scaleY(.9);transform:translate3d(0,25px,0) scaleY(.9)}75%{-webkit-transform:translate3d(0,-10px,0) scaleY(.95);transform:translate3d(0,-10px,0) scaleY(.95)}90%{-webkit-transform:translate3d(0,5px,0) scaleY(.985);transform:translate3d(0,5px,0) scaleY(.985)}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}.animate__bounceInDown{-webkit-animation-name:bounceInDown;animation-name:bounceInDown}@-webkit-keyframes bounceInLeft{0%,60%,75%,90%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(-3000px,0,0) scaleX(3);transform:translate3d(-3000px,0,0) scaleX(3)}60%{opacity:1;-webkit-transform:translate3d(25px,0,0) scaleX(1);transform:translate3d(25px,0,0) scaleX(1)}75%{-webkit-transform:translate3d(-10px,0,0) scaleX(.98);transform:translate3d(-10px,0,0) scaleX(.98)}90%{-webkit-transform:translate3d(5px,0,0) scaleX(.995);transform:translate3d(5px,0,0) scaleX(.995)}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes bounceInLeft{0%,60%,75%,90%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(-3000px,0,0) scaleX(3);transform:translate3d(-3000px,0,0) scaleX(3)}60%{opacity:1;-webkit-transform:translate3d(25px,0,0) scaleX(1);transform:translate3d(25px,0,0) scaleX(1)}75%{-webkit-transform:translate3d(-10px,0,0) scaleX(.98);transform:translate3d(-10px,0,0) scaleX(.98)}90%{-webkit-transform:translate3d(5px,0,0) scaleX(.995);transform:translate3d(5px,0,0) scaleX(.995)}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}.animate__bounceInLeft{-webkit-animation-name:bounceInLeft;animation-name:bounceInLeft}@-webkit-keyframes bounceInRight{0%,60%,75%,90%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(3000px,0,0) scaleX(3);transform:translate3d(3000px,0,0) scaleX(3)}60%{opacity:1;-webkit-transform:translate3d(-25px,0,0) scaleX(1);transform:translate3d(-25px,0,0) scaleX(1)}75%{-webkit-transform:translate3d(10px,0,0) scaleX(.98);transform:translate3d(10px,0,0) scaleX(.98)}90%{-webkit-transform:translate3d(-5px,0,0) scaleX(.995);transform:translate3d(-5px,0,0) scaleX(.995)}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes bounceInRight{0%,60%,75%,90%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(3000px,0,0) scaleX(3);transform:translate3d(3000px,0,0) scaleX(3)}60%{opacity:1;-webkit-transform:translate3d(-25px,0,0) scaleX(1);transform:translate3d(-25px,0,0) scaleX(1)}75%{-webkit-transform:translate3d(10px,0,0) scaleX(.98);transform:translate3d(10px,0,0) scaleX(.98)}90%{-webkit-transform:translate3d(-5px,0,0) scaleX(.995);transform:translate3d(-5px,0,0) scaleX(.995)}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}.animate__bounceInRight{-webkit-animation-name:bounceInRight;animation-name:bounceInRight}@-webkit-keyframes bounceInUp{0%,60%,75%,90%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(0,3000px,0) scaleY(5);transform:translate3d(0,3000px,0) scaleY(5)}60%{opacity:1;-webkit-transform:translate3d(0,-20px,0) scaleY(.9);transform:translate3d(0,-20px,0) scaleY(.9)}75%{-webkit-transform:translate3d(0,10px,0) scaleY(.95);transform:translate3d(0,10px,0) scaleY(.95)}90%{-webkit-transform:translate3d(0,-5px,0) scaleY(.985);transform:translate3d(0,-5px,0) scaleY(.985)}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes bounceInUp{0%,60%,75%,90%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(0,3000px,0) scaleY(5);transform:translate3d(0,3000px,0) scaleY(5)}60%{opacity:1;-webkit-transform:translate3d(0,-20px,0) scaleY(.9);transform:translate3d(0,-20px,0) scaleY(.9)}75%{-webkit-transform:translate3d(0,10px,0) scaleY(.95);transform:translate3d(0,10px,0) scaleY(.95)}90%{-webkit-transform:translate3d(0,-5px,0) scaleY(.985);transform:translate3d(0,-5px,0) scaleY(.985)}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}.animate__bounceInUp{-webkit-animation-name:bounceInUp;animation-name:bounceInUp}@-webkit-keyframes bounceOut{20%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}50%,55%{opacity:1;-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}to{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}}@keyframes bounceOut{20%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}50%,55%{opacity:1;-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}to{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}}.animate__bounceOut{-webkit-animation-duration:.75s;animation-duration:.75s;-webkit-animation-duration:calc(var(--animate-duration)*0.75);animation-duration:calc(var(--animate-duration)*0.75);-webkit-animation-name:bounceOut;animation-name:bounceOut}@-webkit-keyframes bounceOutDown{20%{-webkit-transform:translate3d(0,10px,0) scaleY(.985);transform:translate3d(0,10px,0) scaleY(.985)}40%,45%{opacity:1;-webkit-transform:translate3d(0,-20px,0) scaleY(.9);transform:translate3d(0,-20px,0) scaleY(.9)}to{opacity:0;-webkit-transform:translate3d(0,2000px,0) scaleY(3);transform:translate3d(0,2000px,0) scaleY(3)}}@keyframes bounceOutDown{20%{-webkit-transform:translate3d(0,10px,0) scaleY(.985);transform:translate3d(0,10px,0) scaleY(.985)}40%,45%{opacity:1;-webkit-transform:translate3d(0,-20px,0) scaleY(.9);transform:translate3d(0,-20px,0) scaleY(.9)}to{opacity:0;-webkit-transform:translate3d(0,2000px,0) scaleY(3);transform:translate3d(0,2000px,0) scaleY(3)}}.animate__bounceOutDown{-webkit-animation-name:bounceOutDown;animation-name:bounceOutDown}@-webkit-keyframes bounceOutLeft{20%{opacity:1;-webkit-transform:translate3d(20px,0,0) scaleX(.9);transform:translate3d(20px,0,0) scaleX(.9)}to{opacity:0;-webkit-transform:translate3d(-2000px,0,0) scaleX(2);transform:translate3d(-2000px,0,0) scaleX(2)}}@keyframes bounceOutLeft{20%{opacity:1;-webkit-transform:translate3d(20px,0,0) scaleX(.9);transform:translate3d(20px,0,0) scaleX(.9)}to{opacity:0;-webkit-transform:translate3d(-2000px,0,0) scaleX(2);transform:translate3d(-2000px,0,0) scaleX(2)}}.animate__bounceOutLeft{-webkit-animation-name:bounceOutLeft;animation-name:bounceOutLeft}@-webkit-keyframes bounceOutRight{20%{opacity:1;-webkit-transform:translate3d(-20px,0,0) scaleX(.9);transform:translate3d(-20px,0,0) scaleX(.9)}to{opacity:0;-webkit-transform:translate3d(2000px,0,0) scaleX(2);transform:translate3d(2000px,0,0) scaleX(2)}}@keyframes bounceOutRight{20%{opacity:1;-webkit-transform:translate3d(-20px,0,0) scaleX(.9);transform:translate3d(-20px,0,0) scaleX(.9)}to{opacity:0;-webkit-transform:translate3d(2000px,0,0) scaleX(2);transform:translate3d(2000px,0,0) scaleX(2)}}.animate__bounceOutRight{-webkit-animation-name:bounceOutRight;animation-name:bounceOutRight}@-webkit-keyframes bounceOutUp{20%{-webkit-transform:translate3d(0,-10px,0) scaleY(.985);transform:translate3d(0,-10px,0) scaleY(.985)}40%,45%{opacity:1;-webkit-transform:translate3d(0,20px,0) scaleY(.9);transform:translate3d(0,20px,0) scaleY(.9)}to{opacity:0;-webkit-transform:translate3d(0,-2000px,0) scaleY(3);transform:translate3d(0,-2000px,0) scaleY(3)}}@keyframes bounceOutUp{20%{-webkit-transform:translate3d(0,-10px,0) scaleY(.985);transform:translate3d(0,-10px,0) scaleY(.985)}40%,45%{opacity:1;-webkit-transform:translate3d(0,20px,0) scaleY(.9);transform:translate3d(0,20px,0) scaleY(.9)}to{opacity:0;-webkit-transform:translate3d(0,-2000px,0) scaleY(3);transform:translate3d(0,-2000px,0) scaleY(3)}}.animate__bounceOutUp{-webkit-animation-name:bounceOutUp;animation-name:bounceOutUp}@-webkit-keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.animate__fadeIn{-webkit-animation-name:fadeIn;animation-name:fadeIn}@-webkit-keyframes fadeInDown{0%{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}to{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes fadeInDown{0%{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}to{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}}.animate__fadeInDown{-webkit-animation-name:fadeInDown;animation-name:fadeInDown}@-webkit-keyframes fadeInDownBig{0%{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}to{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes fadeInDownBig{0%{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}to{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}}.animate__fadeInDownBig{-webkit-animation-name:fadeInDownBig;animation-name:fadeInDownBig}@-webkit-keyframes fadeInLeft{0%{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}to{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes fadeInLeft{0%{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}to{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}}.animate__fadeInLeft{-webkit-animation-name:fadeInLeft;animation-name:fadeInLeft}@-webkit-keyframes fadeInLeftBig{0%{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}to{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes fadeInLeftBig{0%{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}to{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}}.animate__fadeInLeftBig{-webkit-animation-name:fadeInLeftBig;animation-name:fadeInLeftBig}@-webkit-keyframes fadeInRight{0%{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}to{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes fadeInRight{0%{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}to{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}}.animate__fadeInRight{-webkit-animation-name:fadeInRight;animation-name:fadeInRight}@-webkit-keyframes fadeInRightBig{0%{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}to{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes fadeInRightBig{0%{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}to{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}}.animate__fadeInRightBig{-webkit-animation-name:fadeInRightBig;animation-name:fadeInRightBig}@-webkit-keyframes fadeInUp{0%{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}to{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes fadeInUp{0%{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}to{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}}.animate__fadeInUp{-webkit-animation-name:fadeInUp;animation-name:fadeInUp}@-webkit-keyframes fadeInUpBig{0%{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}to{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes fadeInUpBig{0%{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}to{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}}.animate__fadeInUpBig{-webkit-animation-name:fadeInUpBig;animation-name:fadeInUpBig}@-webkit-keyframes fadeInTopLeft{0%{opacity:0;-webkit-transform:translate3d(-100%,-100%,0);transform:translate3d(-100%,-100%,0)}to{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes fadeInTopLeft{0%{opacity:0;-webkit-transform:translate3d(-100%,-100%,0);transform:translate3d(-100%,-100%,0)}to{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}}.animate__fadeInTopLeft{-webkit-animation-name:fadeInTopLeft;animation-name:fadeInTopLeft}@-webkit-keyframes fadeInTopRight{0%{opacity:0;-webkit-transform:translate3d(100%,-100%,0);transform:translate3d(100%,-100%,0)}to{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes fadeInTopRight{0%{opacity:0;-webkit-transform:translate3d(100%,-100%,0);transform:translate3d(100%,-100%,0)}to{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}}.animate__fadeInTopRight{-webkit-animation-name:fadeInTopRight;animation-name:fadeInTopRight}@-webkit-keyframes fadeInBottomLeft{0%{opacity:0;-webkit-transform:translate3d(-100%,100%,0);transform:translate3d(-100%,100%,0)}to{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes fadeInBottomLeft{0%{opacity:0;-webkit-transform:translate3d(-100%,100%,0);transform:translate3d(-100%,100%,0)}to{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}}.animate__fadeInBottomLeft{-webkit-animation-name:fadeInBottomLeft;animation-name:fadeInBottomLeft}@-webkit-keyframes fadeInBottomRight{0%{opacity:0;-webkit-transform:translate3d(100%,100%,0);transform:translate3d(100%,100%,0)}to{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes fadeInBottomRight{0%{opacity:0;-webkit-transform:translate3d(100%,100%,0);transform:translate3d(100%,100%,0)}to{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}}.animate__fadeInBottomRight{-webkit-animation-name:fadeInBottomRight;animation-name:fadeInBottomRight}@-webkit-keyframes fadeOut{0%{opacity:1}to{opacity:0}}@keyframes fadeOut{0%{opacity:1}to{opacity:0}}.animate__fadeOut{-webkit-animation-name:fadeOut;animation-name:fadeOut}@-webkit-keyframes fadeOutDown{0%{opacity:1}to{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}@keyframes fadeOutDown{0%{opacity:1}to{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}.animate__fadeOutDown{-webkit-animation-name:fadeOutDown;animation-name:fadeOutDown}@-webkit-keyframes fadeOutDownBig{0%{opacity:1}to{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}}@keyframes fadeOutDownBig{0%{opacity:1}to{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}}.animate__fadeOutDownBig{-webkit-animation-name:fadeOutDownBig;animation-name:fadeOutDownBig}@-webkit-keyframes fadeOutLeft{0%{opacity:1}to{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}@keyframes fadeOutLeft{0%{opacity:1}to{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}.animate__fadeOutLeft{-webkit-animation-name:fadeOutLeft;animation-name:fadeOutLeft}@-webkit-keyframes fadeOutLeftBig{0%{opacity:1}to{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}}@keyframes fadeOutLeftBig{0%{opacity:1}to{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}}.animate__fadeOutLeftBig{-webkit-animation-name:fadeOutLeftBig;animation-name:fadeOutLeftBig}@-webkit-keyframes fadeOutRight{0%{opacity:1}to{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}@keyframes fadeOutRight{0%{opacity:1}to{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}.animate__fadeOutRight{-webkit-animation-name:fadeOutRight;animation-name:fadeOutRight}@-webkit-keyframes fadeOutRightBig{0%{opacity:1}to{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}}@keyframes fadeOutRightBig{0%{opacity:1}to{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}}.animate__fadeOutRightBig{-webkit-animation-name:fadeOutRightBig;animation-name:fadeOutRightBig}@-webkit-keyframes fadeOutUp{0%{opacity:1}to{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}@keyframes fadeOutUp{0%{opacity:1}to{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}.animate__fadeOutUp{-webkit-animation-name:fadeOutUp;animation-name:fadeOutUp}@-webkit-keyframes fadeOutUpBig{0%{opacity:1}to{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}}@keyframes fadeOutUpBig{0%{opacity:1}to{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}}.animate__fadeOutUpBig{-webkit-animation-name:fadeOutUpBig;animation-name:fadeOutUpBig}@-webkit-keyframes fadeOutTopLeft{0%{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}to{opacity:0;-webkit-transform:translate3d(-100%,-100%,0);transform:translate3d(-100%,-100%,0)}}@keyframes fadeOutTopLeft{0%{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}to{opacity:0;-webkit-transform:translate3d(-100%,-100%,0);transform:translate3d(-100%,-100%,0)}}.animate__fadeOutTopLeft{-webkit-animation-name:fadeOutTopLeft;animation-name:fadeOutTopLeft}@-webkit-keyframes fadeOutTopRight{0%{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}to{opacity:0;-webkit-transform:translate3d(100%,-100%,0);transform:translate3d(100%,-100%,0)}}@keyframes fadeOutTopRight{0%{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}to{opacity:0;-webkit-transform:translate3d(100%,-100%,0);transform:translate3d(100%,-100%,0)}}.animate__fadeOutTopRight{-webkit-animation-name:fadeOutTopRight;animation-name:fadeOutTopRight}@-webkit-keyframes fadeOutBottomRight{0%{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}to{opacity:0;-webkit-transform:translate3d(100%,100%,0);transform:translate3d(100%,100%,0)}}@keyframes fadeOutBottomRight{0%{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}to{opacity:0;-webkit-transform:translate3d(100%,100%,0);transform:translate3d(100%,100%,0)}}.animate__fadeOutBottomRight{-webkit-animation-name:fadeOutBottomRight;animation-name:fadeOutBottomRight}@-webkit-keyframes fadeOutBottomLeft{0%{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}to{opacity:0;-webkit-transform:translate3d(-100%,100%,0);transform:translate3d(-100%,100%,0)}}@keyframes fadeOutBottomLeft{0%{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}to{opacity:0;-webkit-transform:translate3d(-100%,100%,0);transform:translate3d(-100%,100%,0)}}.animate__fadeOutBottomLeft{-webkit-animation-name:fadeOutBottomLeft;animation-name:fadeOutBottomLeft}@-webkit-keyframes flip{0%{-webkit-transform:perspective(400px) scaleX(1) translateZ(0) rotateY(-1turn);transform:perspective(400px) scaleX(1) translateZ(0) rotateY(-1turn);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}40%{-webkit-transform:perspective(400px) scaleX(1) translateZ(150px) rotateY(-190deg);transform:perspective(400px) scaleX(1) translateZ(150px) rotateY(-190deg);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}50%{-webkit-transform:perspective(400px) scaleX(1) translateZ(150px) rotateY(-170deg);transform:perspective(400px) scaleX(1) translateZ(150px) rotateY(-170deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}80%{-webkit-transform:perspective(400px) scale3d(.95,.95,.95) translateZ(0) rotateY(0deg);transform:perspective(400px) scale3d(.95,.95,.95) translateZ(0) rotateY(0deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}to{-webkit-transform:perspective(400px) scaleX(1) translateZ(0) rotateY(0deg);transform:perspective(400px) scaleX(1) translateZ(0) rotateY(0deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}}@keyframes flip{0%{-webkit-transform:perspective(400px) scaleX(1) translateZ(0) rotateY(-1turn);transform:perspective(400px) scaleX(1) translateZ(0) rotateY(-1turn);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}40%{-webkit-transform:perspective(400px) scaleX(1) translateZ(150px) rotateY(-190deg);transform:perspective(400px) scaleX(1) translateZ(150px) rotateY(-190deg);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}50%{-webkit-transform:perspective(400px) scaleX(1) translateZ(150px) rotateY(-170deg);transform:perspective(400px) scaleX(1) translateZ(150px) rotateY(-170deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}80%{-webkit-transform:perspective(400px) scale3d(.95,.95,.95) translateZ(0) rotateY(0deg);transform:perspective(400px) scale3d(.95,.95,.95) translateZ(0) rotateY(0deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}to{-webkit-transform:perspective(400px) scaleX(1) translateZ(0) rotateY(0deg);transform:perspective(400px) scaleX(1) translateZ(0) rotateY(0deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}}.animate__animated.animate__flip{-webkit-backface-visibility:visible;backface-visibility:visible;-webkit-animation-name:flip;animation-name:flip}@-webkit-keyframes flipInX{0%{-webkit-transform:perspective(400px) rotateX(90deg);transform:perspective(400px) rotateX(90deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotateX(-20deg);transform:perspective(400px) rotateX(-20deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotateX(10deg);transform:perspective(400px) rotateX(10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotateX(-5deg);transform:perspective(400px) rotateX(-5deg)}to{-webkit-transform:perspective(400px);transform:perspective(400px)}}@keyframes flipInX{0%{-webkit-transform:perspective(400px) rotateX(90deg);transform:perspective(400px) rotateX(90deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotateX(-20deg);transform:perspective(400px) rotateX(-20deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotateX(10deg);transform:perspective(400px) rotateX(10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotateX(-5deg);transform:perspective(400px) rotateX(-5deg)}to{-webkit-transform:perspective(400px);transform:perspective(400px)}}.animate__flipInX{-webkit-backface-visibility:visible!important;backface-visibility:visible!important;-webkit-animation-name:flipInX;animation-name:flipInX}@-webkit-keyframes flipInY{0%{-webkit-transform:perspective(400px) rotateY(90deg);transform:perspective(400px) rotateY(90deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotateY(-20deg);transform:perspective(400px) rotateY(-20deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotateY(10deg);transform:perspective(400px) rotateY(10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotateY(-5deg);transform:perspective(400px) rotateY(-5deg)}to{-webkit-transform:perspective(400px);transform:perspective(400px)}}@keyframes flipInY{0%{-webkit-transform:perspective(400px) rotateY(90deg);transform:perspective(400px) rotateY(90deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotateY(-20deg);transform:perspective(400px) rotateY(-20deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotateY(10deg);transform:perspective(400px) rotateY(10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotateY(-5deg);transform:perspective(400px) rotateY(-5deg)}to{-webkit-transform:perspective(400px);transform:perspective(400px)}}.animate__flipInY{-webkit-backface-visibility:visible!important;backface-visibility:visible!important;-webkit-animation-name:flipInY;animation-name:flipInY}@-webkit-keyframes flipOutX{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotateX(-20deg);transform:perspective(400px) rotateX(-20deg);opacity:1}to{-webkit-transform:perspective(400px) rotateX(90deg);transform:perspective(400px) rotateX(90deg);opacity:0}}@keyframes flipOutX{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotateX(-20deg);transform:perspective(400px) rotateX(-20deg);opacity:1}to{-webkit-transform:perspective(400px) rotateX(90deg);transform:perspective(400px) rotateX(90deg);opacity:0}}.animate__flipOutX{-webkit-animation-duration:.75s;animation-duration:.75s;-webkit-animation-duration:calc(var(--animate-duration)*0.75);animation-duration:calc(var(--animate-duration)*0.75);-webkit-animation-name:flipOutX;animation-name:flipOutX;-webkit-backface-visibility:visible!important;backface-visibility:visible!important}@-webkit-keyframes flipOutY{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotateY(-15deg);transform:perspective(400px) rotateY(-15deg);opacity:1}to{-webkit-transform:perspective(400px) rotateY(90deg);transform:perspective(400px) rotateY(90deg);opacity:0}}@keyframes flipOutY{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotateY(-15deg);transform:perspective(400px) rotateY(-15deg);opacity:1}to{-webkit-transform:perspective(400px) rotateY(90deg);transform:perspective(400px) rotateY(90deg);opacity:0}}.animate__flipOutY{-webkit-animation-duration:.75s;animation-duration:.75s;-webkit-animation-duration:calc(var(--animate-duration)*0.75);animation-duration:calc(var(--animate-duration)*0.75);-webkit-backface-visibility:visible!important;backface-visibility:visible!important;-webkit-animation-name:flipOutY;animation-name:flipOutY}@-webkit-keyframes lightSpeedInRight{0%{-webkit-transform:translate3d(100%,0,0) skewX(-30deg);transform:translate3d(100%,0,0) skewX(-30deg);opacity:0}60%{-webkit-transform:skewX(20deg);transform:skewX(20deg);opacity:1}80%{-webkit-transform:skewX(-5deg);transform:skewX(-5deg)}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes lightSpeedInRight{0%{-webkit-transform:translate3d(100%,0,0) skewX(-30deg);transform:translate3d(100%,0,0) skewX(-30deg);opacity:0}60%{-webkit-transform:skewX(20deg);transform:skewX(20deg);opacity:1}80%{-webkit-transform:skewX(-5deg);transform:skewX(-5deg)}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}.animate__lightSpeedInRight{-webkit-animation-name:lightSpeedInRight;animation-name:lightSpeedInRight;-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}@-webkit-keyframes lightSpeedInLeft{0%{-webkit-transform:translate3d(-100%,0,0) skewX(30deg);transform:translate3d(-100%,0,0) skewX(30deg);opacity:0}60%{-webkit-transform:skewX(-20deg);transform:skewX(-20deg);opacity:1}80%{-webkit-transform:skewX(5deg);transform:skewX(5deg)}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes lightSpeedInLeft{0%{-webkit-transform:translate3d(-100%,0,0) skewX(30deg);transform:translate3d(-100%,0,0) skewX(30deg);opacity:0}60%{-webkit-transform:skewX(-20deg);transform:skewX(-20deg);opacity:1}80%{-webkit-transform:skewX(5deg);transform:skewX(5deg)}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}.animate__lightSpeedInLeft{-webkit-animation-name:lightSpeedInLeft;animation-name:lightSpeedInLeft;-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}@-webkit-keyframes lightSpeedOutRight{0%{opacity:1}to{-webkit-transform:translate3d(100%,0,0) skewX(30deg);transform:translate3d(100%,0,0) skewX(30deg);opacity:0}}@keyframes lightSpeedOutRight{0%{opacity:1}to{-webkit-transform:translate3d(100%,0,0) skewX(30deg);transform:translate3d(100%,0,0) skewX(30deg);opacity:0}}.animate__lightSpeedOutRight{-webkit-animation-name:lightSpeedOutRight;animation-name:lightSpeedOutRight;-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}@-webkit-keyframes lightSpeedOutLeft{0%{opacity:1}to{-webkit-transform:translate3d(-100%,0,0) skewX(-30deg);transform:translate3d(-100%,0,0) skewX(-30deg);opacity:0}}@keyframes lightSpeedOutLeft{0%{opacity:1}to{-webkit-transform:translate3d(-100%,0,0) skewX(-30deg);transform:translate3d(-100%,0,0) skewX(-30deg);opacity:0}}.animate__lightSpeedOutLeft{-webkit-animation-name:lightSpeedOutLeft;animation-name:lightSpeedOutLeft;-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}@-webkit-keyframes rotateIn{0%{-webkit-transform:rotate(-200deg);transform:rotate(-200deg);opacity:0}to{-webkit-transform:translateZ(0);transform:translateZ(0);opacity:1}}@keyframes rotateIn{0%{-webkit-transform:rotate(-200deg);transform:rotate(-200deg);opacity:0}to{-webkit-transform:translateZ(0);transform:translateZ(0);opacity:1}}.animate__rotateIn{-webkit-animation-name:rotateIn;animation-name:rotateIn;-webkit-transform-origin:center;transform-origin:center}@-webkit-keyframes rotateInDownLeft{0%{-webkit-transform:rotate(-45deg);transform:rotate(-45deg);opacity:0}to{-webkit-transform:translateZ(0);transform:translateZ(0);opacity:1}}@keyframes rotateInDownLeft{0%{-webkit-transform:rotate(-45deg);transform:rotate(-45deg);opacity:0}to{-webkit-transform:translateZ(0);transform:translateZ(0);opacity:1}}.animate__rotateInDownLeft{-webkit-animation-name:rotateInDownLeft;animation-name:rotateInDownLeft;-webkit-transform-origin:left bottom;transform-origin:left bottom}@-webkit-keyframes rotateInDownRight{0%{-webkit-transform:rotate(45deg);transform:rotate(45deg);opacity:0}to{-webkit-transform:translateZ(0);transform:translateZ(0);opacity:1}}@keyframes rotateInDownRight{0%{-webkit-transform:rotate(45deg);transform:rotate(45deg);opacity:0}to{-webkit-transform:translateZ(0);transform:translateZ(0);opacity:1}}.animate__rotateInDownRight{-webkit-animation-name:rotateInDownRight;animation-name:rotateInDownRight;-webkit-transform-origin:right bottom;transform-origin:right bottom}@-webkit-keyframes rotateInUpLeft{0%{-webkit-transform:rotate(45deg);transform:rotate(45deg);opacity:0}to{-webkit-transform:translateZ(0);transform:translateZ(0);opacity:1}}@keyframes rotateInUpLeft{0%{-webkit-transform:rotate(45deg);transform:rotate(45deg);opacity:0}to{-webkit-transform:translateZ(0);transform:translateZ(0);opacity:1}}.animate__rotateInUpLeft{-webkit-animation-name:rotateInUpLeft;animation-name:rotateInUpLeft;-webkit-transform-origin:left bottom;transform-origin:left bottom}@-webkit-keyframes rotateInUpRight{0%{-webkit-transform:rotate(-90deg);transform:rotate(-90deg);opacity:0}to{-webkit-transform:translateZ(0);transform:translateZ(0);opacity:1}}@keyframes rotateInUpRight{0%{-webkit-transform:rotate(-90deg);transform:rotate(-90deg);opacity:0}to{-webkit-transform:translateZ(0);transform:translateZ(0);opacity:1}}.animate__rotateInUpRight{-webkit-animation-name:rotateInUpRight;animation-name:rotateInUpRight;-webkit-transform-origin:right bottom;transform-origin:right bottom}@-webkit-keyframes rotateOut{0%{opacity:1}to{-webkit-transform:rotate(200deg);transform:rotate(200deg);opacity:0}}@keyframes rotateOut{0%{opacity:1}to{-webkit-transform:rotate(200deg);transform:rotate(200deg);opacity:0}}.animate__rotateOut{-webkit-animation-name:rotateOut;animation-name:rotateOut;-webkit-transform-origin:center;transform-origin:center}@-webkit-keyframes rotateOutDownLeft{0%{opacity:1}to{-webkit-transform:rotate(45deg);transform:rotate(45deg);opacity:0}}@keyframes rotateOutDownLeft{0%{opacity:1}to{-webkit-transform:rotate(45deg);transform:rotate(45deg);opacity:0}}.animate__rotateOutDownLeft{-webkit-animation-name:rotateOutDownLeft;animation-name:rotateOutDownLeft;-webkit-transform-origin:left bottom;transform-origin:left bottom}@-webkit-keyframes rotateOutDownRight{0%{opacity:1}to{-webkit-transform:rotate(-45deg);transform:rotate(-45deg);opacity:0}}@keyframes rotateOutDownRight{0%{opacity:1}to{-webkit-transform:rotate(-45deg);transform:rotate(-45deg);opacity:0}}.animate__rotateOutDownRight{-webkit-animation-name:rotateOutDownRight;animation-name:rotateOutDownRight;-webkit-transform-origin:right bottom;transform-origin:right bottom}@-webkit-keyframes rotateOutUpLeft{0%{opacity:1}to{-webkit-transform:rotate(-45deg);transform:rotate(-45deg);opacity:0}}@keyframes rotateOutUpLeft{0%{opacity:1}to{-webkit-transform:rotate(-45deg);transform:rotate(-45deg);opacity:0}}.animate__rotateOutUpLeft{-webkit-animation-name:rotateOutUpLeft;animation-name:rotateOutUpLeft;-webkit-transform-origin:left bottom;transform-origin:left bottom}@-webkit-keyframes rotateOutUpRight{0%{opacity:1}to{-webkit-transform:rotate(90deg);transform:rotate(90deg);opacity:0}}@keyframes rotateOutUpRight{0%{opacity:1}to{-webkit-transform:rotate(90deg);transform:rotate(90deg);opacity:0}}.animate__rotateOutUpRight{-webkit-animation-name:rotateOutUpRight;animation-name:rotateOutUpRight;-webkit-transform-origin:right bottom;transform-origin:right bottom}@-webkit-keyframes hinge{0%{-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}20%,60%{-webkit-transform:rotate(80deg);transform:rotate(80deg);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}40%,80%{-webkit-transform:rotate(60deg);transform:rotate(60deg);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;opacity:1}to{-webkit-transform:translate3d(0,700px,0);transform:translate3d(0,700px,0);opacity:0}}@keyframes hinge{0%{-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}20%,60%{-webkit-transform:rotate(80deg);transform:rotate(80deg);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}40%,80%{-webkit-transform:rotate(60deg);transform:rotate(60deg);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;opacity:1}to{-webkit-transform:translate3d(0,700px,0);transform:translate3d(0,700px,0);opacity:0}}.animate__hinge{-webkit-animation-duration:2s;animation-duration:2s;-webkit-animation-duration:calc(var(--animate-duration)*2);animation-duration:calc(var(--animate-duration)*2);-webkit-animation-name:hinge;animation-name:hinge;-webkit-transform-origin:top left;transform-origin:top left}@-webkit-keyframes jackInTheBox{0%{opacity:0;-webkit-transform:scale(.1) rotate(30deg);transform:scale(.1) rotate(30deg);-webkit-transform-origin:center bottom;transform-origin:center bottom}50%{-webkit-transform:rotate(-10deg);transform:rotate(-10deg)}70%{-webkit-transform:rotate(3deg);transform:rotate(3deg)}to{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes jackInTheBox{0%{opacity:0;-webkit-transform:scale(.1) rotate(30deg);transform:scale(.1) rotate(30deg);-webkit-transform-origin:center bottom;transform-origin:center bottom}50%{-webkit-transform:rotate(-10deg);transform:rotate(-10deg)}70%{-webkit-transform:rotate(3deg);transform:rotate(3deg)}to{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}.animate__jackInTheBox{-webkit-animation-name:jackInTheBox;animation-name:jackInTheBox}@-webkit-keyframes rollIn{0%{opacity:0;-webkit-transform:translate3d(-100%,0,0) rotate(-120deg);transform:translate3d(-100%,0,0) rotate(-120deg)}to{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes rollIn{0%{opacity:0;-webkit-transform:translate3d(-100%,0,0) rotate(-120deg);transform:translate3d(-100%,0,0) rotate(-120deg)}to{opacity:1;-webkit-transform:translateZ(0);transform:translateZ(0)}}.animate__rollIn{-webkit-animation-name:rollIn;animation-name:rollIn}@-webkit-keyframes rollOut{0%{opacity:1}to{opacity:0;-webkit-transform:translate3d(100%,0,0) rotate(120deg);transform:translate3d(100%,0,0) rotate(120deg)}}@keyframes rollOut{0%{opacity:1}to{opacity:0;-webkit-transform:translate3d(100%,0,0) rotate(120deg);transform:translate3d(100%,0,0) rotate(120deg)}}.animate__rollOut{-webkit-animation-name:rollOut;animation-name:rollOut}@-webkit-keyframes zoomIn{0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}50%{opacity:1}}@keyframes zoomIn{0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}50%{opacity:1}}.animate__zoomIn{-webkit-animation-name:zoomIn;animation-name:zoomIn}@-webkit-keyframes zoomInDown{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);transform:scale3d(.475,.475,.475) translate3d(0,60px,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}@keyframes zoomInDown{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);transform:scale3d(.475,.475,.475) translate3d(0,60px,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}.animate__zoomInDown{-webkit-animation-name:zoomInDown;animation-name:zoomInDown}@-webkit-keyframes zoomInLeft{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(10px,0,0);transform:scale3d(.475,.475,.475) translate3d(10px,0,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}@keyframes zoomInLeft{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(10px,0,0);transform:scale3d(.475,.475,.475) translate3d(10px,0,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}.animate__zoomInLeft{-webkit-animation-name:zoomInLeft;animation-name:zoomInLeft}@-webkit-keyframes zoomInRight{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}@keyframes zoomInRight{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}.animate__zoomInRight{-webkit-animation-name:zoomInRight;animation-name:zoomInRight}@-webkit-keyframes zoomInUp{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}@keyframes zoomInUp{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}.animate__zoomInUp{-webkit-animation-name:zoomInUp;animation-name:zoomInUp}@-webkit-keyframes zoomOut{0%{opacity:1}50%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}to{opacity:0}}@keyframes zoomOut{0%{opacity:1}50%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}to{opacity:0}}.animate__zoomOut{-webkit-animation-name:zoomOut;animation-name:zoomOut}@-webkit-keyframes zoomOutDown{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}to{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}@keyframes zoomOutDown{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}to{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}.animate__zoomOutDown{-webkit-animation-name:zoomOutDown;animation-name:zoomOutDown;-webkit-transform-origin:center bottom;transform-origin:center bottom}@-webkit-keyframes zoomOutLeft{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(42px,0,0);transform:scale3d(.475,.475,.475) translate3d(42px,0,0)}to{opacity:0;-webkit-transform:scale(.1) translate3d(-2000px,0,0);transform:scale(.1) translate3d(-2000px,0,0)}}@keyframes zoomOutLeft{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(42px,0,0);transform:scale3d(.475,.475,.475) translate3d(42px,0,0)}to{opacity:0;-webkit-transform:scale(.1) translate3d(-2000px,0,0);transform:scale(.1) translate3d(-2000px,0,0)}}.animate__zoomOutLeft{-webkit-animation-name:zoomOutLeft;animation-name:zoomOutLeft;-webkit-transform-origin:left center;transform-origin:left center}@-webkit-keyframes zoomOutRight{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(-42px,0,0);transform:scale3d(.475,.475,.475) translate3d(-42px,0,0)}to{opacity:0;-webkit-transform:scale(.1) translate3d(2000px,0,0);transform:scale(.1) translate3d(2000px,0,0)}}@keyframes zoomOutRight{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(-42px,0,0);transform:scale3d(.475,.475,.475) translate3d(-42px,0,0)}to{opacity:0;-webkit-transform:scale(.1) translate3d(2000px,0,0);transform:scale(.1) translate3d(2000px,0,0)}}.animate__zoomOutRight{-webkit-animation-name:zoomOutRight;animation-name:zoomOutRight;-webkit-transform-origin:right center;transform-origin:right center}@-webkit-keyframes zoomOutUp{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);transform:scale3d(.475,.475,.475) translate3d(0,60px,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}to{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}@keyframes zoomOutUp{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);transform:scale3d(.475,.475,.475) translate3d(0,60px,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}to{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}.animate__zoomOutUp{-webkit-animation-name:zoomOutUp;animation-name:zoomOutUp;-webkit-transform-origin:center bottom;transform-origin:center bottom}@-webkit-keyframes slideInDown{0%{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0);visibility:visible}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes slideInDown{0%{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0);visibility:visible}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}.animate__slideInDown{-webkit-animation-name:slideInDown;animation-name:slideInDown}@-webkit-keyframes slideInLeft{0%{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);visibility:visible}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes slideInLeft{0%{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);visibility:visible}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}.animate__slideInLeft{-webkit-animation-name:slideInLeft;animation-name:slideInLeft}@-webkit-keyframes slideInRight{0%{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);visibility:visible}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes slideInRight{0%{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);visibility:visible}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}.animate__slideInRight{-webkit-animation-name:slideInRight;animation-name:slideInRight}@-webkit-keyframes slideInUp{0%{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);visibility:visible}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}@keyframes slideInUp{0%{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);visibility:visible}to{-webkit-transform:translateZ(0);transform:translateZ(0)}}.animate__slideInUp{-webkit-animation-name:slideInUp;animation-name:slideInUp}@-webkit-keyframes slideOutDown{0%{-webkit-transform:translateZ(0);transform:translateZ(0)}to{visibility:hidden;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}@keyframes slideOutDown{0%{-webkit-transform:translateZ(0);transform:translateZ(0)}to{visibility:hidden;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}.animate__slideOutDown{-webkit-animation-name:slideOutDown;animation-name:slideOutDown}@-webkit-keyframes slideOutLeft{0%{-webkit-transform:translateZ(0);transform:translateZ(0)}to{visibility:hidden;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}@keyframes slideOutLeft{0%{-webkit-transform:translateZ(0);transform:translateZ(0)}to{visibility:hidden;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}.animate__slideOutLeft{-webkit-animation-name:slideOutLeft;animation-name:slideOutLeft}@-webkit-keyframes slideOutRight{0%{-webkit-transform:translateZ(0);transform:translateZ(0)}to{visibility:hidden;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}@keyframes slideOutRight{0%{-webkit-transform:translateZ(0);transform:translateZ(0)}to{visibility:hidden;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}.animate__slideOutRight{-webkit-animation-name:slideOutRight;animation-name:slideOutRight}@-webkit-keyframes slideOutUp{0%{-webkit-transform:translateZ(0);transform:translateZ(0)}to{visibility:hidden;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}@keyframes slideOutUp{0%{-webkit-transform:translateZ(0);transform:translateZ(0)}to{visibility:hidden;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}.animate__slideOutUp{-webkit-animation-name:slideOutUp;animation-name:slideOutUp}
assets/{index.php → css/admin/index.php} RENAMED
File without changes
assets/css/style.css DELETED
@@ -1,148 +0,0 @@
1
- #a2opt-content-general #kb-search-request {
2
- font-size: 18px;
3
- border-radius: 5px;
4
- color: #999;
5
- padding: 3px;
6
- width: 300px;
7
- }
8
-
9
- #a2opt-content-general .kb-search button {
10
- font-size: 14px;
11
- padding: 6px 12px;
12
- vertical-align:top;
13
- }
14
- #a2opt-content-general .btn.large {
15
- font-size: 15px;
16
- line-height: normal;
17
- padding: 9px 14px 9px;
18
- -webkit-border-radius: 6px;
19
- -moz-border-radius: 6px;
20
- border-radius: 6px;
21
- }
22
-
23
- #a2opt-content-general {
24
- background: none;
25
- }
26
-
27
- #a2opt-content-general .fade{
28
- opacity: 100 !important;
29
- }
30
-
31
- #a2opt-content-general .checkbox{
32
- width:24px;
33
- height:24px;
34
- float:left;
35
- background: url(../images/icons.png) no-repeat -452px -112px;
36
- }
37
-
38
- #a2opt-content-general .checkbox.checked{
39
- background: url(../images/icons.png) no-repeat -424px -112px;
40
- }
41
-
42
- #a2opt-content-general .optimization-status{
43
- width:260px;
44
- float:left;
45
- font-size:1.2em;
46
- }
47
-
48
- #a2opt-content-general .glyphicon-ok{
49
- color:green;
50
- }
51
-
52
- #a2opt-content-general .glyphicon-warning-sign{
53
- color:orange;
54
- }
55
- #a2opt-content-general .glyphicon-exclamation-sign{
56
- color:red;
57
- }
58
-
59
- #a2opt-content-general .danger{
60
- color:red;
61
- }
62
-
63
- #a2opt-content-general .warning{
64
- color:orange;
65
- }
66
-
67
- #a2opt-content-general .success{
68
- color:green;
69
- }
70
-
71
-
72
-
73
- #a2opt-content-general .badge-warning{
74
- background-color:orange !important;
75
- }
76
- #a2opt-content-general .badge-danger{
77
- background-color:red !important;
78
- }
79
- #a2opt-content-general .badge-success{
80
- background-color:green !important;
81
- }
82
- #a2opt-content-general .badge-default{
83
- background-color:blue !important;
84
- }
85
-
86
- #a2opt-content-general .optimization-item{
87
- padding:10px;
88
- border-width: 0 0 2px 0;
89
- border-style: solid;
90
- border-color: #ccc;
91
- }
92
-
93
- #a2opt-content-general .tab-content{
94
- padding:10px;
95
- }
96
-
97
- #a2opt-content-general a.a2-exclusive{
98
- display: block;
99
- width: 250px;
100
- height: 19px;
101
- background: url(../images/a2-exclusive.png) no-repeat;
102
- }
103
-
104
- #a2opt-content-general .optimization-item .optimization-item-one{
105
- float:left;
106
- width:44px;
107
- font-size:36px
108
- }
109
-
110
- #a2opt-content-general .optimization-item .optimization-item-two{
111
- float:left;
112
- }
113
-
114
- #a2opt-content-general .optimization-item .optimization-item-three{
115
- clear:both;
116
- }
117
-
118
- #a2opt-content-general .optimization-item .optimization-item-four{
119
- clear:both;
120
- }
121
-
122
- #edge-mode{
123
- display:none !important;
124
- height:0px !important;
125
- }
126
- #gfw-hosting-meta-box{
127
- display:none !important;
128
- }
129
- img[title=Logo]{
130
- display:none;
131
- }
132
-
133
- #a2opt-content-general .optimization-item.inactive {
134
- color: #ddd;
135
- }
136
-
137
- #a2opt-content-general .optimization-item.inactive .glyphicon-exclamation-sign, #a2opt-content-general .optimization-item.inactive .danger {
138
- color: #ddd;
139
- }
140
-
141
- #a2opt-content-general .nav > li > a {
142
- font-size: 14px;
143
- }
144
-
145
- #a2opt-content-general .nav-tabs > li.active > a, #a2opt-content-general .nav-tabs > li.active > a:hover, #a2opt-content-general .nav-tabs > li.active > a:focus {
146
- background-color: #ededed !important;
147
- font-weight: bold;
148
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
assets/images/a2-exclusive.png DELETED
Binary file
assets/images/a2optimized.png DELETED
Binary file
assets/images/admin/a2opt-logo-2022-2x.png ADDED
Binary file
assets/images/admin/a2opt-logo-2022.png ADDED
Binary file
assets/images/admin/index.php ADDED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ // Silence is golden.
assets/images/admin/wave-danger.png ADDED
Binary file
assets/images/admin/wave-empty.png ADDED
Binary file
assets/images/admin/wave-success.png ADDED
Binary file
assets/images/admin/wave-warn.png ADDED
Binary file
assets/images/background-both.png DELETED
Binary file
assets/images/background-left.png DELETED
Binary file
assets/images/background-right.png DELETED
Binary file
assets/images/brankic1979-icon-set.png DELETED
Binary file
assets/images/icons.png DELETED
Binary file
assets/images/image001.jpg DELETED
Binary file
assets/images/spinner.gif DELETED
Binary file
assets/js/admin/a2-optimized.js ADDED
@@ -0,0 +1,854 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ function generateCircle(id, radius, width, graph_data) {
2
+ if (!graph_data) { return; }
3
+
4
+ let baseColor = palette[graph_data.color_class];
5
+
6
+ var circle_graph = Circles.create({
7
+ id: id,
8
+ radius: radius,
9
+ value: graph_data.score,
10
+ maxValue: graph_data.max,
11
+ width: width,
12
+ text: graph_data.text,
13
+ colors: [baseColor + '25', baseColor + '55'],
14
+ duration: 400,
15
+ wrpClass: 'circles-wrp',
16
+ textClass: 'circles-text',
17
+ valueStrokeClass: 'circles-valueStroke',
18
+ maxValueStrokeClass: 'circles-maxValueStroke',
19
+ styleWrapper: true,
20
+ styleText: true
21
+ });
22
+
23
+ return circle_graph;
24
+ }
25
+
26
+ const plugin_draw_a2hosting_box = {
27
+ id: 'custom_canvas_background_color_area',
28
+ beforeDraw: (chart) => {
29
+ const { ctx } = chart;
30
+ ctx.save();
31
+ ctx.globalCompositeOperation = 'destination-over';
32
+ ctx.strokeStyle = palette.success + '50';
33
+ ctx.lineWidth = 5;
34
+ let meta = chart.getDatasetMeta(0);
35
+ let data = meta.data[1];
36
+
37
+ let top = chart.chartArea.top - 5;
38
+ let height = chart.chartArea.height + 10;
39
+ let left = data.x - (data.width * .5) - 20;
40
+ ctx.strokeRect(left, top, chart.chartArea.width - left + 20, height);
41
+ ctx.font = '20px Verdana';
42
+ /*
43
+ var gradient = ctx.createLinearGradient(0, 0, chart.chartArea.width - left + 20, 0);
44
+ gradient.addColorStop("0", palette.success);
45
+ gradient.addColorStop("1", palette.success);
46
+ ctx.fillStyle = gradient;
47
+ */
48
+ ctx.fillStyle = palette.success;
49
+ ctx.fillText('A2 Hosting', left + 60, top + 30);
50
+ ctx.restore();
51
+ }
52
+ }
53
+
54
+ function generateSingleBarGraphData(graph, dataPoint) {
55
+ graph_products = ['host', 'a2hosting-turbo', 'a2hosting-mwp'];
56
+
57
+ let set_title = graph.legend_text;
58
+
59
+ let graph_labels = [];
60
+ let graph_dataset = [];
61
+ let colors = [];
62
+ let bgColors = [];
63
+ let borderColors = [];
64
+ let entryData = [];
65
+
66
+ graph_products.forEach((product, index, array) => {
67
+ let data_entry = page_data.graph_data[product];
68
+ graph_labels[index] = data_entry.display_text;
69
+
70
+
71
+ let value = parseFloat(data_entry[dataPoint]);
72
+ colors[index] = palette[data_entry.color_class];
73
+ bgColors[index] = palette[data_entry.color_class] + '80';
74
+ borderColors[index] = palette[data_entry.color_class] + '50';
75
+ entryData[index] = value;
76
+
77
+ });
78
+ graph_dataset[0] = {
79
+ label: page_data.graphs.tooltips[dataPoint],
80
+ color: colors,
81
+ backgroundColor: bgColors,
82
+ hoverBackgroundColor: bgColors,
83
+ borderColor: borderColors,
84
+ data: entryData
85
+ }
86
+ return { title: set_title, labels: graph_labels, dataset: graph_dataset, show_legend: false, stack: false };
87
+ }
88
+
89
+ function generateStackedBarGraphData(graph, dataPoints = []) {
90
+ graph_products = ['host', 'a2hosting-turbo', 'a2hosting-mwp'];
91
+
92
+ let set_title = graph.legend_text;
93
+
94
+ let graph_labels = [];
95
+ let data_labels = [];
96
+ let graph_dataset = [];
97
+
98
+ let entryData = [];
99
+
100
+ let colors = [];
101
+ let bgColors = [];
102
+ let borderColors = [];
103
+
104
+ // pre grab some info by product -> metric
105
+ graph_products.forEach((el, prodIndex, array) => {
106
+ graph_labels[prodIndex] = page_data.graph_data[el].display_text;
107
+ dataPoints.forEach((dataPointName, metricIndex, array) => {
108
+ let data_entry = page_data.graph_data[el];
109
+
110
+ data_labels[metricIndex] = dataPointName;
111
+ });
112
+ });
113
+
114
+ // get the rest of the info by metric -> product
115
+ dataPoints.forEach((dataPointName, metricIndex, array) => {
116
+
117
+ entryData = [];
118
+
119
+ graph_products.forEach((el, prodIndex, array) => {
120
+ let data_entry = page_data.graph_data[el];
121
+
122
+ let value = parseFloat(data_entry[dataPointName]);
123
+ entryData[prodIndex] = value;
124
+
125
+ // re-use the product colors for the metric colors. This will break if the number of products is ever != the number of metrics
126
+ colors[prodIndex] = palette[data_entry.color_class];
127
+ bgColors[prodIndex] = palette[data_entry.color_class] + '80';
128
+ borderColors[prodIndex] = palette[data_entry.color_class] + '50';
129
+
130
+ });
131
+
132
+ graph_dataset[metricIndex] =
133
+ {
134
+ label: page_data.graphs.tooltips[data_labels[metricIndex]],
135
+ color: colors[metricIndex],
136
+ backgroundColor: bgColors[metricIndex],
137
+ hoverBackgroundColor: bgColors[metricIndex],
138
+ borderColor: borderColors[metricIndex],
139
+ data: entryData
140
+ }
141
+
142
+ });
143
+
144
+
145
+ return { title: set_title, labels: graph_labels, dataset: graph_dataset, show_legend: true, stack: true };
146
+ }
147
+
148
+ function createBarGraph(canvasId, graph_metadata) {
149
+ const targetCanvas = document.getElementById(canvasId);
150
+ var oldChart = Chart.getChart(targetCanvas);
151
+ if (oldChart){
152
+ oldChart.destroy();
153
+ }
154
+
155
+ var chart = new Chart(targetCanvas, {
156
+ type: 'bar',
157
+ data: {
158
+ labels: graph_metadata.labels,
159
+ datasets: graph_metadata.dataset,
160
+ },
161
+ plugins: [plugin_draw_a2hosting_box],
162
+ options: {
163
+ tooltips: {
164
+ callbacks: {
165
+ label: function (tooltipItem, data) {
166
+ return Number(tooltipItem.yLabel).toFixed(2);
167
+ }
168
+ }
169
+ },
170
+ scales: {
171
+ x: {
172
+ stacked: graph_metadata.stack,
173
+ ticks: {
174
+ color: (c) => {
175
+ return c.index > 0 ? 'green' : Chart.defaults.color;
176
+ },
177
+ }
178
+ },
179
+ y: {
180
+ stacked: graph_metadata.stack
181
+ }
182
+
183
+ },
184
+ responsive: false,
185
+ plugins: {
186
+ title: {
187
+ display: true,
188
+ text: graph_metadata.title
189
+ },
190
+ legend: {
191
+ display: graph_metadata.show_legend,
192
+ },
193
+ }
194
+ },
195
+ });
196
+ return chart;
197
+ }
198
+
199
+ function createLineGraph(elemId, graphData, circleId) {
200
+ if (!graphData) { return; }
201
+ let lineDiv = document.getElementById(elemId);
202
+ if (!lineDiv) {return;}
203
+ let rect = lineDiv.getBoundingClientRect();
204
+ var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
205
+ svg.setAttribute("width", rect.width);
206
+ svg.setAttribute("height", rect.height);
207
+
208
+ var max_length = rect.width - 10;
209
+ var progress_percent = graphData.score / graphData.max;
210
+ if (progress_percent > 1) {
211
+ progress_percent = 1;
212
+ }
213
+ var progress_length = max_length * progress_percent;
214
+
215
+ var baseColor = palette[graphData.color_class];
216
+ svg.appendChild(getLinePath(5, 5, max_length, baseColor + "25"));
217
+ svg.appendChild(getLinePath(5, 5, progress_length, baseColor));
218
+
219
+ lineDiv.innerHTML = '';
220
+ lineDiv.appendChild(svg);
221
+
222
+
223
+ if (circleId) {
224
+ let circleDiv = document.getElementById(circleId);
225
+ let centerPos = rect.width / 2;
226
+ let maxOffset = centerPos - 35;
227
+ let offset = progress_length - centerPos;
228
+ if (offset < -1 * maxOffset) {
229
+ offset = -1 * maxOffset;
230
+ }
231
+ else if (offset > maxOffset) {
232
+ offset = maxOffset;
233
+ }
234
+ let graphDiv = circleDiv.querySelector('.circles-wrp');
235
+ graphDiv.style.left = offset + "px";
236
+ }
237
+ }
238
+
239
+ function getLinePath(x, y, length, color) {
240
+ var path = document.createElementNS("http://www.w3.org/2000/svg", "path");
241
+ path.setAttribute("fill", "transparent");
242
+ path.setAttribute("stroke", color);
243
+ path.setAttribute("stroke-width", "10");
244
+ path.setAttribute("stroke-linecap", "round");
245
+ path.setAttribute("stroke-linejoin", "round");
246
+ path.setAttribute("class", "line-graph-style");
247
+ path.setAttribute("d", "m " + x + "," + y + " h " + length + " Z");
248
+
249
+ return path;
250
+
251
+ }
252
+
253
+ // thanks stackoverflow! https://stackoverflow.com/questions/1740700/how-to-get-hex-color-value-rather-than-rgb-value
254
+ function rgb2hex(rgb) {
255
+ var match = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/)
256
+ return '#' + match.slice(1).map(n => parseInt(n, 10).toString(16).padStart(2, '0')).join('');
257
+ }
258
+
259
+ let palette = [];
260
+ document.addEventListener("DOMContentLoaded", function () {
261
+ var palette_items = document.querySelectorAll("#color-palette span");
262
+ palette_items.forEach(function (el, index, array) {
263
+ var style = getComputedStyle(el);
264
+ var element_color = style.color;
265
+ var element_class = el.className;
266
+ var hex = rgb2hex(element_color);
267
+ palette[element_class] = hex;
268
+ });
269
+
270
+ });
271
+
272
+ Vue.component('info-button', {
273
+ props: { metric: { type: String } },
274
+ template: "#info-button-template",
275
+ methods: {
276
+ toggleInfoDiv: function (metric, elem) {
277
+ this.$root.toggleInfoDiv(metric);
278
+ }
279
+ }
280
+ });
281
+
282
+ addEventListener('animationend', onAnimationEnd);
283
+ function onAnimationEnd(event) {
284
+ let elem = event.target;
285
+ if (event.animationName == 'flipToFront1') {
286
+ var front = elem.querySelector('.flip-card-front');
287
+ var back = elem.querySelector('.flip-card-back');
288
+ front.style.display = 'none';
289
+ back.style.display = 'block';
290
+
291
+ elem.classList.remove('flip-start');
292
+ elem.classList.add('flip-finish');
293
+ }
294
+ else if (event.animationName == 'flipToFront2') {
295
+ elem.classList.remove('flip-finish');
296
+ elem.classList.add('flipped');
297
+ }
298
+ else if (event.animationName == 'flipToFront3') {
299
+ var front = elem.querySelector('.flip-card-front');
300
+ var back = elem.querySelector('.flip-card-back');
301
+ front.style.display = 'block';
302
+ back.style.display = 'none';
303
+
304
+ elem.classList.remove('flip-start');
305
+ elem.classList.add('flip-finish');
306
+ }
307
+ else if (event.animationName == 'flipToFront4') {
308
+ elem.classList.remove('flip-finish');
309
+ elem.classList.remove('flipped');
310
+ }
311
+ else {
312
+ elem.classList.remove(event.animationName);
313
+ }
314
+ }
315
+
316
+ /**
317
+ * function used to trigger an animation.
318
+ * mostly used for testing out or demo-ing animations on demand
319
+ * @param {*} anim
320
+ */
321
+ function playAnim(anim) {
322
+ let bell = document.getElementById("drop-bell-wrapper");
323
+ let animname = '';
324
+ switch (anim) {
325
+ case '1':
326
+ animname = 'ringCycle1';
327
+ break;
328
+ case '2':
329
+ animname = 'ringCycle2';
330
+ break;
331
+ case '3':
332
+ animname = 'ringPulse';
333
+ break;
334
+ }
335
+
336
+ if (animname) {
337
+ if (bell.classList.contains(animname)) {
338
+ bell.classList.remove(animname);
339
+ }
340
+ else {
341
+ bell.classList.add(animname);
342
+ }
343
+ }
344
+ }
345
+
346
+ Vue.component('speed-metric-card', {
347
+ props: {
348
+ metric_name: String,
349
+ metric: Object,
350
+ show_line: { type: String, default: 'true' },
351
+ show_wave: { type: String, default: 'true' },
352
+ show_legend: { type: String, default: 'true' },
353
+ },
354
+ template: "#speed-metric-card-template",
355
+ data() {
356
+ return {
357
+
358
+ }
359
+ },
360
+ });
361
+
362
+ Vue.component('flip-panel', {
363
+ props: {
364
+ content_id: String,
365
+ status_class: String,
366
+ additional_classes: String,
367
+ disable_show_button: { Boolean: false }
368
+ },
369
+ template: "#flip-panel-template",
370
+ data() {
371
+ return {
372
+ content_index: 0
373
+ }
374
+ },
375
+ methods: {
376
+ toggleFlipPanel: function (wrapperId, elem) {
377
+ let wrapper = document.getElementById(wrapperId);
378
+ let flip_inner = wrapper.querySelector('.flip-card-inner');
379
+
380
+ this.content_index++;
381
+ if (this.content_index > 1) {
382
+ this.content_index = 0;
383
+ }
384
+
385
+ flip_inner.classList.remove('flip-start');
386
+ flip_inner.classList.remove('flip-finish');
387
+
388
+ flip_inner.classList.add('flip-start');
389
+
390
+ if (this.content_index == 1) {
391
+ }
392
+ }
393
+ }
394
+ });
395
+
396
+ Vue.component('graph-legend', {
397
+ props: { metric: { type: String } },
398
+ data() {
399
+ return page_data.graphs[this.metric]
400
+ },
401
+ template: "#graph-legend-template"
402
+ });
403
+
404
+ Vue.component('optimization-entry', {
405
+ props: {
406
+ opt: Object,
407
+ wrapper_id: String
408
+ },
409
+ data() {
410
+ return this.opt;
411
+ },
412
+ methods: {
413
+ desc_toggle: function (id) {
414
+ let desc = document.getElementById('opt_item_desc_' + id);
415
+ let toggle = document.getElementById('opt_item_toggle_' + id);
416
+
417
+ if (desc.style.display === 'none') {
418
+ desc.style.display = 'block';
419
+ toggle.classList.remove('glyphicon-chevron-down');
420
+ toggle.classList.add('glyphicon-chevron-up');
421
+ } else {
422
+ desc.style.display = 'none';
423
+ toggle.classList.add('glyphicon-chevron-down');
424
+ toggle.classList.remove('glyphicon-chevron-up');
425
+ }
426
+ },
427
+ toggleExtraSettings: function (slug, event) {
428
+ this.$root.$emit('extra_settings_show', { slug: slug });
429
+ this.$parent.toggleFlipPanel(this.wrapper_id, event);
430
+ },
431
+ optimizationClicked: function (isDisabled) {
432
+ if (isDisabled) {
433
+ page_data.showA2Only = true;
434
+ }
435
+ },
436
+ settingToggled: function(event) {
437
+ let changed = event.target;
438
+ let changedSlug = changed.name;
439
+ let changedValue = changed.checked ? 'on' : 'off';
440
+
441
+ if (page_data.settings_tethers[changedValue][changedSlug]){
442
+ page_data.settings_tethers[changedValue][changedSlug].forEach((tethered_slug, index, array) => {
443
+ let newValue = changed.checked;
444
+ if (page_data.optimizations.performance[tethered_slug]){
445
+ page_data.optimizations.performance[tethered_slug].configured = newValue;
446
+ }
447
+ else if (page_data.optimizations.security[tethered_slug]){
448
+ page_data.optimizations.security[tethered_slug].configured = newValue;
449
+ }
450
+ else if (page_data.other_optimizations.performance[tethered_slug]){
451
+ page_data.other_optimizations.performance[tethered_slug].configured = newValue;
452
+ }
453
+ else if (page_data.other_optimizations.security[tethered_slug]){
454
+ page_data.other_optimizations.security[tethered_slug].configured = newValue;
455
+ }
456
+
457
+ });
458
+ }
459
+
460
+ }
461
+ },
462
+ template: "#optimization-entry"
463
+ });
464
+ Vue.component('opt-extra-settings', {
465
+ props: {
466
+ extra_settings: Object,
467
+ },
468
+ data() {
469
+ return {
470
+ selected_slug: '',
471
+ }
472
+ },
473
+ computed: {
474
+ opt_group() {
475
+ return this.extra_settings[this.selected_slug];
476
+ }
477
+ },
478
+ template: "#opt-extra-settings-template",
479
+ mounted() {
480
+ this.$root.$on('extra_settings_show', data => {
481
+ this.selected_slug = data.slug;
482
+ });
483
+ },
484
+ updated() {
485
+ this.adjustSettingVisibility();
486
+ },
487
+ methods: {
488
+ adjustSettingVisibility: function () {
489
+ // hide or show the redis/memcached server fields
490
+ let cache_type = page_data['extra_settings']['a2_object_cache']['settings_sections']['a2_optimized_objectcache_type']['settings']['a2_optimized_objectcache_type']['value'];
491
+
492
+ let memcached_server = document.getElementById('setting-memcached_server');
493
+ let redis_server = document.getElementById('setting-redis_server');
494
+
495
+ if (memcached_server) {
496
+ memcached_server.style = cache_type == 'memcached' ? '' : 'display:none;'
497
+ }
498
+ if (redis_server) {
499
+ redis_server.style = cache_type == 'redis' ? '' : 'display:none;'
500
+ }
501
+ }
502
+ }
503
+ });
504
+
505
+ Vue.component('hosting-matchup', {
506
+ data() {
507
+ return page_data
508
+ },
509
+ methods: {
510
+ pageSpeedCheck: function () {
511
+ this.$root.pageSpeedCheck('hosting-matchup');
512
+ },
513
+ renderGraphs: function() {
514
+ let webperf_meta = generateSingleBarGraphData(page_data.graphs['webperformance'], 'wordpress_db');
515
+ let serverperf_meta = generateStackedBarGraphData(page_data.graphs['serverperformance'], ['php', 'mysql', 'filesystem']);
516
+
517
+ createBarGraph('overall_wordpress_canvas', webperf_meta);
518
+ createBarGraph('server_perf_canvas', serverperf_meta, true, true);
519
+ }
520
+ },
521
+ template: "#hosting-matchup-template",
522
+ mounted() {
523
+ let that = this;
524
+
525
+ this.$root.$on('render_hosting_matchup_graphs', () => {
526
+ this.renderGraphs();
527
+ });
528
+
529
+ document.addEventListener("DOMContentLoaded", function () {
530
+ that.renderGraphs();
531
+ });
532
+ }
533
+ });
534
+
535
+ Vue.component('optimizations-performance', {
536
+ data() {
537
+ return page_data;
538
+ },
539
+ methods: {
540
+ doCircles: function () {
541
+ let graphs = page_data.graphs;
542
+ let optsPerformace = generateCircle('circles-opt-perf', 40, 10, graphs.performance);
543
+ let optsSecurity = generateCircle('circles-opt-security', 40, 10, graphs.security);
544
+ let optsBestp = generateCircle('circles-opt-bestp', 40, 10, graphs.bestp);
545
+ },
546
+ promptToUpdate: function (event, header, message, slug, value) {
547
+ this.$parent.promptForAction(header, message, () => {
548
+ this.updateOptimizations(event, slug, value);
549
+ if (slug == 'regenerate_salts') {
550
+ window.location.href = page_data.login_url;
551
+ }
552
+ });
553
+ },
554
+ updateOptimizations: function (event, slug = "", value = "") {
555
+ page_data.openModal('Updating Optimizations...');
556
+ let params = new URLSearchParams();
557
+ params.append('action', 'apply_optimizations');
558
+ params.append('nonce', ajax.nonce);
559
+
560
+ if (slug) {
561
+ params.append('opt-' + slug, value);
562
+ }
563
+ else {
564
+ for (let key in page_data.optimizations) {
565
+ for (let index in page_data.optimizations[key]) {
566
+ params.append('opt-' + index, page_data.optimizations[key][index]['configured']);
567
+ }
568
+ }
569
+ for (let key in page_data.other_optimizations) {
570
+ for (let index in page_data.other_optimizations[key]) {
571
+ params.append('opt-' + index, page_data.other_optimizations[key][index]['configured']);
572
+ }
573
+ }
574
+ for (let parent in page_data.extra_settings) { // a2_page_cache
575
+ for (let item in page_data.extra_settings[parent]['settings_sections']) { // site_clear
576
+ for (let subitem in page_data.extra_settings[parent]['settings_sections'][item]['settings']) { // clear_site_cache_on_changed_plugin
577
+ params.append('opt-' + subitem, page_data.extra_settings[parent]['settings_sections'][item]['settings'][subitem]['value']);
578
+
579
+ // If this item has extra_fields
580
+ if (page_data.extra_settings[parent]['settings_sections'][item]['settings'][subitem].hasOwnProperty('extra_fields')) {
581
+ for (let extra_field in page_data.extra_settings[parent]['settings_sections'][item]['settings'][subitem]['extra_fields']) { // cache_expiry_time
582
+ params.append('opt-' + extra_field, page_data.extra_settings[parent]['settings_sections'][item]['settings'][subitem]['extra_fields'][extra_field]['value']);
583
+ }
584
+ }
585
+ }
586
+ }
587
+ }
588
+ }
589
+
590
+ axios
591
+ .post(ajax.url, params)
592
+ .catch((error) => {
593
+ alert('There was a problem getting optimization data. See console log.');
594
+ console.log(error.message);
595
+ page_data.closeModal();
596
+ })
597
+ .then((response) => {
598
+ console.log('got ajax response');
599
+ console.log(response.data);
600
+ page_data.closeModal();
601
+ if (response.data.updated_data != null) {
602
+ let updated = response.data.updated_data;
603
+ page_data.optimizations = updated.optimizations;
604
+ page_data.other_optimizations = updated.other_optimizations;
605
+ page_data.graphs = updated.graphs;
606
+ page_data.best_practices = updated.best_practices;
607
+ page_data.extra_settings = updated.extra_settings;
608
+ page_data.mainkey++;
609
+ page_data.showSuccess = true;
610
+ }
611
+ else {
612
+ alert('invalid data received, please reload page');
613
+ page_data.mainkey++;
614
+ page_data.showSuccess = false;
615
+ }
616
+ this.$nextTick(function () { // wait until things are re-rendered from the mainkey++ update, and then trigger the circles re-render
617
+ page_data.updateView++;
618
+ });
619
+ });
620
+ },
621
+ updateNavLinks: function (currentNav) {
622
+ this.sidenav = currentNav;
623
+ }
624
+ },
625
+ template: "#optimizations-performance-template",
626
+ mounted() {
627
+ let that = this;
628
+
629
+ document.addEventListener("DOMContentLoaded", function () {
630
+ that.doCircles();
631
+ let hash = window.location.hash;
632
+ if (hash == '') {
633
+ hash = 'optperf';
634
+ }
635
+ else {
636
+ hash = hash.slice(1); // chop off # from beginning
637
+ }
638
+ that.updateNavLinks(hash);
639
+ });
640
+ },
641
+ props: ['updateChild'],
642
+ watch: {
643
+ updateChild: function () {
644
+ this.doCircles();
645
+ },
646
+ }
647
+ });
648
+
649
+ Vue.component("modal", {
650
+ props: {
651
+ show_busy: { Boolean: false },
652
+ show_close: { Boolean: false }
653
+ },
654
+ data() {
655
+ return page_data;
656
+ },
657
+ template: "#modal-template"
658
+ });
659
+
660
+ Vue.component('server-performance', {
661
+ data() {
662
+ return page_data
663
+ },
664
+ methods: {
665
+ strategyChanged: function (evt) {
666
+ this.$root.pageSpeedCheck('server-performance', false);
667
+
668
+ },
669
+ pageSpeedCheck: function () {
670
+ this.$root.pageSpeedCheck('server-performance');
671
+ },
672
+ rec_toggle: function (id) {
673
+ let desc = document.getElementById('rec_item_desc_' + id);
674
+ let toggle = document.getElementById('rec_item_toggle_' + id);
675
+
676
+ if (desc.style.display === 'none') {
677
+ desc.style.display = 'block';
678
+ toggle.classList.remove('glyphicon-chevron-right');
679
+ toggle.classList.add('glyphicon-chevron-down');
680
+ } else {
681
+ desc.style.display = 'none';
682
+ toggle.classList.add('glyphicon-chevron-right');
683
+ toggle.classList.remove('glyphicon-chevron-down');
684
+ }
685
+
686
+ },
687
+ drawGraphs: function () {
688
+ let perf = page_data.graphs;
689
+ let circles_ttfb = generateCircle('circles-ttfb', 40, 10, perf.ttfb);
690
+ let circles_cls = generateCircle('circles-cls', 40, 10, perf.cls);
691
+ let circles_overall = generateCircle('circles-overall_score', 60, 10, perf.overall_score);
692
+
693
+ let circles_lcp = generateCircle('circles-lcp', 35, 10, perf.lcp);
694
+ let circles_fid = generateCircle('circles-fid', 35, 10, perf.fid);
695
+ let circles_fcp = generateCircle('circles-fcp', 35, 10, perf.fcp);
696
+
697
+ let line_graph_lcp = createLineGraph('line-graph-lcp', perf.lcp, 'circles-lcp');
698
+ let line_graph_fid = createLineGraph('line-graph-fid', perf.fid, 'circles-fid');
699
+ let line_graph_fcp = createLineGraph('line-graph-fcp', perf.fcp, 'circles-fcp');
700
+ }
701
+ },
702
+ template: "#server-performance-template",
703
+ props: ['updateChild'],
704
+ watch: {
705
+ updateChild: function () {
706
+ this.drawGraphs();
707
+ }
708
+ },
709
+ mounted() {
710
+ let that = this;
711
+ document.addEventListener("DOMContentLoaded", function () {
712
+ that.drawGraphs();
713
+ });
714
+ }
715
+ });
716
+
717
+ Vue.component('page-speed-score', {
718
+ data() {
719
+ page_data.info_toggle_data = {
720
+ 'pagespeed': false,
721
+ 'opt': false
722
+ };
723
+ return page_data
724
+ },
725
+ methods: {
726
+ pageSpeedCheck: function () {
727
+ this.$root.pageSpeedCheck('page-speed-score');
728
+ },
729
+ doCircles: function () {
730
+ let graphs = page_data.graphs;
731
+ let plsMobile = generateCircle('circles-pls-mobile', 40, 10, graphs.pagespeed_mobile.overall_score);
732
+ let plsDesktop = generateCircle('circles-pls-desktop', 40, 10, graphs.pagespeed_desktop.overall_score);
733
+
734
+ let optPerf = generateCircle('circles-opt-perf', 35, 7, graphs.performance);
735
+ let optSec = generateCircle('circles-opt-sec', 35, 7, graphs.security);
736
+ let optBP = generateCircle('circles-opt-bestp', 35, 7, graphs.bestp);
737
+ }
738
+ },
739
+ template: "#page-speed-score-template",
740
+ mounted() {
741
+ let that = this;
742
+
743
+ document.addEventListener("DOMContentLoaded", function () {
744
+ that.doCircles();
745
+ });
746
+ },
747
+ props: ['updateChild'],
748
+ watch: {
749
+ updateChild: function () {
750
+ this.doCircles();
751
+ }
752
+ }
753
+ });
754
+
755
+ let app = new Vue({
756
+ el: '#a2-optimized-wrapper',
757
+ data: page_data,
758
+ mounted() {
759
+ document.addEventListener("DOMContentLoaded", function () {
760
+ if (page_data.last_check_date && page_data.last_check_date == 'None'){
761
+ setTimeout(() => {
762
+ page_data.show_coaching = true;
763
+ }, 2000);
764
+ }
765
+ });
766
+ },
767
+ methods: {
768
+ addFakeNotif: function () {
769
+ let content = document.getElementById('fake_notif_text').value;
770
+ let params = new URLSearchParams();
771
+ params.append('action', 'add_notification');
772
+ params.append('a2_notification_text', content);
773
+ axios
774
+ .post(ajax.url, params)
775
+ .catch((error) => {
776
+ alert('There was a problem adding notification. See console log.');
777
+ console.log(error.message);
778
+ })
779
+ .then((response) => {
780
+ console.log(response);
781
+ });
782
+ },
783
+ toggleInfoDiv: function (metric) {
784
+ let data_div = document.querySelector('#graph-' + metric + ' .graph_data');
785
+ let explanation_div = document.querySelector('#graph-' + metric + ' .graph_info');
786
+
787
+ if (data_div.style.display == 'none') {
788
+ data_div.style.display = '';
789
+ explanation_div.style.display = 'none';
790
+ }
791
+ else {
792
+ data_div.style.display = 'none';
793
+ explanation_div.style.display = '';
794
+ }
795
+ },
796
+ pageSpeedCheck: function (page, run_checks = true) {
797
+ let msg = run_checks ? 'It will just take a few moments to update your scores ... ' : 'Loading in scores ... '
798
+ page_data.openModal(msg);
799
+ let params = new URLSearchParams();
800
+ params.append('action', 'run_benchmarks');
801
+ params.append('a2_page', page);
802
+ params.append('run_checks', run_checks);
803
+ params.append('nonce', ajax.nonce);
804
+
805
+ let strat = document.getElementById('server-perf-strategy-select');
806
+ if (strat) {
807
+ params.append('a2_performance_strategy', strat.value);
808
+ }
809
+
810
+ let that = this;
811
+ axios
812
+ .post(ajax.url, params)
813
+ .catch((error) => {
814
+ alert('There was a problem getting benchmark data. See console log.');
815
+ console.log(error.message);
816
+ page_data.closeModal();
817
+ })
818
+ .then((response) => {
819
+ if (run_checks) {
820
+ page_data.last_check_date = 'just now';
821
+ } else {
822
+ page_data.last_check_date = response.data.overall_score.last_check_date;
823
+ }
824
+ if (page == 'hosting-matchup') {
825
+ page_data.graphs = response.data.graphs;
826
+ page_data.graph_data = response.data.graph_data;
827
+
828
+ that.$root.$emit('render_hosting_matchup_graphs');
829
+ } else {
830
+ page_data.graphs = response.data;
831
+ }
832
+ page_data.updateView++;
833
+ page_data.closeModal();
834
+ });
835
+ },
836
+ promptForAction(header, message, yesAction = null, noAction = null) {
837
+ if (!yesAction) {
838
+ return; // no point calling this with no action to do, for now
839
+ }
840
+ page_data.yesNoDialog.header = header;
841
+ page_data.yesNoDialog.message = message;
842
+ page_data.yesNoDialog.yesAction = yesAction;
843
+ if (noAction) {
844
+ page_data.yesNoDialog.noAction = noAction;
845
+ }
846
+
847
+ page_data.yesNoDialog.showYesNo = true;
848
+ },
849
+ loadSubPage(page){
850
+ let base_url = 'admin.php?page=a2-optimized&a2_page=';
851
+ window.location.href = base_url + page;
852
+ }
853
+ }
854
+ });
assets/js/admin/axios.js ADDED
@@ -0,0 +1,1603 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* axios v0.18.0 | (c) 2018 by Matt Zabriskie */
2
+ (function webpackUniversalModuleDefinition(root, factory) {
3
+ if(typeof exports === 'object' && typeof module === 'object')
4
+ module.exports = factory();
5
+ else if(typeof define === 'function' && define.amd)
6
+ define([], factory);
7
+ else if(typeof exports === 'object')
8
+ exports["axios"] = factory();
9
+ else
10
+ root["axios"] = factory();
11
+ })(this, function() {
12
+ return /******/ (function(modules) { // webpackBootstrap
13
+ /******/ // The module cache
14
+ /******/ var installedModules = {};
15
+ /******/
16
+ /******/ // The require function
17
+ /******/ function __webpack_require__(moduleId) {
18
+ /******/
19
+ /******/ // Check if module is in cache
20
+ /******/ if(installedModules[moduleId])
21
+ /******/ return installedModules[moduleId].exports;
22
+ /******/
23
+ /******/ // Create a new module (and put it into the cache)
24
+ /******/ var module = installedModules[moduleId] = {
25
+ /******/ exports: {},
26
+ /******/ id: moduleId,
27
+ /******/ loaded: false
28
+ /******/ };
29
+ /******/
30
+ /******/ // Execute the module function
31
+ /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
32
+ /******/
33
+ /******/ // Flag the module as loaded
34
+ /******/ module.loaded = true;
35
+ /******/
36
+ /******/ // Return the exports of the module
37
+ /******/ return module.exports;
38
+ /******/ }
39
+ /******/
40
+ /******/
41
+ /******/ // expose the modules object (__webpack_modules__)
42
+ /******/ __webpack_require__.m = modules;
43
+ /******/
44
+ /******/ // expose the module cache
45
+ /******/ __webpack_require__.c = installedModules;
46
+ /******/
47
+ /******/ // __webpack_public_path__
48
+ /******/ __webpack_require__.p = "";
49
+ /******/
50
+ /******/ // Load entry module and return exports
51
+ /******/ return __webpack_require__(0);
52
+ /******/ })
53
+ /************************************************************************/
54
+ /******/ ([
55
+ /* 0 */
56
+ /***/ (function(module, exports, __webpack_require__) {
57
+
58
+ module.exports = __webpack_require__(1);
59
+
60
+ /***/ }),
61
+ /* 1 */
62
+ /***/ (function(module, exports, __webpack_require__) {
63
+
64
+ 'use strict';
65
+
66
+ var utils = __webpack_require__(2);
67
+ var bind = __webpack_require__(3);
68
+ var Axios = __webpack_require__(5);
69
+ var defaults = __webpack_require__(6);
70
+
71
+ /**
72
+ * Create an instance of Axios
73
+ *
74
+ * @param {Object} defaultConfig The default config for the instance
75
+ * @return {Axios} A new instance of Axios
76
+ */
77
+ function createInstance(defaultConfig) {
78
+ var context = new Axios(defaultConfig);
79
+ var instance = bind(Axios.prototype.request, context);
80
+
81
+ // Copy axios.prototype to instance
82
+ utils.extend(instance, Axios.prototype, context);
83
+
84
+ // Copy context to instance
85
+ utils.extend(instance, context);
86
+
87
+ return instance;
88
+ }
89
+
90
+ // Create the default instance to be exported
91
+ var axios = createInstance(defaults);
92
+
93
+ // Expose Axios class to allow class inheritance
94
+ axios.Axios = Axios;
95
+
96
+ // Factory for creating new instances
97
+ axios.create = function create(instanceConfig) {
98
+ return createInstance(utils.merge(defaults, instanceConfig));
99
+ };
100
+
101
+ // Expose Cancel & CancelToken
102
+ axios.Cancel = __webpack_require__(23);
103
+ axios.CancelToken = __webpack_require__(24);
104
+ axios.isCancel = __webpack_require__(20);
105
+
106
+ // Expose all/spread
107
+ axios.all = function all(promises) {
108
+ return Promise.all(promises);
109
+ };
110
+ axios.spread = __webpack_require__(25);
111
+
112
+ module.exports = axios;
113
+
114
+ // Allow use of default import syntax in TypeScript
115
+ module.exports.default = axios;
116
+
117
+
118
+ /***/ }),
119
+ /* 2 */
120
+ /***/ (function(module, exports, __webpack_require__) {
121
+
122
+ 'use strict';
123
+
124
+ var bind = __webpack_require__(3);
125
+ var isBuffer = __webpack_require__(4);
126
+
127
+ /*global toString:true*/
128
+
129
+ // utils is a library of generic helper functions non-specific to axios
130
+
131
+ var toString = Object.prototype.toString;
132
+
133
+ /**
134
+ * Determine if a value is an Array
135
+ *
136
+ * @param {Object} val The value to test
137
+ * @returns {boolean} True if value is an Array, otherwise false
138
+ */
139
+ function isArray(val) {
140
+ return toString.call(val) === '[object Array]';
141
+ }
142
+
143
+ /**
144
+ * Determine if a value is an ArrayBuffer
145
+ *
146
+ * @param {Object} val The value to test
147
+ * @returns {boolean} True if value is an ArrayBuffer, otherwise false
148
+ */
149
+ function isArrayBuffer(val) {
150
+ return toString.call(val) === '[object ArrayBuffer]';
151
+ }
152
+
153
+ /**
154
+ * Determine if a value is a FormData
155
+ *
156
+ * @param {Object} val The value to test
157
+ * @returns {boolean} True if value is an FormData, otherwise false
158
+ */
159
+ function isFormData(val) {
160
+ return (typeof FormData !== 'undefined') && (val instanceof FormData);
161
+ }
162
+
163
+ /**
164
+ * Determine if a value is a view on an ArrayBuffer
165
+ *
166
+ * @param {Object} val The value to test
167
+ * @returns {boolean} True if value is a view on an ArrayBuffer, otherwise false
168
+ */
169
+ function isArrayBufferView(val) {
170
+ var result;
171
+ if ((typeof ArrayBuffer !== 'undefined') && (ArrayBuffer.isView)) {
172
+ result = ArrayBuffer.isView(val);
173
+ } else {
174
+ result = (val) && (val.buffer) && (val.buffer instanceof ArrayBuffer);
175
+ }
176
+ return result;
177
+ }
178
+
179
+ /**
180
+ * Determine if a value is a String
181
+ *
182
+ * @param {Object} val The value to test
183
+ * @returns {boolean} True if value is a String, otherwise false
184
+ */
185
+ function isString(val) {
186
+ return typeof val === 'string';
187
+ }
188
+
189
+ /**
190
+ * Determine if a value is a Number
191
+ *
192
+ * @param {Object} val The value to test
193
+ * @returns {boolean} True if value is a Number, otherwise false
194
+ */
195
+ function isNumber(val) {
196
+ return typeof val === 'number';
197
+ }
198
+
199
+ /**
200
+ * Determine if a value is undefined
201
+ *
202
+ * @param {Object} val The value to test
203
+ * @returns {boolean} True if the value is undefined, otherwise false
204
+ */
205
+ function isUndefined(val) {
206
+ return typeof val === 'undefined';
207
+ }
208
+
209
+ /**
210
+ * Determine if a value is an Object
211
+ *
212
+ * @param {Object} val The value to test
213
+ * @returns {boolean} True if value is an Object, otherwise false
214
+ */
215
+ function isObject(val) {
216
+ return val !== null && typeof val === 'object';
217
+ }
218
+
219
+ /**
220
+ * Determine if a value is a Date
221
+ *
222
+ * @param {Object} val The value to test
223
+ * @returns {boolean} True if value is a Date, otherwise false
224
+ */
225
+ function isDate(val) {
226
+ return toString.call(val) === '[object Date]';
227
+ }
228
+
229
+ /**
230
+ * Determine if a value is a File
231
+ *
232
+ * @param {Object} val The value to test
233
+ * @returns {boolean} True if value is a File, otherwise false
234
+ */
235
+ function isFile(val) {
236
+ return toString.call(val) === '[object File]';
237
+ }
238
+
239
+ /**
240
+ * Determine if a value is a Blob
241
+ *
242
+ * @param {Object} val The value to test
243
+ * @returns {boolean} True if value is a Blob, otherwise false
244
+ */
245
+ function isBlob(val) {
246
+ return toString.call(val) === '[object Blob]';
247
+ }
248
+
249
+ /**
250
+ * Determine if a value is a Function
251
+ *
252
+ * @param {Object} val The value to test
253
+ * @returns {boolean} True if value is a Function, otherwise false
254
+ */
255
+ function isFunction(val) {
256
+ return toString.call(val) === '[object Function]';
257
+ }
258
+
259
+ /**
260
+ * Determine if a value is a Stream
261
+ *
262
+ * @param {Object} val The value to test
263
+ * @returns {boolean} True if value is a Stream, otherwise false
264
+ */
265
+ function isStream(val) {
266
+ return isObject(val) && isFunction(val.pipe);
267
+ }
268
+
269
+ /**
270
+ * Determine if a value is a URLSearchParams object
271
+ *
272
+ * @param {Object} val The value to test
273
+ * @returns {boolean} True if value is a URLSearchParams object, otherwise false
274
+ */
275
+ function isURLSearchParams(val) {
276
+ return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams;
277
+ }
278
+
279
+ /**
280
+ * Trim excess whitespace off the beginning and end of a string
281
+ *
282
+ * @param {String} str The String to trim
283
+ * @returns {String} The String freed of excess whitespace
284
+ */
285
+ function trim(str) {
286
+ return str.replace(/^\s*/, '').replace(/\s*$/, '');
287
+ }
288
+
289
+ /**
290
+ * Determine if we're running in a standard browser environment
291
+ *
292
+ * This allows axios to run in a web worker, and react-native.
293
+ * Both environments support XMLHttpRequest, but not fully standard globals.
294
+ *
295
+ * web workers:
296
+ * typeof window -> undefined
297
+ * typeof document -> undefined
298
+ *
299
+ * react-native:
300
+ * navigator.product -> 'ReactNative'
301
+ */
302
+ function isStandardBrowserEnv() {
303
+ if (typeof navigator !== 'undefined' && navigator.product === 'ReactNative') {
304
+ return false;
305
+ }
306
+ return (
307
+ typeof window !== 'undefined' &&
308
+ typeof document !== 'undefined'
309
+ );
310
+ }
311
+
312
+ /**
313
+ * Iterate over an Array or an Object invoking a function for each item.
314
+ *
315
+ * If `obj` is an Array callback will be called passing
316
+ * the value, index, and complete array for each item.
317
+ *
318
+ * If 'obj' is an Object callback will be called passing
319
+ * the value, key, and complete object for each property.
320
+ *
321
+ * @param {Object|Array} obj The object to iterate
322
+ * @param {Function} fn The callback to invoke for each item
323
+ */
324
+ function forEach(obj, fn) {
325
+ // Don't bother if no value provided
326
+ if (obj === null || typeof obj === 'undefined') {
327
+ return;
328
+ }
329
+
330
+ // Force an array if not already something iterable
331
+ if (typeof obj !== 'object') {
332
+ /*eslint no-param-reassign:0*/
333
+ obj = [obj];
334
+ }
335
+
336
+ if (isArray(obj)) {
337
+ // Iterate over array values
338
+ for (var i = 0, l = obj.length; i < l; i++) {
339
+ fn.call(null, obj[i], i, obj);
340
+ }
341
+ } else {
342
+ // Iterate over object keys
343
+ for (var key in obj) {
344
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
345
+ fn.call(null, obj[key], key, obj);
346
+ }
347
+ }
348
+ }
349
+ }
350
+
351
+ /**
352
+ * Accepts varargs expecting each argument to be an object, then
353
+ * immutably merges the properties of each object and returns result.
354
+ *
355
+ * When multiple objects contain the same key the later object in
356
+ * the arguments list will take precedence.
357
+ *
358
+ * Example:
359
+ *
360
+ * ```js
361
+ * var result = merge({foo: 123}, {foo: 456});
362
+ * console.log(result.foo); // outputs 456
363
+ * ```
364
+ *
365
+ * @param {Object} obj1 Object to merge
366
+ * @returns {Object} Result of all merge properties
367
+ */
368
+ function merge(/* obj1, obj2, obj3, ... */) {
369
+ var result = {};
370
+ function assignValue(val, key) {
371
+ if (typeof result[key] === 'object' && typeof val === 'object') {
372
+ result[key] = merge(result[key], val);
373
+ } else {
374
+ result[key] = val;
375
+ }
376
+ }
377
+
378
+ for (var i = 0, l = arguments.length; i < l; i++) {
379
+ forEach(arguments[i], assignValue);
380
+ }
381
+ return result;
382
+ }
383
+
384
+ /**
385
+ * Extends object a by mutably adding to it the properties of object b.
386
+ *
387
+ * @param {Object} a The object to be extended
388
+ * @param {Object} b The object to copy properties from
389
+ * @param {Object} thisArg The object to bind function to
390
+ * @return {Object} The resulting value of object a
391
+ */
392
+ function extend(a, b, thisArg) {
393
+ forEach(b, function assignValue(val, key) {
394
+ if (thisArg && typeof val === 'function') {
395
+ a[key] = bind(val, thisArg);
396
+ } else {
397
+ a[key] = val;
398
+ }
399
+ });
400
+ return a;
401
+ }
402
+
403
+ module.exports = {
404
+ isArray: isArray,
405
+ isArrayBuffer: isArrayBuffer,
406
+ isBuffer: isBuffer,
407
+ isFormData: isFormData,
408
+ isArrayBufferView: isArrayBufferView,
409
+ isString: isString,
410
+ isNumber: isNumber,
411
+ isObject: isObject,
412
+ isUndefined: isUndefined,
413
+ isDate: isDate,
414
+ isFile: isFile,
415
+ isBlob: isBlob,
416
+ isFunction: isFunction,
417
+ isStream: isStream,
418
+ isURLSearchParams: isURLSearchParams,
419
+ isStandardBrowserEnv: isStandardBrowserEnv,
420
+ forEach: forEach,
421
+ merge: merge,
422
+ extend: extend,
423
+ trim: trim
424
+ };
425
+
426
+
427
+ /***/ }),
428
+ /* 3 */
429
+ /***/ (function(module, exports) {
430
+
431
+ 'use strict';
432
+
433
+ module.exports = function bind(fn, thisArg) {
434
+ return function wrap() {
435
+ var args = new Array(arguments.length);
436
+ for (var i = 0; i < args.length; i++) {
437
+ args[i] = arguments[i];
438
+ }
439
+ return fn.apply(thisArg, args);
440
+ };
441
+ };
442
+
443
+
444
+ /***/ }),
445
+ /* 4 */
446
+ /***/ (function(module, exports) {
447
+
448
+ /*!
449
+ * Determine if an object is a Buffer
450
+ *
451
+ * @author Feross Aboukhadijeh <https://feross.org>
452
+ * @license MIT
453
+ */
454
+
455
+ // The _isBuffer check is for Safari 5-7 support, because it's missing
456
+ // Object.prototype.constructor. Remove this eventually
457
+ module.exports = function (obj) {
458
+ return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer)
459
+ }
460
+
461
+ function isBuffer (obj) {
462
+ return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj)
463
+ }
464
+
465
+ // For Node v0.10 support. Remove this eventually.
466
+ function isSlowBuffer (obj) {
467
+ return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0))
468
+ }
469
+
470
+
471
+ /***/ }),
472
+ /* 5 */
473
+ /***/ (function(module, exports, __webpack_require__) {
474
+
475
+ 'use strict';
476
+
477
+ var defaults = __webpack_require__(6);
478
+ var utils = __webpack_require__(2);
479
+ var InterceptorManager = __webpack_require__(17);
480
+ var dispatchRequest = __webpack_require__(18);
481
+
482
+ /**
483
+ * Create a new instance of Axios
484
+ *
485
+ * @param {Object} instanceConfig The default config for the instance
486
+ */
487
+ function Axios(instanceConfig) {
488
+ this.defaults = instanceConfig;
489
+ this.interceptors = {
490
+ request: new InterceptorManager(),
491
+ response: new InterceptorManager()
492
+ };
493
+ }
494
+
495
+ /**
496
+ * Dispatch a request
497
+ *
498
+ * @param {Object} config The config specific for this request (merged with this.defaults)
499
+ */
500
+ Axios.prototype.request = function request(config) {
501
+ /*eslint no-param-reassign:0*/
502
+ // Allow for axios('example/url'[, config]) a la fetch API
503
+ if (typeof config === 'string') {
504
+ config = utils.merge({
505
+ url: arguments[0]
506
+ }, arguments[1]);
507
+ }
508
+
509
+ config = utils.merge(defaults, {method: 'get'}, this.defaults, config);
510
+ config.method = config.method.toLowerCase();
511
+
512
+ // Hook up interceptors middleware
513
+ var chain = [dispatchRequest, undefined];
514
+ var promise = Promise.resolve(config);
515
+
516
+ this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
517
+ chain.unshift(interceptor.fulfilled, interceptor.rejected);
518
+ });
519
+
520
+ this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
521
+ chain.push(interceptor.fulfilled, interceptor.rejected);
522
+ });
523
+
524
+ while (chain.length) {
525
+ promise = promise.then(chain.shift(), chain.shift());
526
+ }
527
+
528
+ return promise;
529
+ };
530
+
531
+ // Provide aliases for supported request methods
532
+ utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) {
533
+ /*eslint func-names:0*/
534
+ Axios.prototype[method] = function(url, config) {
535
+ return this.request(utils.merge(config || {}, {
536
+ method: method,
537
+ url: url
538
+ }));
539
+ };
540
+ });
541
+
542
+ utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
543
+ /*eslint func-names:0*/
544
+ Axios.prototype[method] = function(url, data, config) {
545
+ return this.request(utils.merge(config || {}, {
546
+ method: method,
547
+ url: url,
548
+ data: data
549
+ }));
550
+ };
551
+ });
552
+
553
+ module.exports = Axios;
554
+
555
+
556
+ /***/ }),
557
+ /* 6 */
558
+ /***/ (function(module, exports, __webpack_require__) {
559
+
560
+ 'use strict';
561
+
562
+ var utils = __webpack_require__(2);
563
+ var normalizeHeaderName = __webpack_require__(7);
564
+
565
+ var DEFAULT_CONTENT_TYPE = {
566
+ 'Content-Type': 'application/x-www-form-urlencoded'
567
+ };
568
+
569
+ function setContentTypeIfUnset(headers, value) {
570
+ if (!utils.isUndefined(headers) && utils.isUndefined(headers['Content-Type'])) {
571
+ headers['Content-Type'] = value;
572
+ }
573
+ }
574
+
575
+ function getDefaultAdapter() {
576
+ var adapter;
577
+ if (typeof XMLHttpRequest !== 'undefined') {
578
+ // For browsers use XHR adapter
579
+ adapter = __webpack_require__(8);
580
+ } else if (typeof process !== 'undefined') {
581
+ // For node use HTTP adapter
582
+ adapter = __webpack_require__(8);
583
+ }
584
+ return adapter;
585
+ }
586
+
587
+ var defaults = {
588
+ adapter: getDefaultAdapter(),
589
+
590
+ transformRequest: [function transformRequest(data, headers) {
591
+ normalizeHeaderName(headers, 'Content-Type');
592
+ if (utils.isFormData(data) ||
593
+ utils.isArrayBuffer(data) ||
594
+ utils.isBuffer(data) ||
595
+ utils.isStream(data) ||
596
+ utils.isFile(data) ||
597
+ utils.isBlob(data)
598
+ ) {
599
+ return data;
600
+ }
601
+ if (utils.isArrayBufferView(data)) {
602
+ return data.buffer;
603
+ }
604
+ if (utils.isURLSearchParams(data)) {
605
+ setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8');
606
+ return data.toString();
607
+ }
608
+ if (utils.isObject(data)) {
609
+ setContentTypeIfUnset(headers, 'application/json;charset=utf-8');
610
+ return JSON.stringify(data);
611
+ }
612
+ return data;
613
+ }],
614
+
615
+ transformResponse: [function transformResponse(data) {
616
+ /*eslint no-param-reassign:0*/
617
+ if (typeof data === 'string') {
618
+ try {
619
+ data = JSON.parse(data);
620
+ } catch (e) { /* Ignore */ }
621
+ }
622
+ return data;
623
+ }],
624
+
625
+ /**
626
+ * A timeout in milliseconds to abort a request. If set to 0 (default) a
627
+ * timeout is not created.
628
+ */
629
+ timeout: 0,
630
+
631
+ xsrfCookieName: 'XSRF-TOKEN',
632
+ xsrfHeaderName: 'X-XSRF-TOKEN',
633
+
634
+ maxContentLength: -1,
635
+
636
+ validateStatus: function validateStatus(status) {
637
+ return status >= 200 && status < 300;
638
+ }
639
+ };
640
+
641
+ defaults.headers = {
642
+ common: {
643
+ 'Accept': 'application/json, text/plain, */*'
644
+ }
645
+ };
646
+
647
+ utils.forEach(['delete', 'get', 'head'], function forEachMethodNoData(method) {
648
+ defaults.headers[method] = {};
649
+ });
650
+
651
+ utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
652
+ defaults.headers[method] = utils.merge(DEFAULT_CONTENT_TYPE);
653
+ });
654
+
655
+ module.exports = defaults;
656
+
657
+
658
+ /***/ }),
659
+ /* 7 */
660
+ /***/ (function(module, exports, __webpack_require__) {
661
+
662
+ 'use strict';
663
+
664
+ var utils = __webpack_require__(2);
665
+
666
+ module.exports = function normalizeHeaderName(headers, normalizedName) {
667
+ utils.forEach(headers, function processHeader(value, name) {
668
+ if (name !== normalizedName && name.toUpperCase() === normalizedName.toUpperCase()) {
669
+ headers[normalizedName] = value;
670
+ delete headers[name];
671
+ }
672
+ });
673
+ };
674
+
675
+
676
+ /***/ }),
677
+ /* 8 */
678
+ /***/ (function(module, exports, __webpack_require__) {
679
+
680
+ 'use strict';
681
+
682
+ var utils = __webpack_require__(2);
683
+ var settle = __webpack_require__(9);
684
+ var buildURL = __webpack_require__(12);
685
+ var parseHeaders = __webpack_require__(13);
686
+ var isURLSameOrigin = __webpack_require__(14);
687
+ var createError = __webpack_require__(10);
688
+ var btoa = (typeof window !== 'undefined' && window.btoa && window.btoa.bind(window)) || __webpack_require__(15);
689
+
690
+ module.exports = function xhrAdapter(config) {
691
+ return new Promise(function dispatchXhrRequest(resolve, reject) {
692
+ var requestData = config.data;
693
+ var requestHeaders = config.headers;
694
+
695
+ if (utils.isFormData(requestData)) {
696
+ delete requestHeaders['Content-Type']; // Let the browser set it
697
+ }
698
+
699
+ var request = new XMLHttpRequest();
700
+ var loadEvent = 'onreadystatechange';
701
+ var xDomain = false;
702
+
703
+ // For IE 8/9 CORS support
704
+ // Only supports POST and GET calls and doesn't returns the response headers.
705
+ // DON'T do this for testing b/c XMLHttpRequest is mocked, not XDomainRequest.
706
+ if (("production") !== 'test' &&
707
+ typeof window !== 'undefined' &&
708
+ window.XDomainRequest && !('withCredentials' in request) &&
709
+ !isURLSameOrigin(config.url)) {
710
+ request = new window.XDomainRequest();
711
+ loadEvent = 'onload';
712
+ xDomain = true;
713
+ request.onprogress = function handleProgress() {};
714
+ request.ontimeout = function handleTimeout() {};
715
+ }
716
+
717
+ // HTTP basic authentication
718
+ if (config.auth) {
719
+ var username = config.auth.username || '';
720
+ var password = config.auth.password || '';
721
+ requestHeaders.Authorization = 'Basic ' + btoa(username + ':' + password);
722
+ }
723
+
724
+ request.open(config.method.toUpperCase(), buildURL(config.url, config.params, config.paramsSerializer), true);
725
+
726
+ // Set the request timeout in MS
727
+ request.timeout = config.timeout;
728
+
729
+ // Listen for ready state
730
+ request[loadEvent] = function handleLoad() {
731
+ if (!request || (request.readyState !== 4 && !xDomain)) {
732
+ return;
733
+ }
734
+
735
+ // The request errored out and we didn't get a response, this will be
736
+ // handled by onerror instead
737
+ // With one exception: request that using file: protocol, most browsers
738
+ // will return status as 0 even though it's a successful request
739
+ if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) {
740
+ return;
741
+ }
742
+
743
+ // Prepare the response
744
+ var responseHeaders = 'getAllResponseHeaders' in request ? parseHeaders(request.getAllResponseHeaders()) : null;
745
+ var responseData = !config.responseType || config.responseType === 'text' ? request.responseText : request.response;
746
+ var response = {
747
+ data: responseData,
748
+ // IE sends 1223 instead of 204 (https://github.com/axios/axios/issues/201)
749
+ status: request.status === 1223 ? 204 : request.status,
750
+ statusText: request.status === 1223 ? 'No Content' : request.statusText,
751
+ headers: responseHeaders,
752
+ config: config,
753
+ request: request
754
+ };
755
+
756
+ settle(resolve, reject, response);
757
+
758
+ // Clean up request
759
+ request = null;
760
+ };
761
+
762
+ // Handle low level network errors
763
+ request.onerror = function handleError() {
764
+ // Real errors are hidden from us by the browser
765
+ // onerror should only fire if it's a network error
766
+ reject(createError('Network Error', config, null, request));
767
+
768
+ // Clean up request
769
+ request = null;
770
+ };
771
+
772
+ // Handle timeout
773
+ request.ontimeout = function handleTimeout() {
774
+ reject(createError('timeout of ' + config.timeout + 'ms exceeded', config, 'ECONNABORTED',
775
+ request));
776
+
777
+ // Clean up request
778
+ request = null;
779
+ };
780
+
781
+ // Add xsrf header
782
+ // This is only done if running in a standard browser environment.
783
+ // Specifically not if we're in a web worker, or react-native.
784
+ if (utils.isStandardBrowserEnv()) {
785
+ var cookies = __webpack_require__(16);
786
+
787
+ // Add xsrf header
788
+ var xsrfValue = (config.withCredentials || isURLSameOrigin(config.url)) && config.xsrfCookieName ?
789
+ cookies.read(config.xsrfCookieName) :
790
+ undefined;
791
+
792
+ if (xsrfValue) {
793
+ requestHeaders[config.xsrfHeaderName] = xsrfValue;
794
+ }
795
+ }
796
+
797
+ // Add headers to the request
798
+ if ('setRequestHeader' in request) {
799
+ utils.forEach(requestHeaders, function setRequestHeader(val, key) {
800
+ if (typeof requestData === 'undefined' && key.toLowerCase() === 'content-type') {
801
+ // Remove Content-Type if data is undefined
802
+ delete requestHeaders[key];
803
+ } else {
804
+ // Otherwise add header to the request
805
+ request.setRequestHeader(key, val);
806
+ }
807
+ });
808
+ }
809
+
810
+ // Add withCredentials to request if needed
811
+ if (config.withCredentials) {
812
+ request.withCredentials = true;
813
+ }
814
+
815
+ // Add responseType to request if needed
816
+ if (config.responseType) {
817
+ try {
818
+ request.responseType = config.responseType;
819
+ } catch (e) {
820
+ // Expected DOMException thrown by browsers not compatible XMLHttpRequest Level 2.
821
+ // But, this can be suppressed for 'json' type as it can be parsed by default 'transformResponse' function.
822
+ if (config.responseType !== 'json') {
823
+ throw e;
824
+ }
825
+ }
826
+ }
827
+
828
+ // Handle progress if needed
829
+ if (typeof config.onDownloadProgress === 'function') {
830
+ request.addEventListener('progress', config.onDownloadProgress);
831
+ }
832
+
833
+ // Not all browsers support upload events
834
+ if (typeof config.onUploadProgress === 'function' && request.upload) {
835
+ request.upload.addEventListener('progress', config.onUploadProgress);
836
+ }
837
+
838
+ if (config.cancelToken) {
839
+ // Handle cancellation
840
+ config.cancelToken.promise.then(function onCanceled(cancel) {
841
+ if (!request) {
842
+ return;
843
+ }
844
+
845
+ request.abort();
846
+ reject(cancel);
847
+ // Clean up request
848
+ request = null;
849
+ });
850
+ }
851
+
852
+ if (requestData === undefined) {
853
+ requestData = null;
854
+ }
855
+
856
+ // Send the request
857
+ request.send(requestData);
858
+ });
859
+ };
860
+
861
+
862
+ /***/ }),
863
+ /* 9 */
864
+ /***/ (function(module, exports, __webpack_require__) {
865
+
866
+ 'use strict';
867
+
868
+ var createError = __webpack_require__(10);
869
+
870
+ /**
871
+ * Resolve or reject a Promise based on response status.
872
+ *
873
+ * @param {Function} resolve A function that resolves the promise.
874
+ * @param {Function} reject A function that rejects the promise.
875
+ * @param {object} response The response.
876
+ */
877
+ module.exports = function settle(resolve, reject, response) {
878
+ var validateStatus = response.config.validateStatus;
879
+ // Note: status is not exposed by XDomainRequest
880
+ if (!response.status || !validateStatus || validateStatus(response.status)) {
881
+ resolve(response);
882
+ } else {
883
+ reject(createError(
884
+ 'Request failed with status code ' + response.status,
885
+ response.config,
886
+ null,
887
+ response.request,
888
+ response
889
+ ));
890
+ }
891
+ };
892
+
893
+
894
+ /***/ }),
895
+ /* 10 */
896
+ /***/ (function(module, exports, __webpack_require__) {
897
+
898
+ 'use strict';
899
+
900
+ var enhanceError = __webpack_require__(11);
901
+
902
+ /**
903
+ * Create an Error with the specified message, config, error code, request and response.
904
+ *
905
+ * @param {string} message The error message.
906
+ * @param {Object} config The config.
907
+ * @param {string} [code] The error code (for example, 'ECONNABORTED').
908
+ * @param {Object} [request] The request.
909
+ * @param {Object} [response] The response.
910
+ * @returns {Error} The created error.
911
+ */
912
+ module.exports = function createError(message, config, code, request, response) {
913
+ var error = new Error(message);
914
+ return enhanceError(error, config, code, request, response);
915
+ };
916
+
917
+
918
+ /***/ }),
919
+ /* 11 */
920
+ /***/ (function(module, exports) {
921
+
922
+ 'use strict';
923
+
924
+ /**
925
+ * Update an Error with the specified config, error code, and response.
926
+ *
927
+ * @param {Error} error The error to update.
928
+ * @param {Object} config The config.
929
+ * @param {string} [code] The error code (for example, 'ECONNABORTED').
930
+ * @param {Object} [request] The request.
931
+ * @param {Object} [response] The response.
932
+ * @returns {Error} The error.
933
+ */
934
+ module.exports = function enhanceError(error, config, code, request, response) {
935
+ error.config = config;
936
+ if (code) {
937
+ error.code = code;
938
+ }
939
+ error.request = request;
940
+ error.response = response;
941
+ return error;
942
+ };
943
+
944
+
945
+ /***/ }),
946
+ /* 12 */
947
+ /***/ (function(module, exports, __webpack_require__) {
948
+
949
+ 'use strict';
950
+
951
+ var utils = __webpack_require__(2);
952
+
953
+ function encode(val) {
954
+ return encodeURIComponent(val).
955
+ replace(/%40/gi, '@').
956
+ replace(/%3A/gi, ':').
957
+ replace(/%24/g, '$').
958
+ replace(/%2C/gi, ',').
959
+ replace(/%20/g, '+').
960
+ replace(/%5B/gi, '[').
961
+ replace(/%5D/gi, ']');
962
+ }
963
+
964
+ /**
965
+ * Build a URL by appending params to the end
966
+ *
967
+ * @param {string} url The base of the url (e.g., http://www.google.com)
968
+ * @param {object} [params] The params to be appended
969
+ * @returns {string} The formatted url
970
+ */
971
+ module.exports = function buildURL(url, params, paramsSerializer) {
972
+ /*eslint no-param-reassign:0*/
973
+ if (!params) {
974
+ return url;
975
+ }
976
+
977
+ var serializedParams;
978
+ if (paramsSerializer) {
979
+ serializedParams = paramsSerializer(params);
980
+ } else if (utils.isURLSearchParams(params)) {
981
+ serializedParams = params.toString();
982
+ } else {
983
+ var parts = [];
984
+
985
+ utils.forEach(params, function serialize(val, key) {
986
+ if (val === null || typeof val === 'undefined') {
987
+ return;
988
+ }
989
+
990
+ if (utils.isArray(val)) {
991
+ key = key + '[]';
992
+ } else {
993
+ val = [val];
994
+ }
995
+
996
+ utils.forEach(val, function parseValue(v) {
997
+ if (utils.isDate(v)) {
998
+ v = v.toISOString();
999
+ } else if (utils.isObject(v)) {
1000
+ v = JSON.stringify(v);
1001
+ }
1002
+ parts.push(encode(key) + '=' + encode(v));
1003
+ });
1004
+ });
1005
+
1006
+ serializedParams = parts.join('&');
1007
+ }
1008
+
1009
+ if (serializedParams) {
1010
+ url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams;
1011
+ }
1012
+
1013
+ return url;
1014
+ };
1015
+
1016
+
1017
+ /***/ }),
1018
+ /* 13 */
1019
+ /***/ (function(module, exports, __webpack_require__) {
1020
+
1021
+ 'use strict';
1022
+
1023
+ var utils = __webpack_require__(2);
1024
+
1025
+ // Headers whose duplicates are ignored by node
1026
+ // c.f. https://nodejs.org/api/http.html#http_message_headers
1027
+ var ignoreDuplicateOf = [
1028
+ 'age', 'authorization', 'content-length', 'content-type', 'etag',
1029
+ 'expires', 'from', 'host', 'if-modified-since', 'if-unmodified-since',
1030
+ 'last-modified', 'location', 'max-forwards', 'proxy-authorization',
1031
+ 'referer', 'retry-after', 'user-agent'
1032
+ ];
1033
+
1034
+ /**
1035
+ * Parse headers into an object
1036
+ *
1037
+ * ```
1038
+ * Date: Wed, 27 Aug 2014 08:58:49 GMT
1039
+ * Content-Type: application/json
1040
+ * Connection: keep-alive
1041
+ * Transfer-Encoding: chunked
1042
+ * ```
1043
+ *
1044
+ * @param {String} headers Headers needing to be parsed
1045
+ * @returns {Object} Headers parsed into an object
1046
+ */
1047
+ module.exports = function parseHeaders(headers) {
1048
+ var parsed = {};
1049
+ var key;
1050
+ var val;
1051
+ var i;
1052
+
1053
+ if (!headers) { return parsed; }
1054
+
1055
+ utils.forEach(headers.split('\n'), function parser(line) {
1056
+ i = line.indexOf(':');
1057
+ key = utils.trim(line.substr(0, i)).toLowerCase();
1058
+ val = utils.trim(line.substr(i + 1));
1059
+
1060
+ if (key) {
1061
+ if (parsed[key] && ignoreDuplicateOf.indexOf(key) >= 0) {
1062
+ return;
1063
+ }
1064
+ if (key === 'set-cookie') {
1065
+ parsed[key] = (parsed[key] ? parsed[key] : []).concat([val]);
1066
+ } else {
1067
+ parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;
1068
+ }
1069
+ }
1070
+ });
1071
+
1072
+ return parsed;
1073
+ };
1074
+
1075
+
1076
+ /***/ }),
1077
+ /* 14 */
1078
+ /***/ (function(module, exports, __webpack_require__) {
1079
+
1080
+ 'use strict';
1081
+
1082
+ var utils = __webpack_require__(2);
1083
+
1084
+ module.exports = (
1085
+ utils.isStandardBrowserEnv() ?
1086
+
1087
+ // Standard browser envs have full support of the APIs needed to test
1088
+ // whether the request URL is of the same origin as current location.
1089
+ (function standardBrowserEnv() {
1090
+ var msie = /(msie|trident)/i.test(navigator.userAgent);
1091
+ var urlParsingNode = document.createElement('a');
1092
+ var originURL;
1093
+
1094
+ /**
1095
+ * Parse a URL to discover it's components
1096
+ *
1097
+ * @param {String} url The URL to be parsed
1098
+ * @returns {Object}
1099
+ */
1100
+ function resolveURL(url) {
1101
+ var href = url;
1102
+
1103
+ if (msie) {
1104
+ // IE needs attribute set twice to normalize properties
1105
+ urlParsingNode.setAttribute('href', href);
1106
+ href = urlParsingNode.href;
1107
+ }
1108
+
1109
+ urlParsingNode.setAttribute('href', href);
1110
+
1111
+ // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils
1112
+ return {
1113
+ href: urlParsingNode.href,
1114
+ protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',
1115
+ host: urlParsingNode.host,
1116
+ search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '',
1117
+ hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',
1118
+ hostname: urlParsingNode.hostname,
1119
+ port: urlParsingNode.port,
1120
+ pathname: (urlParsingNode.pathname.charAt(0) === '/') ?
1121
+ urlParsingNode.pathname :
1122
+ '/' + urlParsingNode.pathname
1123
+ };
1124
+ }
1125
+
1126
+ originURL = resolveURL(window.location.href);
1127
+
1128
+ /**
1129
+ * Determine if a URL shares the same origin as the current location
1130
+ *
1131
+ * @param {String} requestURL The URL to test
1132
+ * @returns {boolean} True if URL shares the same origin, otherwise false
1133
+ */
1134
+ return function isURLSameOrigin(requestURL) {
1135
+ var parsed = (utils.isString(requestURL)) ? resolveURL(requestURL) : requestURL;
1136
+ return (parsed.protocol === originURL.protocol &&
1137
+ parsed.host === originURL.host);
1138
+ };
1139
+ })() :
1140
+
1141
+ // Non standard browser envs (web workers, react-native) lack needed support.
1142
+ (function nonStandardBrowserEnv() {
1143
+ return function isURLSameOrigin() {
1144
+ return true;
1145
+ };
1146
+ })()
1147
+ );
1148
+
1149
+
1150
+ /***/ }),
1151
+ /* 15 */
1152
+ /***/ (function(module, exports) {
1153
+
1154
+ 'use strict';
1155
+
1156
+ // btoa polyfill for IE<10 courtesy https://github.com/davidchambers/Base64.js
1157
+
1158
+ var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
1159
+
1160
+ function E() {
1161
+ this.message = 'String contains an invalid character';
1162
+ }
1163
+ E.prototype = new Error;
1164
+ E.prototype.code = 5;
1165
+ E.prototype.name = 'InvalidCharacterError';
1166
+
1167
+ function btoa(input) {
1168
+ var str = String(input);
1169
+ var output = '';
1170
+ for (
1171
+ // initialize result and counter
1172
+ var block, charCode, idx = 0, map = chars;
1173
+ // if the next str index does not exist:
1174
+ // change the mapping table to "="
1175
+ // check if d has no fractional digits
1176
+ str.charAt(idx | 0) || (map = '=', idx % 1);
1177
+ // "8 - idx % 1 * 8" generates the sequence 2, 4, 6, 8
1178
+ output += map.charAt(63 & block >> 8 - idx % 1 * 8)
1179
+ ) {
1180
+ charCode = str.charCodeAt(idx += 3 / 4);
1181
+ if (charCode > 0xFF) {
1182
+ throw new E();
1183
+ }
1184
+ block = block << 8 | charCode;
1185
+ }
1186
+ return output;
1187
+ }
1188
+
1189
+ module.exports = btoa;
1190
+
1191
+
1192
+ /***/ }),
1193
+ /* 16 */
1194
+ /***/ (function(module, exports, __webpack_require__) {
1195
+
1196
+ 'use strict';
1197
+
1198
+ var utils = __webpack_require__(2);
1199
+
1200
+ module.exports = (
1201
+ utils.isStandardBrowserEnv() ?
1202
+
1203
+ // Standard browser envs support document.cookie
1204
+ (function standardBrowserEnv() {
1205
+ return {
1206
+ write: function write(name, value, expires, path, domain, secure) {
1207
+ var cookie = [];
1208
+ cookie.push(name + '=' + encodeURIComponent(value));
1209
+
1210
+ if (utils.isNumber(expires)) {
1211
+ cookie.push('expires=' + new Date(expires).toGMTString());
1212
+ }
1213
+
1214
+ if (utils.isString(path)) {
1215
+ cookie.push('path=' + path);
1216
+ }
1217
+
1218
+ if (utils.isString(domain)) {
1219
+ cookie.push('domain=' + domain);
1220
+ }
1221
+
1222
+ if (secure === true) {
1223
+ cookie.push('secure');
1224
+ }
1225
+
1226
+ document.cookie = cookie.join('; ');
1227
+ },
1228
+
1229
+ read: function read(name) {
1230
+ var match = document.cookie.match(new RegExp('(^|;\\s*)(' + name + ')=([^;]*)'));
1231
+ return (match ? decodeURIComponent(match[3]) : null);
1232
+ },
1233
+
1234
+ remove: function remove(name) {
1235
+ this.write(name, '', Date.now() - 86400000);
1236
+ }
1237
+ };
1238
+ })() :
1239
+
1240
+ // Non standard browser env (web workers, react-native) lack needed support.
1241
+ (function nonStandardBrowserEnv() {
1242
+ return {
1243
+ write: function write() {},
1244
+ read: function read() { return null; },
1245
+ remove: function remove() {}
1246
+ };
1247
+ })()
1248
+ );
1249
+
1250
+
1251
+ /***/ }),
1252
+ /* 17 */
1253
+ /***/ (function(module, exports, __webpack_require__) {
1254
+
1255
+ 'use strict';
1256
+
1257
+ var utils = __webpack_require__(2);
1258
+
1259
+ function InterceptorManager() {
1260
+ this.handlers = [];
1261
+ }
1262
+
1263
+ /**
1264
+ * Add a new interceptor to the stack
1265
+ *
1266
+ * @param {Function} fulfilled The function to handle `then` for a `Promise`
1267
+ * @param {Function} rejected The function to handle `reject` for a `Promise`
1268
+ *
1269
+ * @return {Number} An ID used to remove interceptor later
1270
+ */
1271
+ InterceptorManager.prototype.use = function use(fulfilled, rejected) {
1272
+ this.handlers.push({
1273
+ fulfilled: fulfilled,
1274
+ rejected: rejected
1275
+ });
1276
+ return this.handlers.length - 1;
1277
+ };
1278
+
1279
+ /**
1280
+ * Remove an interceptor from the stack
1281
+ *
1282
+ * @param {Number} id The ID that was returned by `use`
1283
+ */
1284
+ InterceptorManager.prototype.eject = function eject(id) {
1285
+ if (this.handlers[id]) {
1286
+ this.handlers[id] = null;
1287
+ }
1288
+ };
1289
+
1290
+ /**
1291
+ * Iterate over all the registered interceptors
1292
+ *
1293
+ * This method is particularly useful for skipping over any
1294
+ * interceptors that may have become `null` calling `eject`.
1295
+ *
1296
+ * @param {Function} fn The function to call for each interceptor
1297
+ */
1298
+ InterceptorManager.prototype.forEach = function forEach(fn) {
1299
+ utils.forEach(this.handlers, function forEachHandler(h) {
1300
+ if (h !== null) {
1301
+ fn(h);
1302
+ }
1303
+ });
1304
+ };
1305
+
1306
+ module.exports = InterceptorManager;
1307
+
1308
+
1309
+ /***/ }),
1310
+ /* 18 */
1311
+ /***/ (function(module, exports, __webpack_require__) {
1312
+
1313
+ 'use strict';
1314
+
1315
+ var utils = __webpack_require__(2);
1316
+ var transformData = __webpack_require__(19);
1317
+ var isCancel = __webpack_require__(20);
1318
+ var defaults = __webpack_require__(6);
1319
+ var isAbsoluteURL = __webpack_require__(21);
1320
+ var combineURLs = __webpack_require__(22);
1321
+
1322
+ /**
1323
+ * Throws a `Cancel` if cancellation has been requested.
1324
+ */
1325
+ function throwIfCancellationRequested(config) {
1326
+ if (config.cancelToken) {
1327
+ config.cancelToken.throwIfRequested();
1328
+ }
1329
+ }
1330
+
1331
+ /**
1332
+ * Dispatch a request to the server using the configured adapter.
1333
+ *
1334
+ * @param {object} config The config that is to be used for the request
1335
+ * @returns {Promise} The Promise to be fulfilled
1336
+ */
1337
+ module.exports = function dispatchRequest(config) {
1338
+ throwIfCancellationRequested(config);
1339
+
1340
+ // Support baseURL config
1341
+ if (config.baseURL && !isAbsoluteURL(config.url)) {
1342
+ config.url = combineURLs(config.baseURL, config.url);
1343
+ }
1344
+
1345
+ // Ensure headers exist
1346
+ config.headers = config.headers || {};
1347
+
1348
+ // Transform request data
1349
+ config.data = transformData(
1350
+ config.data,
1351
+ config.headers,
1352
+ config.transformRequest
1353
+ );
1354
+
1355
+ // Flatten headers
1356
+ config.headers = utils.merge(
1357
+ config.headers.common || {},
1358
+ config.headers[config.method] || {},
1359
+ config.headers || {}
1360
+ );
1361
+
1362
+ utils.forEach(
1363
+ ['delete', 'get', 'head', 'post', 'put', 'patch', 'common'],
1364
+ function cleanHeaderConfig(method) {
1365
+ delete config.headers[method];
1366
+ }
1367
+ );
1368
+
1369
+ var adapter = config.adapter || defaults.adapter;
1370
+
1371
+ return adapter(config).then(function onAdapterResolution(response) {
1372
+ throwIfCancellationRequested(config);
1373
+
1374
+ // Transform response data
1375
+ response.data = transformData(
1376
+ response.data,
1377
+ response.headers,
1378
+ config.transformResponse
1379
+ );
1380
+
1381
+ return response;
1382
+ }, function onAdapterRejection(reason) {
1383
+ if (!isCancel(reason)) {
1384
+ throwIfCancellationRequested(config);
1385
+
1386
+ // Transform response data
1387
+ if (reason && reason.response) {
1388
+ reason.response.data = transformData(
1389
+ reason.response.data,
1390
+ reason.response.headers,
1391
+ config.transformResponse
1392
+ );
1393
+ }
1394
+ }
1395
+
1396
+ return Promise.reject(reason);
1397
+ });
1398
+ };
1399
+
1400
+
1401
+ /***/ }),
1402
+ /* 19 */
1403
+ /***/ (function(module, exports, __webpack_require__) {
1404
+
1405
+ 'use strict';
1406
+
1407
+ var utils = __webpack_require__(2);
1408
+
1409
+ /**
1410
+ * Transform the data for a request or a response
1411
+ *
1412
+ * @param {Object|String} data The data to be transformed
1413
+ * @param {Array} headers The headers for the request or response
1414
+ * @param {Array|Function} fns A single function or Array of functions
1415
+ * @returns {*} The resulting transformed data
1416
+ */
1417
+ module.exports = function transformData(data, headers, fns) {
1418
+ /*eslint no-param-reassign:0*/
1419
+ utils.forEach(fns, function transform(fn) {
1420
+ data = fn(data, headers);
1421
+ });
1422
+
1423
+ return data;
1424
+ };
1425
+
1426
+
1427
+ /***/ }),
1428
+ /* 20 */
1429
+ /***/ (function(module, exports) {
1430
+
1431
+ 'use strict';
1432
+
1433
+ module.exports = function isCancel(value) {
1434
+ return !!(value && value.__CANCEL__);
1435
+ };
1436
+
1437
+
1438
+ /***/ }),
1439
+ /* 21 */
1440
+ /***/ (function(module, exports) {
1441
+
1442
+ 'use strict';
1443
+
1444
+ /**
1445
+ * Determines whether the specified URL is absolute
1446
+ *
1447
+ * @param {string} url The URL to test
1448
+ * @returns {boolean} True if the specified URL is absolute, otherwise false
1449
+ */
1450
+ module.exports = function isAbsoluteURL(url) {
1451
+ // A URL is considered absolute if it begins with "<scheme>://" or "//" (protocol-relative URL).
1452
+ // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed
1453
+ // by any combination of letters, digits, plus, period, or hyphen.
1454
+ return /^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(url);
1455
+ };
1456
+
1457
+
1458
+ /***/ }),
1459
+ /* 22 */
1460
+ /***/ (function(module, exports) {
1461
+
1462
+ 'use strict';
1463
+
1464
+ /**
1465
+ * Creates a new URL by combining the specified URLs
1466
+ *
1467
+ * @param {string} baseURL The base URL
1468
+ * @param {string} relativeURL The relative URL
1469
+ * @returns {string} The combined URL
1470
+ */
1471
+ module.exports = function combineURLs(baseURL, relativeURL) {
1472
+ return relativeURL
1473
+ ? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '')
1474
+ : baseURL;
1475
+ };
1476
+
1477
+
1478
+ /***/ }),
1479
+ /* 23 */
1480
+ /***/ (function(module, exports) {
1481
+
1482
+ 'use strict';
1483
+
1484
+ /**
1485
+ * A `Cancel` is an object that is thrown when an operation is canceled.
1486
+ *
1487
+ * @class
1488
+ * @param {string=} message The message.
1489
+ */
1490
+ function Cancel(message) {
1491
+ this.message = message;
1492
+ }
1493
+
1494
+ Cancel.prototype.toString = function toString() {
1495
+ return 'Cancel' + (this.message ? ': ' + this.message : '');
1496
+ };
1497
+
1498
+ Cancel.prototype.__CANCEL__ = true;
1499
+
1500
+ module.exports = Cancel;
1501
+
1502
+
1503
+ /***/ }),
1504
+ /* 24 */
1505
+ /***/ (function(module, exports, __webpack_require__) {
1506
+
1507
+ 'use strict';
1508
+
1509
+ var Cancel = __webpack_require__(23);
1510
+
1511
+ /**
1512
+ * A `CancelToken` is an object that can be used to request cancellation of an operation.
1513
+ *
1514
+ * @class
1515
+ * @param {Function} executor The executor function.
1516
+ */
1517
+ function CancelToken(executor) {
1518
+ if (typeof executor !== 'function') {
1519
+ throw new TypeError('executor must be a function.');
1520
+ }
1521
+
1522
+ var resolvePromise;
1523
+ this.promise = new Promise(function promiseExecutor(resolve) {
1524
+ resolvePromise = resolve;
1525
+ });
1526
+
1527
+ var token = this;
1528
+ executor(function cancel(message) {
1529
+ if (token.reason) {
1530
+ // Cancellation has already been requested
1531
+ return;
1532
+ }
1533
+
1534
+ token.reason = new Cancel(message);
1535
+ resolvePromise(token.reason);
1536
+ });
1537
+ }
1538
+
1539
+ /**
1540
+ * Throws a `Cancel` if cancellation has been requested.
1541
+ */
1542
+ CancelToken.prototype.throwIfRequested = function throwIfRequested() {
1543
+ if (this.reason) {
1544
+ throw this.reason;
1545
+ }
1546
+ };
1547
+
1548
+ /**
1549
+ * Returns an object that contains a new `CancelToken` and a function that, when called,
1550
+ * cancels the `CancelToken`.
1551
+ */
1552
+ CancelToken.source = function source() {
1553
+ var cancel;
1554
+ var token = new CancelToken(function executor(c) {
1555
+ cancel = c;
1556
+ });
1557
+ return {
1558
+ token: token,
1559
+ cancel: cancel
1560
+ };
1561
+ };
1562
+
1563
+ module.exports = CancelToken;
1564
+
1565
+
1566
+ /***/ }),
1567
+ /* 25 */
1568
+ /***/ (function(module, exports) {
1569
+
1570
+ 'use strict';
1571
+
1572
+ /**
1573
+ * Syntactic sugar for invoking a function and expanding an array for arguments.
1574
+ *
1575
+ * Common use case would be to use `Function.prototype.apply`.
1576
+ *
1577
+ * ```js
1578
+ * function f(x, y, z) {}
1579
+ * var args = [1, 2, 3];
1580
+ * f.apply(null, args);
1581
+ * ```
1582
+ *
1583
+ * With `spread` this example can be re-written.
1584
+ *
1585
+ * ```js
1586
+ * spread(function(x, y, z) {})([1, 2, 3]);
1587
+ * ```
1588
+ *
1589
+ * @param {Function} callback
1590
+ * @returns {Function}
1591
+ */
1592
+ module.exports = function spread(callback) {
1593
+ return function wrap(arr) {
1594
+ return callback.apply(null, arr);
1595
+ };
1596
+ };
1597
+
1598
+
1599
+ /***/ })
1600
+ /******/ ])
1601
+ });
1602
+ ;
1603
+ //# sourceMappingURL=axios.map
assets/js/admin/chart.min.js ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Chart.js v3.9.1
3
+ * https://www.chartjs.org
4
+ * (c) 2022 Chart.js Contributors
5
+ * Released under the MIT License
6
+ */
7
+ !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).Chart=e()}(this,(function(){"use strict";function t(){}const e=function(){let t=0;return function(){return t++}}();function i(t){return null==t}function s(t){if(Array.isArray&&Array.isArray(t))return!0;const e=Object.prototype.toString.call(t);return"[object"===e.slice(0,7)&&"Array]"===e.slice(-6)}function n(t){return null!==t&&"[object Object]"===Object.prototype.toString.call(t)}const o=t=>("number"==typeof t||t instanceof Number)&&isFinite(+t);function a(t,e){return o(t)?t:e}function r(t,e){return void 0===t?e:t}const l=(t,e)=>"string"==typeof t&&t.endsWith("%")?parseFloat(t)/100:t/e,h=(t,e)=>"string"==typeof t&&t.endsWith("%")?parseFloat(t)/100*e:+t;function c(t,e,i){if(t&&"function"==typeof t.call)return t.apply(i,e)}function d(t,e,i,o){let a,r,l;if(s(t))if(r=t.length,o)for(a=r-1;a>=0;a--)e.call(i,t[a],a);else for(a=0;a<r;a++)e.call(i,t[a],a);else if(n(t))for(l=Object.keys(t),r=l.length,a=0;a<r;a++)e.call(i,t[l[a]],l[a])}function u(t,e){let i,s,n,o;if(!t||!e||t.length!==e.length)return!1;for(i=0,s=t.length;i<s;++i)if(n=t[i],o=e[i],n.datasetIndex!==o.datasetIndex||n.index!==o.index)return!1;return!0}function f(t){if(s(t))return t.map(f);if(n(t)){const e=Object.create(null),i=Object.keys(t),s=i.length;let n=0;for(;n<s;++n)e[i[n]]=f(t[i[n]]);return e}return t}function g(t){return-1===["__proto__","prototype","constructor"].indexOf(t)}function p(t,e,i,s){if(!g(t))return;const o=e[t],a=i[t];n(o)&&n(a)?m(o,a,s):e[t]=f(a)}function m(t,e,i){const o=s(e)?e:[e],a=o.length;if(!n(t))return t;const r=(i=i||{}).merger||p;for(let s=0;s<a;++s){if(!n(e=o[s]))continue;const a=Object.keys(e);for(let s=0,n=a.length;s<n;++s)r(a[s],t,e,i)}return t}function b(t,e){return m(t,e,{merger:x})}function x(t,e,i){if(!g(t))return;const s=e[t],o=i[t];n(s)&&n(o)?b(s,o):Object.prototype.hasOwnProperty.call(e,t)||(e[t]=f(o))}const _={"":t=>t,x:t=>t.x,y:t=>t.y};function y(t,e){const i=_[e]||(_[e]=function(t){const e=v(t);return t=>{for(const i of e){if(""===i)break;t=t&&t[i]}return t}}(e));return i(t)}function v(t){const e=t.split("."),i=[];let s="";for(const t of e)s+=t,s.endsWith("\\")?s=s.slice(0,-1)+".":(i.push(s),s="");return i}function w(t){return t.charAt(0).toUpperCase()+t.slice(1)}const M=t=>void 0!==t,k=t=>"function"==typeof t,S=(t,e)=>{if(t.size!==e.size)return!1;for(const i of t)if(!e.has(i))return!1;return!0};function P(t){return"mouseup"===t.type||"click"===t.type||"contextmenu"===t.type}const D=Math.PI,O=2*D,C=O+D,A=Number.POSITIVE_INFINITY,T=D/180,L=D/2,E=D/4,R=2*D/3,I=Math.log10,z=Math.sign;function F(t){const e=Math.round(t);t=N(t,e,t/1e3)?e:t;const i=Math.pow(10,Math.floor(I(t))),s=t/i;return(s<=1?1:s<=2?2:s<=5?5:10)*i}function V(t){const e=[],i=Math.sqrt(t);let s;for(s=1;s<i;s++)t%s==0&&(e.push(s),e.push(t/s));return i===(0|i)&&e.push(i),e.sort(((t,e)=>t-e)).pop(),e}function B(t){return!isNaN(parseFloat(t))&&isFinite(t)}function N(t,e,i){return Math.abs(t-e)<i}function W(t,e){const i=Math.round(t);return i-e<=t&&i+e>=t}function j(t,e,i){let s,n,o;for(s=0,n=t.length;s<n;s++)o=t[s][i],isNaN(o)||(e.min=Math.min(e.min,o),e.max=Math.max(e.max,o))}function H(t){return t*(D/180)}function $(t){return t*(180/D)}function Y(t){if(!o(t))return;let e=1,i=0;for(;Math.round(t*e)/e!==t;)e*=10,i++;return i}function U(t,e){const i=e.x-t.x,s=e.y-t.y,n=Math.sqrt(i*i+s*s);let o=Math.atan2(s,i);return o<-.5*D&&(o+=O),{angle:o,distance:n}}function X(t,e){return Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2))}function q(t,e){return(t-e+C)%O-D}function K(t){return(t%O+O)%O}function G(t,e,i,s){const n=K(t),o=K(e),a=K(i),r=K(o-n),l=K(a-n),h=K(n-o),c=K(n-a);return n===o||n===a||s&&o===a||r>l&&h<c}function Z(t,e,i){return Math.max(e,Math.min(i,t))}function J(t){return Z(t,-32768,32767)}function Q(t,e,i,s=1e-6){return t>=Math.min(e,i)-s&&t<=Math.max(e,i)+s}function tt(t,e,i){i=i||(i=>t[i]<e);let s,n=t.length-1,o=0;for(;n-o>1;)s=o+n>>1,i(s)?o=s:n=s;return{lo:o,hi:n}}const et=(t,e,i,s)=>tt(t,i,s?s=>t[s][e]<=i:s=>t[s][e]<i),it=(t,e,i)=>tt(t,i,(s=>t[s][e]>=i));function st(t,e,i){let s=0,n=t.length;for(;s<n&&t[s]<e;)s++;for(;n>s&&t[n-1]>i;)n--;return s>0||n<t.length?t.slice(s,n):t}const nt=["push","pop","shift","splice","unshift"];function ot(t,e){t._chartjs?t._chartjs.listeners.push(e):(Object.defineProperty(t,"_chartjs",{configurable:!0,enumerable:!1,value:{listeners:[e]}}),nt.forEach((e=>{const i="_onData"+w(e),s=t[e];Object.defineProperty(t,e,{configurable:!0,enumerable:!1,value(...e){const n=s.apply(this,e);return t._chartjs.listeners.forEach((t=>{"function"==typeof t[i]&&t[i](...e)})),n}})})))}function at(t,e){const i=t._chartjs;if(!i)return;const s=i.listeners,n=s.indexOf(e);-1!==n&&s.splice(n,1),s.length>0||(nt.forEach((e=>{delete t[e]})),delete t._chartjs)}function rt(t){const e=new Set;let i,s;for(i=0,s=t.length;i<s;++i)e.add(t[i]);return e.size===s?t:Array.from(e)}const lt="undefined"==typeof window?function(t){return t()}:window.requestAnimationFrame;function ht(t,e,i){const s=i||(t=>Array.prototype.slice.call(t));let n=!1,o=[];return function(...i){o=s(i),n||(n=!0,lt.call(window,(()=>{n=!1,t.apply(e,o)})))}}function ct(t,e){let i;return function(...s){return e?(clearTimeout(i),i=setTimeout(t,e,s)):t.apply(this,s),e}}const dt=t=>"start"===t?"left":"end"===t?"right":"center",ut=(t,e,i)=>"start"===t?e:"end"===t?i:(e+i)/2,ft=(t,e,i,s)=>t===(s?"left":"right")?i:"center"===t?(e+i)/2:e;function gt(t,e,i){const s=e.length;let n=0,o=s;if(t._sorted){const{iScale:a,_parsed:r}=t,l=a.axis,{min:h,max:c,minDefined:d,maxDefined:u}=a.getUserBounds();d&&(n=Z(Math.min(et(r,a.axis,h).lo,i?s:et(e,l,a.getPixelForValue(h)).lo),0,s-1)),o=u?Z(Math.max(et(r,a.axis,c,!0).hi+1,i?0:et(e,l,a.getPixelForValue(c),!0).hi+1),n,s)-n:s-n}return{start:n,count:o}}function pt(t){const{xScale:e,yScale:i,_scaleRanges:s}=t,n={xmin:e.min,xmax:e.max,ymin:i.min,ymax:i.max};if(!s)return t._scaleRanges=n,!0;const o=s.xmin!==e.min||s.xmax!==e.max||s.ymin!==i.min||s.ymax!==i.max;return Object.assign(s,n),o}var mt=new class{constructor(){this._request=null,this._charts=new Map,this._running=!1,this._lastDate=void 0}_notify(t,e,i,s){const n=e.listeners[s],o=e.duration;n.forEach((s=>s({chart:t,initial:e.initial,numSteps:o,currentStep:Math.min(i-e.start,o)})))}_refresh(){this._request||(this._running=!0,this._request=lt.call(window,(()=>{this._update(),this._request=null,this._running&&this._refresh()})))}_update(t=Date.now()){let e=0;this._charts.forEach(((i,s)=>{if(!i.running||!i.items.length)return;const n=i.items;let o,a=n.length-1,r=!1;for(;a>=0;--a)o=n[a],o._active?(o._total>i.duration&&(i.duration=o._total),o.tick(t),r=!0):(n[a]=n[n.length-1],n.pop());r&&(s.draw(),this._notify(s,i,t,"progress")),n.length||(i.running=!1,this._notify(s,i,t,"complete"),i.initial=!1),e+=n.length})),this._lastDate=t,0===e&&(this._running=!1)}_getAnims(t){const e=this._charts;let i=e.get(t);return i||(i={running:!1,initial:!0,items:[],listeners:{complete:[],progress:[]}},e.set(t,i)),i}listen(t,e,i){this._getAnims(t).listeners[e].push(i)}add(t,e){e&&e.length&&this._getAnims(t).items.push(...e)}has(t){return this._getAnims(t).items.length>0}start(t){const e=this._charts.get(t);e&&(e.running=!0,e.start=Date.now(),e.duration=e.items.reduce(((t,e)=>Math.max(t,e._duration)),0),this._refresh())}running(t){if(!this._running)return!1;const e=this._charts.get(t);return!!(e&&e.running&&e.items.length)}stop(t){const e=this._charts.get(t);if(!e||!e.items.length)return;const i=e.items;let s=i.length-1;for(;s>=0;--s)i[s].cancel();e.items=[],this._notify(t,e,Date.now(),"complete")}remove(t){return this._charts.delete(t)}};
8
+ /*!
9
+ * @kurkle/color v0.2.1
10
+ * https://github.com/kurkle/color#readme
11
+ * (c) 2022 Jukka Kurkela
12
+ * Released under the MIT License
13
+ */function bt(t){return t+.5|0}const xt=(t,e,i)=>Math.max(Math.min(t,i),e);function _t(t){return xt(bt(2.55*t),0,255)}function yt(t){return xt(bt(255*t),0,255)}function vt(t){return xt(bt(t/2.55)/100,0,1)}function wt(t){return xt(bt(100*t),0,100)}const Mt={0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,A:10,B:11,C:12,D:13,E:14,F:15,a:10,b:11,c:12,d:13,e:14,f:15},kt=[..."0123456789ABCDEF"],St=t=>kt[15&t],Pt=t=>kt[(240&t)>>4]+kt[15&t],Dt=t=>(240&t)>>4==(15&t);function Ot(t){var e=(t=>Dt(t.r)&&Dt(t.g)&&Dt(t.b)&&Dt(t.a))(t)?St:Pt;return t?"#"+e(t.r)+e(t.g)+e(t.b)+((t,e)=>t<255?e(t):"")(t.a,e):void 0}const Ct=/^(hsla?|hwb|hsv)\(\s*([-+.e\d]+)(?:deg)?[\s,]+([-+.e\d]+)%[\s,]+([-+.e\d]+)%(?:[\s,]+([-+.e\d]+)(%)?)?\s*\)$/;function At(t,e,i){const s=e*Math.min(i,1-i),n=(e,n=(e+t/30)%12)=>i-s*Math.max(Math.min(n-3,9-n,1),-1);return[n(0),n(8),n(4)]}function Tt(t,e,i){const s=(s,n=(s+t/60)%6)=>i-i*e*Math.max(Math.min(n,4-n,1),0);return[s(5),s(3),s(1)]}function Lt(t,e,i){const s=At(t,1,.5);let n;for(e+i>1&&(n=1/(e+i),e*=n,i*=n),n=0;n<3;n++)s[n]*=1-e-i,s[n]+=e;return s}function Et(t){const e=t.r/255,i=t.g/255,s=t.b/255,n=Math.max(e,i,s),o=Math.min(e,i,s),a=(n+o)/2;let r,l,h;return n!==o&&(h=n-o,l=a>.5?h/(2-n-o):h/(n+o),r=function(t,e,i,s,n){return t===n?(e-i)/s+(e<i?6:0):e===n?(i-t)/s+2:(t-e)/s+4}(e,i,s,h,n),r=60*r+.5),[0|r,l||0,a]}function Rt(t,e,i,s){return(Array.isArray(e)?t(e[0],e[1],e[2]):t(e,i,s)).map(yt)}function It(t,e,i){return Rt(At,t,e,i)}function zt(t){return(t%360+360)%360}function Ft(t){const e=Ct.exec(t);let i,s=255;if(!e)return;e[5]!==i&&(s=e[6]?_t(+e[5]):yt(+e[5]));const n=zt(+e[2]),o=+e[3]/100,a=+e[4]/100;return i="hwb"===e[1]?function(t,e,i){return Rt(Lt,t,e,i)}(n,o,a):"hsv"===e[1]?function(t,e,i){return Rt(Tt,t,e,i)}(n,o,a):It(n,o,a),{r:i[0],g:i[1],b:i[2],a:s}}const Vt={x:"dark",Z:"light",Y:"re",X:"blu",W:"gr",V:"medium",U:"slate",A:"ee",T:"ol",S:"or",B:"ra",C:"lateg",D:"ights",R:"in",Q:"turquois",E:"hi",P:"ro",O:"al",N:"le",M:"de",L:"yello",F:"en",K:"ch",G:"arks",H:"ea",I:"ightg",J:"wh"},Bt={OiceXe:"f0f8ff",antiquewEte:"faebd7",aqua:"ffff",aquamarRe:"7fffd4",azuY:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"0",blanKedOmond:"ffebcd",Xe:"ff",XeviTet:"8a2be2",bPwn:"a52a2a",burlywood:"deb887",caMtXe:"5f9ea0",KartYuse:"7fff00",KocTate:"d2691e",cSO:"ff7f50",cSnflowerXe:"6495ed",cSnsilk:"fff8dc",crimson:"dc143c",cyan:"ffff",xXe:"8b",xcyan:"8b8b",xgTMnPd:"b8860b",xWay:"a9a9a9",xgYF:"6400",xgYy:"a9a9a9",xkhaki:"bdb76b",xmagFta:"8b008b",xTivegYF:"556b2f",xSange:"ff8c00",xScEd:"9932cc",xYd:"8b0000",xsOmon:"e9967a",xsHgYF:"8fbc8f",xUXe:"483d8b",xUWay:"2f4f4f",xUgYy:"2f4f4f",xQe:"ced1",xviTet:"9400d3",dAppRk:"ff1493",dApskyXe:"bfff",dimWay:"696969",dimgYy:"696969",dodgerXe:"1e90ff",fiYbrick:"b22222",flSOwEte:"fffaf0",foYstWAn:"228b22",fuKsia:"ff00ff",gaRsbSo:"dcdcdc",ghostwEte:"f8f8ff",gTd:"ffd700",gTMnPd:"daa520",Way:"808080",gYF:"8000",gYFLw:"adff2f",gYy:"808080",honeyMw:"f0fff0",hotpRk:"ff69b4",RdianYd:"cd5c5c",Rdigo:"4b0082",ivSy:"fffff0",khaki:"f0e68c",lavFMr:"e6e6fa",lavFMrXsh:"fff0f5",lawngYF:"7cfc00",NmoncEffon:"fffacd",ZXe:"add8e6",ZcSO:"f08080",Zcyan:"e0ffff",ZgTMnPdLw:"fafad2",ZWay:"d3d3d3",ZgYF:"90ee90",ZgYy:"d3d3d3",ZpRk:"ffb6c1",ZsOmon:"ffa07a",ZsHgYF:"20b2aa",ZskyXe:"87cefa",ZUWay:"778899",ZUgYy:"778899",ZstAlXe:"b0c4de",ZLw:"ffffe0",lime:"ff00",limegYF:"32cd32",lRF:"faf0e6",magFta:"ff00ff",maPon:"800000",VaquamarRe:"66cdaa",VXe:"cd",VScEd:"ba55d3",VpurpN:"9370db",VsHgYF:"3cb371",VUXe:"7b68ee",VsprRggYF:"fa9a",VQe:"48d1cc",VviTetYd:"c71585",midnightXe:"191970",mRtcYam:"f5fffa",mistyPse:"ffe4e1",moccasR:"ffe4b5",navajowEte:"ffdead",navy:"80",Tdlace:"fdf5e6",Tive:"808000",TivedBb:"6b8e23",Sange:"ffa500",SangeYd:"ff4500",ScEd:"da70d6",pOegTMnPd:"eee8aa",pOegYF:"98fb98",pOeQe:"afeeee",pOeviTetYd:"db7093",papayawEp:"ffefd5",pHKpuff:"ffdab9",peru:"cd853f",pRk:"ffc0cb",plum:"dda0dd",powMrXe:"b0e0e6",purpN:"800080",YbeccapurpN:"663399",Yd:"ff0000",Psybrown:"bc8f8f",PyOXe:"4169e1",saddNbPwn:"8b4513",sOmon:"fa8072",sandybPwn:"f4a460",sHgYF:"2e8b57",sHshell:"fff5ee",siFna:"a0522d",silver:"c0c0c0",skyXe:"87ceeb",UXe:"6a5acd",UWay:"708090",UgYy:"708090",snow:"fffafa",sprRggYF:"ff7f",stAlXe:"4682b4",tan:"d2b48c",teO:"8080",tEstN:"d8bfd8",tomato:"ff6347",Qe:"40e0d0",viTet:"ee82ee",JHt:"f5deb3",wEte:"ffffff",wEtesmoke:"f5f5f5",Lw:"ffff00",LwgYF:"9acd32"};let Nt;function Wt(t){Nt||(Nt=function(){const t={},e=Object.keys(Bt),i=Object.keys(Vt);let s,n,o,a,r;for(s=0;s<e.length;s++){for(a=r=e[s],n=0;n<i.length;n++)o=i[n],r=r.replace(o,Vt[o]);o=parseInt(Bt[a],16),t[r]=[o>>16&255,o>>8&255,255&o]}return t}(),Nt.transparent=[0,0,0,0]);const e=Nt[t.toLowerCase()];return e&&{r:e[0],g:e[1],b:e[2],a:4===e.length?e[3]:255}}const jt=/^rgba?\(\s*([-+.\d]+)(%)?[\s,]+([-+.e\d]+)(%)?[\s,]+([-+.e\d]+)(%)?(?:[\s,/]+([-+.e\d]+)(%)?)?\s*\)$/;const Ht=t=>t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055,$t=t=>t<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4);function Yt(t,e,i){if(t){let s=Et(t);s[e]=Math.max(0,Math.min(s[e]+s[e]*i,0===e?360:1)),s=It(s),t.r=s[0],t.g=s[1],t.b=s[2]}}function Ut(t,e){return t?Object.assign(e||{},t):t}function Xt(t){var e={r:0,g:0,b:0,a:255};return Array.isArray(t)?t.length>=3&&(e={r:t[0],g:t[1],b:t[2],a:255},t.length>3&&(e.a=yt(t[3]))):(e=Ut(t,{r:0,g:0,b:0,a:1})).a=yt(e.a),e}function qt(t){return"r"===t.charAt(0)?function(t){const e=jt.exec(t);let i,s,n,o=255;if(e){if(e[7]!==i){const t=+e[7];o=e[8]?_t(t):xt(255*t,0,255)}return i=+e[1],s=+e[3],n=+e[5],i=255&(e[2]?_t(i):xt(i,0,255)),s=255&(e[4]?_t(s):xt(s,0,255)),n=255&(e[6]?_t(n):xt(n,0,255)),{r:i,g:s,b:n,a:o}}}(t):Ft(t)}class Kt{constructor(t){if(t instanceof Kt)return t;const e=typeof t;let i;var s,n,o;"object"===e?i=Xt(t):"string"===e&&(o=(s=t).length,"#"===s[0]&&(4===o||5===o?n={r:255&17*Mt[s[1]],g:255&17*Mt[s[2]],b:255&17*Mt[s[3]],a:5===o?17*Mt[s[4]]:255}:7!==o&&9!==o||(n={r:Mt[s[1]]<<4|Mt[s[2]],g:Mt[s[3]]<<4|Mt[s[4]],b:Mt[s[5]]<<4|Mt[s[6]],a:9===o?Mt[s[7]]<<4|Mt[s[8]]:255})),i=n||Wt(t)||qt(t)),this._rgb=i,this._valid=!!i}get valid(){return this._valid}get rgb(){var t=Ut(this._rgb);return t&&(t.a=vt(t.a)),t}set rgb(t){this._rgb=Xt(t)}rgbString(){return this._valid?(t=this._rgb)&&(t.a<255?`rgba(${t.r}, ${t.g}, ${t.b}, ${vt(t.a)})`:`rgb(${t.r}, ${t.g}, ${t.b})`):void 0;var t}hexString(){return this._valid?Ot(this._rgb):void 0}hslString(){return this._valid?function(t){if(!t)return;const e=Et(t),i=e[0],s=wt(e[1]),n=wt(e[2]);return t.a<255?`hsla(${i}, ${s}%, ${n}%, ${vt(t.a)})`:`hsl(${i}, ${s}%, ${n}%)`}(this._rgb):void 0}mix(t,e){if(t){const i=this.rgb,s=t.rgb;let n;const o=e===n?.5:e,a=2*o-1,r=i.a-s.a,l=((a*r==-1?a:(a+r)/(1+a*r))+1)/2;n=1-l,i.r=255&l*i.r+n*s.r+.5,i.g=255&l*i.g+n*s.g+.5,i.b=255&l*i.b+n*s.b+.5,i.a=o*i.a+(1-o)*s.a,this.rgb=i}return this}interpolate(t,e){return t&&(this._rgb=function(t,e,i){const s=$t(vt(t.r)),n=$t(vt(t.g)),o=$t(vt(t.b));return{r:yt(Ht(s+i*($t(vt(e.r))-s))),g:yt(Ht(n+i*($t(vt(e.g))-n))),b:yt(Ht(o+i*($t(vt(e.b))-o))),a:t.a+i*(e.a-t.a)}}(this._rgb,t._rgb,e)),this}clone(){return new Kt(this.rgb)}alpha(t){return this._rgb.a=yt(t),this}clearer(t){return this._rgb.a*=1-t,this}greyscale(){const t=this._rgb,e=bt(.3*t.r+.59*t.g+.11*t.b);return t.r=t.g=t.b=e,this}opaquer(t){return this._rgb.a*=1+t,this}negate(){const t=this._rgb;return t.r=255-t.r,t.g=255-t.g,t.b=255-t.b,this}lighten(t){return Yt(this._rgb,2,t),this}darken(t){return Yt(this._rgb,2,-t),this}saturate(t){return Yt(this._rgb,1,t),this}desaturate(t){return Yt(this._rgb,1,-t),this}rotate(t){return function(t,e){var i=Et(t);i[0]=zt(i[0]+e),i=It(i),t.r=i[0],t.g=i[1],t.b=i[2]}(this._rgb,t),this}}function Gt(t){return new Kt(t)}function Zt(t){if(t&&"object"==typeof t){const e=t.toString();return"[object CanvasPattern]"===e||"[object CanvasGradient]"===e}return!1}function Jt(t){return Zt(t)?t:Gt(t)}function Qt(t){return Zt(t)?t:Gt(t).saturate(.5).darken(.1).hexString()}const te=Object.create(null),ee=Object.create(null);function ie(t,e){if(!e)return t;const i=e.split(".");for(let e=0,s=i.length;e<s;++e){const s=i[e];t=t[s]||(t[s]=Object.create(null))}return t}function se(t,e,i){return"string"==typeof e?m(ie(t,e),i):m(ie(t,""),e)}var ne=new class{constructor(t){this.animation=void 0,this.backgroundColor="rgba(0,0,0,0.1)",this.borderColor="rgba(0,0,0,0.1)",this.color="#666",this.datasets={},this.devicePixelRatio=t=>t.chart.platform.getDevicePixelRatio(),this.elements={},this.events=["mousemove","mouseout","click","touchstart","touchmove"],this.font={family:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",size:12,style:"normal",lineHeight:1.2,weight:null},this.hover={},this.hoverBackgroundColor=(t,e)=>Qt(e.backgroundColor),this.hoverBorderColor=(t,e)=>Qt(e.borderColor),this.hoverColor=(t,e)=>Qt(e.color),this.indexAxis="x",this.interaction={mode:"nearest",intersect:!0,includeInvisible:!1},this.maintainAspectRatio=!0,this.onHover=null,this.onClick=null,this.parsing=!0,this.plugins={},this.responsive=!0,this.scale=void 0,this.scales={},this.showLine=!0,this.drawActiveElementsOnTop=!0,this.describe(t)}set(t,e){return se(this,t,e)}get(t){return ie(this,t)}describe(t,e){return se(ee,t,e)}override(t,e){return se(te,t,e)}route(t,e,i,s){const o=ie(this,t),a=ie(this,i),l="_"+e;Object.defineProperties(o,{[l]:{value:o[e],writable:!0},[e]:{enumerable:!0,get(){const t=this[l],e=a[s];return n(t)?Object.assign({},e,t):r(t,e)},set(t){this[l]=t}}})}}({_scriptable:t=>!t.startsWith("on"),_indexable:t=>"events"!==t,hover:{_fallback:"interaction"},interaction:{_scriptable:!1,_indexable:!1}});function oe(){return"undefined"!=typeof window&&"undefined"!=typeof document}function ae(t){let e=t.parentNode;return e&&"[object ShadowRoot]"===e.toString()&&(e=e.host),e}function re(t,e,i){let s;return"string"==typeof t?(s=parseInt(t,10),-1!==t.indexOf("%")&&(s=s/100*e.parentNode[i])):s=t,s}const le=t=>window.getComputedStyle(t,null);function he(t,e){return le(t).getPropertyValue(e)}const ce=["top","right","bottom","left"];function de(t,e,i){const s={};i=i?"-"+i:"";for(let n=0;n<4;n++){const o=ce[n];s[o]=parseFloat(t[e+"-"+o+i])||0}return s.width=s.left+s.right,s.height=s.top+s.bottom,s}function ue(t,e){if("native"in t)return t;const{canvas:i,currentDevicePixelRatio:s}=e,n=le(i),o="border-box"===n.boxSizing,a=de(n,"padding"),r=de(n,"border","width"),{x:l,y:h,box:c}=function(t,e){const i=t.touches,s=i&&i.length?i[0]:t,{offsetX:n,offsetY:o}=s;let a,r,l=!1;if(((t,e,i)=>(t>0||e>0)&&(!i||!i.shadowRoot))(n,o,t.target))a=n,r=o;else{const t=e.getBoundingClientRect();a=s.clientX-t.left,r=s.clientY-t.top,l=!0}return{x:a,y:r,box:l}}(t,i),d=a.left+(c&&r.left),u=a.top+(c&&r.top);let{width:f,height:g}=e;return o&&(f-=a.width+r.width,g-=a.height+r.height),{x:Math.round((l-d)/f*i.width/s),y:Math.round((h-u)/g*i.height/s)}}const fe=t=>Math.round(10*t)/10;function ge(t,e,i,s){const n=le(t),o=de(n,"margin"),a=re(n.maxWidth,t,"clientWidth")||A,r=re(n.maxHeight,t,"clientHeight")||A,l=function(t,e,i){let s,n;if(void 0===e||void 0===i){const o=ae(t);if(o){const t=o.getBoundingClientRect(),a=le(o),r=de(a,"border","width"),l=de(a,"padding");e=t.width-l.width-r.width,i=t.height-l.height-r.height,s=re(a.maxWidth,o,"clientWidth"),n=re(a.maxHeight,o,"clientHeight")}else e=t.clientWidth,i=t.clientHeight}return{width:e,height:i,maxWidth:s||A,maxHeight:n||A}}(t,e,i);let{width:h,height:c}=l;if("content-box"===n.boxSizing){const t=de(n,"border","width"),e=de(n,"padding");h-=e.width+t.width,c-=e.height+t.height}return h=Math.max(0,h-o.width),c=Math.max(0,s?Math.floor(h/s):c-o.height),h=fe(Math.min(h,a,l.maxWidth)),c=fe(Math.min(c,r,l.maxHeight)),h&&!c&&(c=fe(h/2)),{width:h,height:c}}function pe(t,e,i){const s=e||1,n=Math.floor(t.height*s),o=Math.floor(t.width*s);t.height=n/s,t.width=o/s;const a=t.canvas;return a.style&&(i||!a.style.height&&!a.style.width)&&(a.style.height=`${t.height}px`,a.style.width=`${t.width}px`),(t.currentDevicePixelRatio!==s||a.height!==n||a.width!==o)&&(t.currentDevicePixelRatio=s,a.height=n,a.width=o,t.ctx.setTransform(s,0,0,s,0,0),!0)}const me=function(){let t=!1;try{const e={get passive(){return t=!0,!1}};window.addEventListener("test",null,e),window.removeEventListener("test",null,e)}catch(t){}return t}();function be(t,e){const i=he(t,e),s=i&&i.match(/^(\d+)(\.\d+)?px$/);return s?+s[1]:void 0}function xe(t){return!t||i(t.size)||i(t.family)?null:(t.style?t.style+" ":"")+(t.weight?t.weight+" ":"")+t.size+"px "+t.family}function _e(t,e,i,s,n){let o=e[n];return o||(o=e[n]=t.measureText(n).width,i.push(n)),o>s&&(s=o),s}function ye(t,e,i,n){let o=(n=n||{}).data=n.data||{},a=n.garbageCollect=n.garbageCollect||[];n.font!==e&&(o=n.data={},a=n.garbageCollect=[],n.font=e),t.save(),t.font=e;let r=0;const l=i.length;let h,c,d,u,f;for(h=0;h<l;h++)if(u=i[h],null!=u&&!0!==s(u))r=_e(t,o,a,r,u);else if(s(u))for(c=0,d=u.length;c<d;c++)f=u[c],null==f||s(f)||(r=_e(t,o,a,r,f));t.restore();const g=a.length/2;if(g>i.length){for(h=0;h<g;h++)delete o[a[h]];a.splice(0,g)}return r}function ve(t,e,i){const s=t.currentDevicePixelRatio,n=0!==i?Math.max(i/2,.5):0;return Math.round((e-n)*s)/s+n}function we(t,e){(e=e||t.getContext("2d")).save(),e.resetTransform(),e.clearRect(0,0,t.width,t.height),e.restore()}function Me(t,e,i,s){ke(t,e,i,s,null)}function ke(t,e,i,s,n){let o,a,r,l,h,c;const d=e.pointStyle,u=e.rotation,f=e.radius;let g=(u||0)*T;if(d&&"object"==typeof d&&(o=d.toString(),"[object HTMLImageElement]"===o||"[object HTMLCanvasElement]"===o))return t.save(),t.translate(i,s),t.rotate(g),t.drawImage(d,-d.width/2,-d.height/2,d.width,d.height),void t.restore();if(!(isNaN(f)||f<=0)){switch(t.beginPath(),d){default:n?t.ellipse(i,s,n/2,f,0,0,O):t.arc(i,s,f,0,O),t.closePath();break;case"triangle":t.moveTo(i+Math.sin(g)*f,s-Math.cos(g)*f),g+=R,t.lineTo(i+Math.sin(g)*f,s-Math.cos(g)*f),g+=R,t.lineTo(i+Math.sin(g)*f,s-Math.cos(g)*f),t.closePath();break;case"rectRounded":h=.516*f,l=f-h,a=Math.cos(g+E)*l,r=Math.sin(g+E)*l,t.arc(i-a,s-r,h,g-D,g-L),t.arc(i+r,s-a,h,g-L,g),t.arc(i+a,s+r,h,g,g+L),t.arc(i-r,s+a,h,g+L,g+D),t.closePath();break;case"rect":if(!u){l=Math.SQRT1_2*f,c=n?n/2:l,t.rect(i-c,s-l,2*c,2*l);break}g+=E;case"rectRot":a=Math.cos(g)*f,r=Math.sin(g)*f,t.moveTo(i-a,s-r),t.lineTo(i+r,s-a),t.lineTo(i+a,s+r),t.lineTo(i-r,s+a),t.closePath();break;case"crossRot":g+=E;case"cross":a=Math.cos(g)*f,r=Math.sin(g)*f,t.moveTo(i-a,s-r),t.lineTo(i+a,s+r),t.moveTo(i+r,s-a),t.lineTo(i-r,s+a);break;case"star":a=Math.cos(g)*f,r=Math.sin(g)*f,t.moveTo(i-a,s-r),t.lineTo(i+a,s+r),t.moveTo(i+r,s-a),t.lineTo(i-r,s+a),g+=E,a=Math.cos(g)*f,r=Math.sin(g)*f,t.moveTo(i-a,s-r),t.lineTo(i+a,s+r),t.moveTo(i+r,s-a),t.lineTo(i-r,s+a);break;case"line":a=n?n/2:Math.cos(g)*f,r=Math.sin(g)*f,t.moveTo(i-a,s-r),t.lineTo(i+a,s+r);break;case"dash":t.moveTo(i,s),t.lineTo(i+Math.cos(g)*f,s+Math.sin(g)*f)}t.fill(),e.borderWidth>0&&t.stroke()}}function Se(t,e,i){return i=i||.5,!e||t&&t.x>e.left-i&&t.x<e.right+i&&t.y>e.top-i&&t.y<e.bottom+i}function Pe(t,e){t.save(),t.beginPath(),t.rect(e.left,e.top,e.right-e.left,e.bottom-e.top),t.clip()}function De(t){t.restore()}function Oe(t,e,i,s,n){if(!e)return t.lineTo(i.x,i.y);if("middle"===n){const s=(e.x+i.x)/2;t.lineTo(s,e.y),t.lineTo(s,i.y)}else"after"===n!=!!s?t.lineTo(e.x,i.y):t.lineTo(i.x,e.y);t.lineTo(i.x,i.y)}function Ce(t,e,i,s){if(!e)return t.lineTo(i.x,i.y);t.bezierCurveTo(s?e.cp1x:e.cp2x,s?e.cp1y:e.cp2y,s?i.cp2x:i.cp1x,s?i.cp2y:i.cp1y,i.x,i.y)}function Ae(t,e,n,o,a,r={}){const l=s(e)?e:[e],h=r.strokeWidth>0&&""!==r.strokeColor;let c,d;for(t.save(),t.font=a.string,function(t,e){e.translation&&t.translate(e.translation[0],e.translation[1]);i(e.rotation)||t.rotate(e.rotation);e.color&&(t.fillStyle=e.color);e.textAlign&&(t.textAlign=e.textAlign);e.textBaseline&&(t.textBaseline=e.textBaseline)}(t,r),c=0;c<l.length;++c)d=l[c],h&&(r.strokeColor&&(t.strokeStyle=r.strokeColor),i(r.strokeWidth)||(t.lineWidth=r.strokeWidth),t.strokeText(d,n,o,r.maxWidth)),t.fillText(d,n,o,r.maxWidth),Te(t,n,o,d,r),o+=a.lineHeight;t.restore()}function Te(t,e,i,s,n){if(n.strikethrough||n.underline){const o=t.measureText(s),a=e-o.actualBoundingBoxLeft,r=e+o.actualBoundingBoxRight,l=i-o.actualBoundingBoxAscent,h=i+o.actualBoundingBoxDescent,c=n.strikethrough?(l+h)/2:h;t.strokeStyle=t.fillStyle,t.beginPath(),t.lineWidth=n.decorationWidth||2,t.moveTo(a,c),t.lineTo(r,c),t.stroke()}}function Le(t,e){const{x:i,y:s,w:n,h:o,radius:a}=e;t.arc(i+a.topLeft,s+a.topLeft,a.topLeft,-L,D,!0),t.lineTo(i,s+o-a.bottomLeft),t.arc(i+a.bottomLeft,s+o-a.bottomLeft,a.bottomLeft,D,L,!0),t.lineTo(i+n-a.bottomRight,s+o),t.arc(i+n-a.bottomRight,s+o-a.bottomRight,a.bottomRight,L,0,!0),t.lineTo(i+n,s+a.topRight),t.arc(i+n-a.topRight,s+a.topRight,a.topRight,0,-L,!0),t.lineTo(i+a.topLeft,s)}function Ee(t,e=[""],i=t,s,n=(()=>t[0])){M(s)||(s=$e("_fallback",t));const o={[Symbol.toStringTag]:"Object",_cacheable:!0,_scopes:t,_rootScopes:i,_fallback:s,_getTarget:n,override:n=>Ee([n,...t],e,i,s)};return new Proxy(o,{deleteProperty:(e,i)=>(delete e[i],delete e._keys,delete t[0][i],!0),get:(i,s)=>Ve(i,s,(()=>function(t,e,i,s){let n;for(const o of e)if(n=$e(ze(o,t),i),M(n))return Fe(t,n)?je(i,s,t,n):n}(s,e,t,i))),getOwnPropertyDescriptor:(t,e)=>Reflect.getOwnPropertyDescriptor(t._scopes[0],e),getPrototypeOf:()=>Reflect.getPrototypeOf(t[0]),has:(t,e)=>Ye(t).includes(e),ownKeys:t=>Ye(t),set(t,e,i){const s=t._storage||(t._storage=n());return t[e]=s[e]=i,delete t._keys,!0}})}function Re(t,e,i,o){const a={_cacheable:!1,_proxy:t,_context:e,_subProxy:i,_stack:new Set,_descriptors:Ie(t,o),setContext:e=>Re(t,e,i,o),override:s=>Re(t.override(s),e,i,o)};return new Proxy(a,{deleteProperty:(e,i)=>(delete e[i],delete t[i],!0),get:(t,e,i)=>Ve(t,e,(()=>function(t,e,i){const{_proxy:o,_context:a,_subProxy:r,_descriptors:l}=t;let h=o[e];k(h)&&l.isScriptable(e)&&(h=function(t,e,i,s){const{_proxy:n,_context:o,_subProxy:a,_stack:r}=i;if(r.has(t))throw new Error("Recursion detected: "+Array.from(r).join("->")+"->"+t);r.add(t),e=e(o,a||s),r.delete(t),Fe(t,e)&&(e=je(n._scopes,n,t,e));return e}(e,h,t,i));s(h)&&h.length&&(h=function(t,e,i,s){const{_proxy:o,_context:a,_subProxy:r,_descriptors:l}=i;if(M(a.index)&&s(t))e=e[a.index%e.length];else if(n(e[0])){const i=e,s=o._scopes.filter((t=>t!==i));e=[];for(const n of i){const i=je(s,o,t,n);e.push(Re(i,a,r&&r[t],l))}}return e}(e,h,t,l.isIndexable));Fe(e,h)&&(h=Re(h,a,r&&r[e],l));return h}(t,e,i))),getOwnPropertyDescriptor:(e,i)=>e._descriptors.allKeys?Reflect.has(t,i)?{enumerable:!0,configurable:!0}:void 0:Reflect.getOwnPropertyDescriptor(t,i),getPrototypeOf:()=>Reflect.getPrototypeOf(t),has:(e,i)=>Reflect.has(t,i),ownKeys:()=>Reflect.ownKeys(t),set:(e,i,s)=>(t[i]=s,delete e[i],!0)})}function Ie(t,e={scriptable:!0,indexable:!0}){const{_scriptable:i=e.scriptable,_indexable:s=e.indexable,_allKeys:n=e.allKeys}=t;return{allKeys:n,scriptable:i,indexable:s,isScriptable:k(i)?i:()=>i,isIndexable:k(s)?s:()=>s}}const ze=(t,e)=>t?t+w(e):e,Fe=(t,e)=>n(e)&&"adapters"!==t&&(null===Object.getPrototypeOf(e)||e.constructor===Object);function Ve(t,e,i){if(Object.prototype.hasOwnProperty.call(t,e))return t[e];const s=i();return t[e]=s,s}function Be(t,e,i){return k(t)?t(e,i):t}const Ne=(t,e)=>!0===t?e:"string"==typeof t?y(e,t):void 0;function We(t,e,i,s,n){for(const o of e){const e=Ne(i,o);if(e){t.add(e);const o=Be(e._fallback,i,n);if(M(o)&&o!==i&&o!==s)return o}else if(!1===e&&M(s)&&i!==s)return null}return!1}function je(t,e,i,o){const a=e._rootScopes,r=Be(e._fallback,i,o),l=[...t,...a],h=new Set;h.add(o);let c=He(h,l,i,r||i,o);return null!==c&&((!M(r)||r===i||(c=He(h,l,r,c,o),null!==c))&&Ee(Array.from(h),[""],a,r,(()=>function(t,e,i){const o=t._getTarget();e in o||(o[e]={});const a=o[e];if(s(a)&&n(i))return i;return a}(e,i,o))))}function He(t,e,i,s,n){for(;i;)i=We(t,e,i,s,n);return i}function $e(t,e){for(const i of e){if(!i)continue;const e=i[t];if(M(e))return e}}function Ye(t){let e=t._keys;return e||(e=t._keys=function(t){const e=new Set;for(const i of t)for(const t of Object.keys(i).filter((t=>!t.startsWith("_"))))e.add(t);return Array.from(e)}(t._scopes)),e}function Ue(t,e,i,s){const{iScale:n}=t,{key:o="r"}=this._parsing,a=new Array(s);let r,l,h,c;for(r=0,l=s;r<l;++r)h=r+i,c=e[h],a[r]={r:n.parse(y(c,o),h)};return a}const Xe=Number.EPSILON||1e-14,qe=(t,e)=>e<t.length&&!t[e].skip&&t[e],Ke=t=>"x"===t?"y":"x";function Ge(t,e,i,s){const n=t.skip?e:t,o=e,a=i.skip?e:i,r=X(o,n),l=X(a,o);let h=r/(r+l),c=l/(r+l);h=isNaN(h)?0:h,c=isNaN(c)?0:c;const d=s*h,u=s*c;return{previous:{x:o.x-d*(a.x-n.x),y:o.y-d*(a.y-n.y)},next:{x:o.x+u*(a.x-n.x),y:o.y+u*(a.y-n.y)}}}function Ze(t,e="x"){const i=Ke(e),s=t.length,n=Array(s).fill(0),o=Array(s);let a,r,l,h=qe(t,0);for(a=0;a<s;++a)if(r=l,l=h,h=qe(t,a+1),l){if(h){const t=h[e]-l[e];n[a]=0!==t?(h[i]-l[i])/t:0}o[a]=r?h?z(n[a-1])!==z(n[a])?0:(n[a-1]+n[a])/2:n[a-1]:n[a]}!function(t,e,i){const s=t.length;let n,o,a,r,l,h=qe(t,0);for(let c=0;c<s-1;++c)l=h,h=qe(t,c+1),l&&h&&(N(e[c],0,Xe)?i[c]=i[c+1]=0:(n=i[c]/e[c],o=i[c+1]/e[c],r=Math.pow(n,2)+Math.pow(o,2),r<=9||(a=3/Math.sqrt(r),i[c]=n*a*e[c],i[c+1]=o*a*e[c])))}(t,n,o),function(t,e,i="x"){const s=Ke(i),n=t.length;let o,a,r,l=qe(t,0);for(let h=0;h<n;++h){if(a=r,r=l,l=qe(t,h+1),!r)continue;const n=r[i],c=r[s];a&&(o=(n-a[i])/3,r[`cp1${i}`]=n-o,r[`cp1${s}`]=c-o*e[h]),l&&(o=(l[i]-n)/3,r[`cp2${i}`]=n+o,r[`cp2${s}`]=c+o*e[h])}}(t,o,e)}function Je(t,e,i){return Math.max(Math.min(t,i),e)}function Qe(t,e,i,s,n){let o,a,r,l;if(e.spanGaps&&(t=t.filter((t=>!t.skip))),"monotone"===e.cubicInterpolationMode)Ze(t,n);else{let i=s?t[t.length-1]:t[0];for(o=0,a=t.length;o<a;++o)r=t[o],l=Ge(i,r,t[Math.min(o+1,a-(s?0:1))%a],e.tension),r.cp1x=l.previous.x,r.cp1y=l.previous.y,r.cp2x=l.next.x,r.cp2y=l.next.y,i=r}e.capBezierPoints&&function(t,e){let i,s,n,o,a,r=Se(t[0],e);for(i=0,s=t.length;i<s;++i)a=o,o=r,r=i<s-1&&Se(t[i+1],e),o&&(n=t[i],a&&(n.cp1x=Je(n.cp1x,e.left,e.right),n.cp1y=Je(n.cp1y,e.top,e.bottom)),r&&(n.cp2x=Je(n.cp2x,e.left,e.right),n.cp2y=Je(n.cp2y,e.top,e.bottom)))}(t,i)}const ti=t=>0===t||1===t,ei=(t,e,i)=>-Math.pow(2,10*(t-=1))*Math.sin((t-e)*O/i),ii=(t,e,i)=>Math.pow(2,-10*t)*Math.sin((t-e)*O/i)+1,si={linear:t=>t,easeInQuad:t=>t*t,easeOutQuad:t=>-t*(t-2),easeInOutQuad:t=>(t/=.5)<1?.5*t*t:-.5*(--t*(t-2)-1),easeInCubic:t=>t*t*t,easeOutCubic:t=>(t-=1)*t*t+1,easeInOutCubic:t=>(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2),easeInQuart:t=>t*t*t*t,easeOutQuart:t=>-((t-=1)*t*t*t-1),easeInOutQuart:t=>(t/=.5)<1?.5*t*t*t*t:-.5*((t-=2)*t*t*t-2),easeInQuint:t=>t*t*t*t*t,easeOutQuint:t=>(t-=1)*t*t*t*t+1,easeInOutQuint:t=>(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2),easeInSine:t=>1-Math.cos(t*L),easeOutSine:t=>Math.sin(t*L),easeInOutSine:t=>-.5*(Math.cos(D*t)-1),easeInExpo:t=>0===t?0:Math.pow(2,10*(t-1)),easeOutExpo:t=>1===t?1:1-Math.pow(2,-10*t),easeInOutExpo:t=>ti(t)?t:t<.5?.5*Math.pow(2,10*(2*t-1)):.5*(2-Math.pow(2,-10*(2*t-1))),easeInCirc:t=>t>=1?t:-(Math.sqrt(1-t*t)-1),easeOutCirc:t=>Math.sqrt(1-(t-=1)*t),easeInOutCirc:t=>(t/=.5)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1),easeInElastic:t=>ti(t)?t:ei(t,.075,.3),easeOutElastic:t=>ti(t)?t:ii(t,.075,.3),easeInOutElastic(t){const e=.1125;return ti(t)?t:t<.5?.5*ei(2*t,e,.45):.5+.5*ii(2*t-1,e,.45)},easeInBack(t){const e=1.70158;return t*t*((e+1)*t-e)},easeOutBack(t){const e=1.70158;return(t-=1)*t*((e+1)*t+e)+1},easeInOutBack(t){let e=1.70158;return(t/=.5)<1?t*t*((1+(e*=1.525))*t-e)*.5:.5*((t-=2)*t*((1+(e*=1.525))*t+e)+2)},easeInBounce:t=>1-si.easeOutBounce(1-t),easeOutBounce(t){const e=7.5625,i=2.75;return t<1/i?e*t*t:t<2/i?e*(t-=1.5/i)*t+.75:t<2.5/i?e*(t-=2.25/i)*t+.9375:e*(t-=2.625/i)*t+.984375},easeInOutBounce:t=>t<.5?.5*si.easeInBounce(2*t):.5*si.easeOutBounce(2*t-1)+.5};function ni(t,e,i,s){return{x:t.x+i*(e.x-t.x),y:t.y+i*(e.y-t.y)}}function oi(t,e,i,s){return{x:t.x+i*(e.x-t.x),y:"middle"===s?i<.5?t.y:e.y:"after"===s?i<1?t.y:e.y:i>0?e.y:t.y}}function ai(t,e,i,s){const n={x:t.cp2x,y:t.cp2y},o={x:e.cp1x,y:e.cp1y},a=ni(t,n,i),r=ni(n,o,i),l=ni(o,e,i),h=ni(a,r,i),c=ni(r,l,i);return ni(h,c,i)}const ri=new Map;function li(t,e,i){return function(t,e){e=e||{};const i=t+JSON.stringify(e);let s=ri.get(i);return s||(s=new Intl.NumberFormat(t,e),ri.set(i,s)),s}(e,i).format(t)}const hi=new RegExp(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/),ci=new RegExp(/^(normal|italic|initial|inherit|unset|(oblique( -?[0-9]?[0-9]deg)?))$/);function di(t,e){const i=(""+t).match(hi);if(!i||"normal"===i[1])return 1.2*e;switch(t=+i[2],i[3]){case"px":return t;case"%":t/=100}return e*t}function ui(t,e){const i={},s=n(e),o=s?Object.keys(e):e,a=n(t)?s?i=>r(t[i],t[e[i]]):e=>t[e]:()=>t;for(const t of o)i[t]=+a(t)||0;return i}function fi(t){return ui(t,{top:"y",right:"x",bottom:"y",left:"x"})}function gi(t){return ui(t,["topLeft","topRight","bottomLeft","bottomRight"])}function pi(t){const e=fi(t);return e.width=e.left+e.right,e.height=e.top+e.bottom,e}function mi(t,e){t=t||{},e=e||ne.font;let i=r(t.size,e.size);"string"==typeof i&&(i=parseInt(i,10));let s=r(t.style,e.style);s&&!(""+s).match(ci)&&(console.warn('Invalid font style specified: "'+s+'"'),s="");const n={family:r(t.family,e.family),lineHeight:di(r(t.lineHeight,e.lineHeight),i),size:i,style:s,weight:r(t.weight,e.weight),string:""};return n.string=xe(n),n}function bi(t,e,i,n){let o,a,r,l=!0;for(o=0,a=t.length;o<a;++o)if(r=t[o],void 0!==r&&(void 0!==e&&"function"==typeof r&&(r=r(e),l=!1),void 0!==i&&s(r)&&(r=r[i%r.length],l=!1),void 0!==r))return n&&!l&&(n.cacheable=!1),r}function xi(t,e,i){const{min:s,max:n}=t,o=h(e,(n-s)/2),a=(t,e)=>i&&0===t?0:t+e;return{min:a(s,-Math.abs(o)),max:a(n,o)}}function _i(t,e){return Object.assign(Object.create(t),e)}function yi(t,e,i){return t?function(t,e){return{x:i=>t+t+e-i,setWidth(t){e=t},textAlign:t=>"center"===t?t:"right"===t?"left":"right",xPlus:(t,e)=>t-e,leftForLtr:(t,e)=>t-e}}(e,i):{x:t=>t,setWidth(t){},textAlign:t=>t,xPlus:(t,e)=>t+e,leftForLtr:(t,e)=>t}}function vi(t,e){let i,s;"ltr"!==e&&"rtl"!==e||(i=t.canvas.style,s=[i.getPropertyValue("direction"),i.getPropertyPriority("direction")],i.setProperty("direction",e,"important"),t.prevTextDirection=s)}function wi(t,e){void 0!==e&&(delete t.prevTextDirection,t.canvas.style.setProperty("direction",e[0],e[1]))}function Mi(t){return"angle"===t?{between:G,compare:q,normalize:K}:{between:Q,compare:(t,e)=>t-e,normalize:t=>t}}function ki({start:t,end:e,count:i,loop:s,style:n}){return{start:t%i,end:e%i,loop:s&&(e-t+1)%i==0,style:n}}function Si(t,e,i){if(!i)return[t];const{property:s,start:n,end:o}=i,a=e.length,{compare:r,between:l,normalize:h}=Mi(s),{start:c,end:d,loop:u,style:f}=function(t,e,i){const{property:s,start:n,end:o}=i,{between:a,normalize:r}=Mi(s),l=e.length;let h,c,{start:d,end:u,loop:f}=t;if(f){for(d+=l,u+=l,h=0,c=l;h<c&&a(r(e[d%l][s]),n,o);++h)d--,u--;d%=l,u%=l}return u<d&&(u+=l),{start:d,end:u,loop:f,style:t.style}}(t,e,i),g=[];let p,m,b,x=!1,_=null;const y=()=>x||l(n,b,p)&&0!==r(n,b),v=()=>!x||0===r(o,p)||l(o,b,p);for(let t=c,i=c;t<=d;++t)m=e[t%a],m.skip||(p=h(m[s]),p!==b&&(x=l(p,n,o),null===_&&y()&&(_=0===r(p,n)?t:i),null!==_&&v()&&(g.push(ki({start:_,end:t,loop:u,count:a,style:f})),_=null),i=t,b=p));return null!==_&&g.push(ki({start:_,end:d,loop:u,count:a,style:f})),g}function Pi(t,e){const i=[],s=t.segments;for(let n=0;n<s.length;n++){const o=Si(s[n],t.points,e);o.length&&i.push(...o)}return i}function Di(t,e){const i=t.points,s=t.options.spanGaps,n=i.length;if(!n)return[];const o=!!t._loop,{start:a,end:r}=function(t,e,i,s){let n=0,o=e-1;if(i&&!s)for(;n<e&&!t[n].skip;)n++;for(;n<e&&t[n].skip;)n++;for(n%=e,i&&(o+=n);o>n&&t[o%e].skip;)o--;return o%=e,{start:n,end:o}}(i,n,o,s);if(!0===s)return Oi(t,[{start:a,end:r,loop:o}],i,e);return Oi(t,function(t,e,i,s){const n=t.length,o=[];let a,r=e,l=t[e];for(a=e+1;a<=i;++a){const i=t[a%n];i.skip||i.stop?l.skip||(s=!1,o.push({start:e%n,end:(a-1)%n,loop:s}),e=r=i.stop?a:null):(r=a,l.skip&&(e=a)),l=i}return null!==r&&o.push({start:e%n,end:r%n,loop:s}),o}(i,a,r<a?r+n:r,!!t._fullLoop&&0===a&&r===n-1),i,e)}function Oi(t,e,i,s){return s&&s.setContext&&i?function(t,e,i,s){const n=t._chart.getContext(),o=Ci(t.options),{_datasetIndex:a,options:{spanGaps:r}}=t,l=i.length,h=[];let c=o,d=e[0].start,u=d;function f(t,e,s,n){const o=r?-1:1;if(t!==e){for(t+=l;i[t%l].skip;)t-=o;for(;i[e%l].skip;)e+=o;t%l!=e%l&&(h.push({start:t%l,end:e%l,loop:s,style:n}),c=n,d=e%l)}}for(const t of e){d=r?d:t.start;let e,o=i[d%l];for(u=d+1;u<=t.end;u++){const r=i[u%l];e=Ci(s.setContext(_i(n,{type:"segment",p0:o,p1:r,p0DataIndex:(u-1)%l,p1DataIndex:u%l,datasetIndex:a}))),Ai(e,c)&&f(d,u-1,t.loop,c),o=r,c=e}d<u-1&&f(d,u-1,t.loop,c)}return h}(t,e,i,s):e}function Ci(t){return{backgroundColor:t.backgroundColor,borderCapStyle:t.borderCapStyle,borderDash:t.borderDash,borderDashOffset:t.borderDashOffset,borderJoinStyle:t.borderJoinStyle,borderWidth:t.borderWidth,borderColor:t.borderColor}}function Ai(t,e){return e&&JSON.stringify(t)!==JSON.stringify(e)}var Ti=Object.freeze({__proto__:null,easingEffects:si,isPatternOrGradient:Zt,color:Jt,getHoverColor:Qt,noop:t,uid:e,isNullOrUndef:i,isArray:s,isObject:n,isFinite:o,finiteOrDefault:a,valueOrDefault:r,toPercentage:l,toDimension:h,callback:c,each:d,_elementsEqual:u,clone:f,_merger:p,merge:m,mergeIf:b,_mergerIf:x,_deprecated:function(t,e,i,s){void 0!==e&&console.warn(t+': "'+i+'" is deprecated. Please use "'+s+'" instead')},resolveObjectKey:y,_splitKey:v,_capitalize:w,defined:M,isFunction:k,setsEqual:S,_isClickEvent:P,toFontString:xe,_measureText:_e,_longestText:ye,_alignPixel:ve,clearCanvas:we,drawPoint:Me,drawPointLegend:ke,_isPointInArea:Se,clipArea:Pe,unclipArea:De,_steppedLineTo:Oe,_bezierCurveTo:Ce,renderText:Ae,addRoundedRectPath:Le,_lookup:tt,_lookupByKey:et,_rlookupByKey:it,_filterBetween:st,listenArrayEvents:ot,unlistenArrayEvents:at,_arrayUnique:rt,_createResolver:Ee,_attachContext:Re,_descriptors:Ie,_parseObjectDataRadialScale:Ue,splineCurve:Ge,splineCurveMonotone:Ze,_updateBezierControlPoints:Qe,_isDomSupported:oe,_getParentNode:ae,getStyle:he,getRelativePosition:ue,getMaximumSize:ge,retinaScale:pe,supportsEventListenerOptions:me,readUsedSize:be,fontString:function(t,e,i){return e+" "+t+"px "+i},requestAnimFrame:lt,throttled:ht,debounce:ct,_toLeftRightCenter:dt,_alignStartEnd:ut,_textX:ft,_getStartAndCountOfVisiblePoints:gt,_scaleRangesChanged:pt,_pointInLine:ni,_steppedInterpolation:oi,_bezierInterpolation:ai,formatNumber:li,toLineHeight:di,_readValueToProps:ui,toTRBL:fi,toTRBLCorners:gi,toPadding:pi,toFont:mi,resolve:bi,_addGrace:xi,createContext:_i,PI:D,TAU:O,PITAU:C,INFINITY:A,RAD_PER_DEG:T,HALF_PI:L,QUARTER_PI:E,TWO_THIRDS_PI:R,log10:I,sign:z,niceNum:F,_factorize:V,isNumber:B,almostEquals:N,almostWhole:W,_setMinAndMaxByKey:j,toRadians:H,toDegrees:$,_decimalPlaces:Y,getAngleFromPoint:U,distanceBetweenPoints:X,_angleDiff:q,_normalizeAngle:K,_angleBetween:G,_limitValue:Z,_int16Range:J,_isBetween:Q,getRtlAdapter:yi,overrideTextDirection:vi,restoreTextDirection:wi,_boundSegment:Si,_boundSegments:Pi,_computeSegments:Di});function Li(t,e,i,s){const{controller:n,data:o,_sorted:a}=t,r=n._cachedMeta.iScale;if(r&&e===r.axis&&"r"!==e&&a&&o.length){const t=r._reversePixels?it:et;if(!s)return t(o,e,i);if(n._sharedOptions){const s=o[0],n="function"==typeof s.getRange&&s.getRange(e);if(n){const s=t(o,e,i-n),a=t(o,e,i+n);return{lo:s.lo,hi:a.hi}}}}return{lo:0,hi:o.length-1}}function Ei(t,e,i,s,n){const o=t.getSortedVisibleDatasetMetas(),a=i[e];for(let t=0,i=o.length;t<i;++t){const{index:i,data:r}=o[t],{lo:l,hi:h}=Li(o[t],e,a,n);for(let t=l;t<=h;++t){const e=r[t];e.skip||s(e,i,t)}}}function Ri(t,e,i,s,n){const o=[];if(!n&&!t.isPointInArea(e))return o;return Ei(t,i,e,(function(i,a,r){(n||Se(i,t.chartArea,0))&&i.inRange(e.x,e.y,s)&&o.push({element:i,datasetIndex:a,index:r})}),!0),o}function Ii(t,e,i,s,n,o){let a=[];const r=function(t){const e=-1!==t.indexOf("x"),i=-1!==t.indexOf("y");return function(t,s){const n=e?Math.abs(t.x-s.x):0,o=i?Math.abs(t.y-s.y):0;return Math.sqrt(Math.pow(n,2)+Math.pow(o,2))}}(i);let l=Number.POSITIVE_INFINITY;return Ei(t,i,e,(function(i,h,c){const d=i.inRange(e.x,e.y,n);if(s&&!d)return;const u=i.getCenterPoint(n);if(!(!!o||t.isPointInArea(u))&&!d)return;const f=r(e,u);f<l?(a=[{element:i,datasetIndex:h,index:c}],l=f):f===l&&a.push({element:i,datasetIndex:h,index:c})})),a}function zi(t,e,i,s,n,o){return o||t.isPointInArea(e)?"r"!==i||s?Ii(t,e,i,s,n,o):function(t,e,i,s){let n=[];return Ei(t,i,e,(function(t,i,o){const{startAngle:a,endAngle:r}=t.getProps(["startAngle","endAngle"],s),{angle:l}=U(t,{x:e.x,y:e.y});G(l,a,r)&&n.push({element:t,datasetIndex:i,index:o})})),n}(t,e,i,n):[]}function Fi(t,e,i,s,n){const o=[],a="x"===i?"inXRange":"inYRange";let r=!1;return Ei(t,i,e,((t,s,l)=>{t[a](e[i],n)&&(o.push({element:t,datasetIndex:s,index:l}),r=r||t.inRange(e.x,e.y,n))})),s&&!r?[]:o}var Vi={evaluateInteractionItems:Ei,modes:{index(t,e,i,s){const n=ue(e,t),o=i.axis||"x",a=i.includeInvisible||!1,r=i.intersect?Ri(t,n,o,s,a):zi(t,n,o,!1,s,a),l=[];return r.length?(t.getSortedVisibleDatasetMetas().forEach((t=>{const e=r[0].index,i=t.data[e];i&&!i.skip&&l.push({element:i,datasetIndex:t.index,index:e})})),l):[]},dataset(t,e,i,s){const n=ue(e,t),o=i.axis||"xy",a=i.includeInvisible||!1;let r=i.intersect?Ri(t,n,o,s,a):zi(t,n,o,!1,s,a);if(r.length>0){const e=r[0].datasetIndex,i=t.getDatasetMeta(e).data;r=[];for(let t=0;t<i.length;++t)r.push({element:i[t],datasetIndex:e,index:t})}return r},point:(t,e,i,s)=>Ri(t,ue(e,t),i.axis||"xy",s,i.includeInvisible||!1),nearest(t,e,i,s){const n=ue(e,t),o=i.axis||"xy",a=i.includeInvisible||!1;return zi(t,n,o,i.intersect,s,a)},x:(t,e,i,s)=>Fi(t,ue(e,t),"x",i.intersect,s),y:(t,e,i,s)=>Fi(t,ue(e,t),"y",i.intersect,s)}};const Bi=["left","top","right","bottom"];function Ni(t,e){return t.filter((t=>t.pos===e))}function Wi(t,e){return t.filter((t=>-1===Bi.indexOf(t.pos)&&t.box.axis===e))}function ji(t,e){return t.sort(((t,i)=>{const s=e?i:t,n=e?t:i;return s.weight===n.weight?s.index-n.index:s.weight-n.weight}))}function Hi(t,e){const i=function(t){const e={};for(const i of t){const{stack:t,pos:s,stackWeight:n}=i;if(!t||!Bi.includes(s))continue;const o=e[t]||(e[t]={count:0,placed:0,weight:0,size:0});o.count++,o.weight+=n}return e}(t),{vBoxMaxWidth:s,hBoxMaxHeight:n}=e;let o,a,r;for(o=0,a=t.length;o<a;++o){r=t[o];const{fullSize:a}=r.box,l=i[r.stack],h=l&&r.stackWeight/l.weight;r.horizontal?(r.width=h?h*s:a&&e.availableWidth,r.height=n):(r.width=s,r.height=h?h*n:a&&e.availableHeight)}return i}function $i(t,e,i,s){return Math.max(t[i],e[i])+Math.max(t[s],e[s])}function Yi(t,e){t.top=Math.max(t.top,e.top),t.left=Math.max(t.left,e.left),t.bottom=Math.max(t.bottom,e.bottom),t.right=Math.max(t.right,e.right)}function Ui(t,e,i,s){const{pos:o,box:a}=i,r=t.maxPadding;if(!n(o)){i.size&&(t[o]-=i.size);const e=s[i.stack]||{size:0,count:1};e.size=Math.max(e.size,i.horizontal?a.height:a.width),i.size=e.size/e.count,t[o]+=i.size}a.getPadding&&Yi(r,a.getPadding());const l=Math.max(0,e.outerWidth-$i(r,t,"left","right")),h=Math.max(0,e.outerHeight-$i(r,t,"top","bottom")),c=l!==t.w,d=h!==t.h;return t.w=l,t.h=h,i.horizontal?{same:c,other:d}:{same:d,other:c}}function Xi(t,e){const i=e.maxPadding;function s(t){const s={left:0,top:0,right:0,bottom:0};return t.forEach((t=>{s[t]=Math.max(e[t],i[t])})),s}return s(t?["left","right"]:["top","bottom"])}function qi(t,e,i,s){const n=[];let o,a,r,l,h,c;for(o=0,a=t.length,h=0;o<a;++o){r=t[o],l=r.box,l.update(r.width||e.w,r.height||e.h,Xi(r.horizontal,e));const{same:a,other:d}=Ui(e,i,r,s);h|=a&&n.length,c=c||d,l.fullSize||n.push(r)}return h&&qi(n,e,i,s)||c}function Ki(t,e,i,s,n){t.top=i,t.left=e,t.right=e+s,t.bottom=i+n,t.width=s,t.height=n}function Gi(t,e,i,s){const n=i.padding;let{x:o,y:a}=e;for(const r of t){const t=r.box,l=s[r.stack]||{count:1,placed:0,weight:1},h=r.stackWeight/l.weight||1;if(r.horizontal){const s=e.w*h,o=l.size||t.height;M(l.start)&&(a=l.start),t.fullSize?Ki(t,n.left,a,i.outerWidth-n.right-n.left,o):Ki(t,e.left+l.placed,a,s,o),l.start=a,l.placed+=s,a=t.bottom}else{const s=e.h*h,a=l.size||t.width;M(l.start)&&(o=l.start),t.fullSize?Ki(t,o,n.top,a,i.outerHeight-n.bottom-n.top):Ki(t,o,e.top+l.placed,a,s),l.start=o,l.placed+=s,o=t.right}}e.x=o,e.y=a}ne.set("layout",{autoPadding:!0,padding:{top:0,right:0,bottom:0,left:0}});var Zi={addBox(t,e){t.boxes||(t.boxes=[]),e.fullSize=e.fullSize||!1,e.position=e.position||"top",e.weight=e.weight||0,e._layers=e._layers||function(){return[{z:0,draw(t){e.draw(t)}}]},t.boxes.push(e)},removeBox(t,e){const i=t.boxes?t.boxes.indexOf(e):-1;-1!==i&&t.boxes.splice(i,1)},configure(t,e,i){e.fullSize=i.fullSize,e.position=i.position,e.weight=i.weight},update(t,e,i,s){if(!t)return;const n=pi(t.options.layout.padding),o=Math.max(e-n.width,0),a=Math.max(i-n.height,0),r=function(t){const e=function(t){const e=[];let i,s,n,o,a,r;for(i=0,s=(t||[]).length;i<s;++i)n=t[i],({position:o,options:{stack:a,stackWeight:r=1}}=n),e.push({index:i,box:n,pos:o,horizontal:n.isHorizontal(),weight:n.weight,stack:a&&o+a,stackWeight:r});return e}(t),i=ji(e.filter((t=>t.box.fullSize)),!0),s=ji(Ni(e,"left"),!0),n=ji(Ni(e,"right")),o=ji(Ni(e,"top"),!0),a=ji(Ni(e,"bottom")),r=Wi(e,"x"),l=Wi(e,"y");return{fullSize:i,leftAndTop:s.concat(o),rightAndBottom:n.concat(l).concat(a).concat(r),chartArea:Ni(e,"chartArea"),vertical:s.concat(n).concat(l),horizontal:o.concat(a).concat(r)}}(t.boxes),l=r.vertical,h=r.horizontal;d(t.boxes,(t=>{"function"==typeof t.beforeLayout&&t.beforeLayout()}));const c=l.reduce(((t,e)=>e.box.options&&!1===e.box.options.display?t:t+1),0)||1,u=Object.freeze({outerWidth:e,outerHeight:i,padding:n,availableWidth:o,availableHeight:a,vBoxMaxWidth:o/2/c,hBoxMaxHeight:a/2}),f=Object.assign({},n);Yi(f,pi(s));const g=Object.assign({maxPadding:f,w:o,h:a,x:n.left,y:n.top},n),p=Hi(l.concat(h),u);qi(r.fullSize,g,u,p),qi(l,g,u,p),qi(h,g,u,p)&&qi(l,g,u,p),function(t){const e=t.maxPadding;function i(i){const s=Math.max(e[i]-t[i],0);return t[i]+=s,s}t.y+=i("top"),t.x+=i("left"),i("right"),i("bottom")}(g),Gi(r.leftAndTop,g,u,p),g.x+=g.w,g.y+=g.h,Gi(r.rightAndBottom,g,u,p),t.chartArea={left:g.left,top:g.top,right:g.left+g.w,bottom:g.top+g.h,height:g.h,width:g.w},d(r.chartArea,(e=>{const i=e.box;Object.assign(i,t.chartArea),i.update(g.w,g.h,{left:0,top:0,right:0,bottom:0})}))}};class Ji{acquireContext(t,e){}releaseContext(t){return!1}addEventListener(t,e,i){}removeEventListener(t,e,i){}getDevicePixelRatio(){return 1}getMaximumSize(t,e,i,s){return e=Math.max(0,e||t.width),i=i||t.height,{width:e,height:Math.max(0,s?Math.floor(e/s):i)}}isAttached(t){return!0}updateConfig(t){}}class Qi extends Ji{acquireContext(t){return t&&t.getContext&&t.getContext("2d")||null}updateConfig(t){t.options.animation=!1}}const ts={touchstart:"mousedown",touchmove:"mousemove",touchend:"mouseup",pointerenter:"mouseenter",pointerdown:"mousedown",pointermove:"mousemove",pointerup:"mouseup",pointerleave:"mouseout",pointerout:"mouseout"},es=t=>null===t||""===t;const is=!!me&&{passive:!0};function ss(t,e,i){t.canvas.removeEventListener(e,i,is)}function ns(t,e){for(const i of t)if(i===e||i.contains(e))return!0}function os(t,e,i){const s=t.canvas,n=new MutationObserver((t=>{let e=!1;for(const i of t)e=e||ns(i.addedNodes,s),e=e&&!ns(i.removedNodes,s);e&&i()}));return n.observe(document,{childList:!0,subtree:!0}),n}function as(t,e,i){const s=t.canvas,n=new MutationObserver((t=>{let e=!1;for(const i of t)e=e||ns(i.removedNodes,s),e=e&&!ns(i.addedNodes,s);e&&i()}));return n.observe(document,{childList:!0,subtree:!0}),n}const rs=new Map;let ls=0;function hs(){const t=window.devicePixelRatio;t!==ls&&(ls=t,rs.forEach(((e,i)=>{i.currentDevicePixelRatio!==t&&e()})))}function cs(t,e,i){const s=t.canvas,n=s&&ae(s);if(!n)return;const o=ht(((t,e)=>{const s=n.clientWidth;i(t,e),s<n.clientWidth&&i()}),window),a=new ResizeObserver((t=>{const e=t[0],i=e.contentRect.width,s=e.contentRect.height;0===i&&0===s||o(i,s)}));return a.observe(n),function(t,e){rs.size||window.addEventListener("resize",hs),rs.set(t,e)}(t,o),a}function ds(t,e,i){i&&i.disconnect(),"resize"===e&&function(t){rs.delete(t),rs.size||window.removeEventListener("resize",hs)}(t)}function us(t,e,i){const s=t.canvas,n=ht((e=>{null!==t.ctx&&i(function(t,e){const i=ts[t.type]||t.type,{x:s,y:n}=ue(t,e);return{type:i,chart:e,native:t,x:void 0!==s?s:null,y:void 0!==n?n:null}}(e,t))}),t,(t=>{const e=t[0];return[e,e.offsetX,e.offsetY]}));return function(t,e,i){t.addEventListener(e,i,is)}(s,e,n),n}class fs extends Ji{acquireContext(t,e){const i=t&&t.getContext&&t.getContext("2d");return i&&i.canvas===t?(function(t,e){const i=t.style,s=t.getAttribute("height"),n=t.getAttribute("width");if(t.$chartjs={initial:{height:s,width:n,style:{display:i.display,height:i.height,width:i.width}}},i.display=i.display||"block",i.boxSizing=i.boxSizing||"border-box",es(n)){const e=be(t,"width");void 0!==e&&(t.width=e)}if(es(s))if(""===t.style.height)t.height=t.width/(e||2);else{const e=be(t,"height");void 0!==e&&(t.height=e)}}(t,e),i):null}releaseContext(t){const e=t.canvas;if(!e.$chartjs)return!1;const s=e.$chartjs.initial;["height","width"].forEach((t=>{const n=s[t];i(n)?e.removeAttribute(t):e.setAttribute(t,n)}));const n=s.style||{};return Object.keys(n).forEach((t=>{e.style[t]=n[t]})),e.width=e.width,delete e.$chartjs,!0}addEventListener(t,e,i){this.removeEventListener(t,e);const s=t.$proxies||(t.$proxies={}),n={attach:os,detach:as,resize:cs}[e]||us;s[e]=n(t,e,i)}removeEventListener(t,e){const i=t.$proxies||(t.$proxies={}),s=i[e];if(!s)return;({attach:ds,detach:ds,resize:ds}[e]||ss)(t,e,s),i[e]=void 0}getDevicePixelRatio(){return window.devicePixelRatio}getMaximumSize(t,e,i,s){return ge(t,e,i,s)}isAttached(t){const e=ae(t);return!(!e||!e.isConnected)}}function gs(t){return!oe()||"undefined"!=typeof OffscreenCanvas&&t instanceof OffscreenCanvas?Qi:fs}var ps=Object.freeze({__proto__:null,_detectPlatform:gs,BasePlatform:Ji,BasicPlatform:Qi,DomPlatform:fs});const ms="transparent",bs={boolean:(t,e,i)=>i>.5?e:t,color(t,e,i){const s=Jt(t||ms),n=s.valid&&Jt(e||ms);return n&&n.valid?n.mix(s,i).hexString():e},number:(t,e,i)=>t+(e-t)*i};class xs{constructor(t,e,i,s){const n=e[i];s=bi([t.to,s,n,t.from]);const o=bi([t.from,n,s]);this._active=!0,this._fn=t.fn||bs[t.type||typeof o],this._easing=si[t.easing]||si.linear,this._start=Math.floor(Date.now()+(t.delay||0)),this._duration=this._total=Math.floor(t.duration),this._loop=!!t.loop,this._target=e,this._prop=i,this._from=o,this._to=s,this._promises=void 0}active(){return this._active}update(t,e,i){if(this._active){this._notify(!1);const s=this._target[this._prop],n=i-this._start,o=this._duration-n;this._start=i,this._duration=Math.floor(Math.max(o,t.duration)),this._total+=n,this._loop=!!t.loop,this._to=bi([t.to,e,s,t.from]),this._from=bi([t.from,s,e])}}cancel(){this._active&&(this.tick(Date.now()),this._active=!1,this._notify(!1))}tick(t){const e=t-this._start,i=this._duration,s=this._prop,n=this._from,o=this._loop,a=this._to;let r;if(this._active=n!==a&&(o||e<i),!this._active)return this._target[s]=a,void this._notify(!0);e<0?this._target[s]=n:(r=e/i%2,r=o&&r>1?2-r:r,r=this._easing(Math.min(1,Math.max(0,r))),this._target[s]=this._fn(n,a,r))}wait(){const t=this._promises||(this._promises=[]);return new Promise(((e,i)=>{t.push({res:e,rej:i})}))}_notify(t){const e=t?"res":"rej",i=this._promises||[];for(let t=0;t<i.length;t++)i[t][e]()}}ne.set("animation",{delay:void 0,duration:1e3,easing:"easeOutQuart",fn:void 0,from:void 0,loop:void 0,to:void 0,type:void 0});const _s=Object.keys(ne.animation);ne.describe("animation",{_fallback:!1,_indexable:!1,_scriptable:t=>"onProgress"!==t&&"onComplete"!==t&&"fn"!==t}),ne.set("animations",{colors:{type:"color",properties:["color","borderColor","backgroundColor"]},numbers:{type:"number",properties:["x","y","borderWidth","radius","tension"]}}),ne.describe("animations",{_fallback:"animation"}),ne.set("transitions",{active:{animation:{duration:400}},resize:{animation:{duration:0}},show:{animations:{colors:{from:"transparent"},visible:{type:"boolean",duration:0}}},hide:{animations:{colors:{to:"transparent"},visible:{type:"boolean",easing:"linear",fn:t=>0|t}}}});class ys{constructor(t,e){this._chart=t,this._properties=new Map,this.configure(e)}configure(t){if(!n(t))return;const e=this._properties;Object.getOwnPropertyNames(t).forEach((i=>{const o=t[i];if(!n(o))return;const a={};for(const t of _s)a[t]=o[t];(s(o.properties)&&o.properties||[i]).forEach((t=>{t!==i&&e.has(t)||e.set(t,a)}))}))}_animateOptions(t,e){const i=e.options,s=function(t,e){if(!e)return;let i=t.options;if(!i)return void(t.options=e);i.$shared&&(t.options=i=Object.assign({},i,{$shared:!1,$animations:{}}));return i}(t,i);if(!s)return[];const n=this._createAnimations(s,i);return i.$shared&&function(t,e){const i=[],s=Object.keys(e);for(let e=0;e<s.length;e++){const n=t[s[e]];n&&n.active()&&i.push(n.wait())}return Promise.all(i)}(t.options.$animations,i).then((()=>{t.options=i}),(()=>{})),n}_createAnimations(t,e){const i=this._properties,s=[],n=t.$animations||(t.$animations={}),o=Object.keys(e),a=Date.now();let r;for(r=o.length-1;r>=0;--r){const l=o[r];if("$"===l.charAt(0))continue;if("options"===l){s.push(...this._animateOptions(t,e));continue}const h=e[l];let c=n[l];const d=i.get(l);if(c){if(d&&c.active()){c.update(d,h,a);continue}c.cancel()}d&&d.duration?(n[l]=c=new xs(d,t,l,h),s.push(c)):t[l]=h}return s}update(t,e){if(0===this._properties.size)return void Object.assign(t,e);const i=this._createAnimations(t,e);return i.length?(mt.add(this._chart,i),!0):void 0}}function vs(t,e){const i=t&&t.options||{},s=i.reverse,n=void 0===i.min?e:0,o=void 0===i.max?e:0;return{start:s?o:n,end:s?n:o}}function ws(t,e){const i=[],s=t._getSortedDatasetMetas(e);let n,o;for(n=0,o=s.length;n<o;++n)i.push(s[n].index);return i}function Ms(t,e,i,s={}){const n=t.keys,a="single"===s.mode;let r,l,h,c;if(null!==e){for(r=0,l=n.length;r<l;++r){if(h=+n[r],h===i){if(s.all)continue;break}c=t.values[h],o(c)&&(a||0===e||z(e)===z(c))&&(e+=c)}return e}}function ks(t,e){const i=t&&t.options.stacked;return i||void 0===i&&void 0!==e.stack}function Ss(t,e,i){const s=t[e]||(t[e]={});return s[i]||(s[i]={})}function Ps(t,e,i,s){for(const n of e.getMatchingVisibleMetas(s).reverse()){const e=t[n.index];if(i&&e>0||!i&&e<0)return n.index}return null}function Ds(t,e){const{chart:i,_cachedMeta:s}=t,n=i._stacks||(i._stacks={}),{iScale:o,vScale:a,index:r}=s,l=o.axis,h=a.axis,c=function(t,e,i){return`${t.id}.${e.id}.${i.stack||i.type}`}(o,a,s),d=e.length;let u;for(let t=0;t<d;++t){const i=e[t],{[l]:o,[h]:d}=i;u=(i._stacks||(i._stacks={}))[h]=Ss(n,c,o),u[r]=d,u._top=Ps(u,a,!0,s.type),u._bottom=Ps(u,a,!1,s.type)}}function Os(t,e){const i=t.scales;return Object.keys(i).filter((t=>i[t].axis===e)).shift()}function Cs(t,e){const i=t.controller.index,s=t.vScale&&t.vScale.axis;if(s){e=e||t._parsed;for(const t of e){const e=t._stacks;if(!e||void 0===e[s]||void 0===e[s][i])return;delete e[s][i]}}}const As=t=>"reset"===t||"none"===t,Ts=(t,e)=>e?t:Object.assign({},t);class Ls{constructor(t,e){this.chart=t,this._ctx=t.ctx,this.index=e,this._cachedDataOpts={},this._cachedMeta=this.getMeta(),this._type=this._cachedMeta.type,this.options=void 0,this._parsing=!1,this._data=void 0,this._objectData=void 0,this._sharedOptions=void 0,this._drawStart=void 0,this._drawCount=void 0,this.enableOptionSharing=!1,this.supportsDecimation=!1,this.$context=void 0,this._syncList=[],this.initialize()}initialize(){const t=this._cachedMeta;this.configure(),this.linkScales(),t._stacked=ks(t.vScale,t),this.addElements()}updateIndex(t){this.index!==t&&Cs(this._cachedMeta),this.index=t}linkScales(){const t=this.chart,e=this._cachedMeta,i=this.getDataset(),s=(t,e,i,s)=>"x"===t?e:"r"===t?s:i,n=e.xAxisID=r(i.xAxisID,Os(t,"x")),o=e.yAxisID=r(i.yAxisID,Os(t,"y")),a=e.rAxisID=r(i.rAxisID,Os(t,"r")),l=e.indexAxis,h=e.iAxisID=s(l,n,o,a),c=e.vAxisID=s(l,o,n,a);e.xScale=this.getScaleForId(n),e.yScale=this.getScaleForId(o),e.rScale=this.getScaleForId(a),e.iScale=this.getScaleForId(h),e.vScale=this.getScaleForId(c)}getDataset(){return this.chart.data.datasets[this.index]}getMeta(){return this.chart.getDatasetMeta(this.index)}getScaleForId(t){return this.chart.scales[t]}_getOtherScale(t){const e=this._cachedMeta;return t===e.iScale?e.vScale:e.iScale}reset(){this._update("reset")}_destroy(){const t=this._cachedMeta;this._data&&at(this._data,this),t._stacked&&Cs(t)}_dataCheck(){const t=this.getDataset(),e=t.data||(t.data=[]),i=this._data;if(n(e))this._data=function(t){const e=Object.keys(t),i=new Array(e.length);let s,n,o;for(s=0,n=e.length;s<n;++s)o=e[s],i[s]={x:o,y:t[o]};return i}(e);else if(i!==e){if(i){at(i,this);const t=this._cachedMeta;Cs(t),t._parsed=[]}e&&Object.isExtensible(e)&&ot(e,this),this._syncList=[],this._data=e}}addElements(){const t=this._cachedMeta;this._dataCheck(),this.datasetElementType&&(t.dataset=new this.datasetElementType)}buildOrUpdateElements(t){const e=this._cachedMeta,i=this.getDataset();let s=!1;this._dataCheck();const n=e._stacked;e._stacked=ks(e.vScale,e),e.stack!==i.stack&&(s=!0,Cs(e),e.stack=i.stack),this._resyncElements(t),(s||n!==e._stacked)&&Ds(this,e._parsed)}configure(){const t=this.chart.config,e=t.datasetScopeKeys(this._type),i=t.getOptionScopes(this.getDataset(),e,!0);this.options=t.createResolver(i,this.getContext()),this._parsing=this.options.parsing,this._cachedDataOpts={}}parse(t,e){const{_cachedMeta:i,_data:o}=this,{iScale:a,_stacked:r}=i,l=a.axis;let h,c,d,u=0===t&&e===o.length||i._sorted,f=t>0&&i._parsed[t-1];if(!1===this._parsing)i._parsed=o,i._sorted=!0,d=o;else{d=s(o[t])?this.parseArrayData(i,o,t,e):n(o[t])?this.parseObjectData(i,o,t,e):this.parsePrimitiveData(i,o,t,e);const a=()=>null===c[l]||f&&c[l]<f[l];for(h=0;h<e;++h)i._parsed[h+t]=c=d[h],u&&(a()&&(u=!1),f=c);i._sorted=u}r&&Ds(this,d)}parsePrimitiveData(t,e,i,s){const{iScale:n,vScale:o}=t,a=n.axis,r=o.axis,l=n.getLabels(),h=n===o,c=new Array(s);let d,u,f;for(d=0,u=s;d<u;++d)f=d+i,c[d]={[a]:h||n.parse(l[f],f),[r]:o.parse(e[f],f)};return c}parseArrayData(t,e,i,s){const{xScale:n,yScale:o}=t,a=new Array(s);let r,l,h,c;for(r=0,l=s;r<l;++r)h=r+i,c=e[h],a[r]={x:n.parse(c[0],h),y:o.parse(c[1],h)};return a}parseObjectData(t,e,i,s){const{xScale:n,yScale:o}=t,{xAxisKey:a="x",yAxisKey:r="y"}=this._parsing,l=new Array(s);let h,c,d,u;for(h=0,c=s;h<c;++h)d=h+i,u=e[d],l[h]={x:n.parse(y(u,a),d),y:o.parse(y(u,r),d)};return l}getParsed(t){return this._cachedMeta._parsed[t]}getDataElement(t){return this._cachedMeta.data[t]}applyStack(t,e,i){const s=this.chart,n=this._cachedMeta,o=e[t.axis];return Ms({keys:ws(s,!0),values:e._stacks[t.axis]},o,n.index,{mode:i})}updateRangeFromParsed(t,e,i,s){const n=i[e.axis];let o=null===n?NaN:n;const a=s&&i._stacks[e.axis];s&&a&&(s.values=a,o=Ms(s,n,this._cachedMeta.index)),t.min=Math.min(t.min,o),t.max=Math.max(t.max,o)}getMinMax(t,e){const i=this._cachedMeta,s=i._parsed,n=i._sorted&&t===i.iScale,a=s.length,r=this._getOtherScale(t),l=((t,e,i)=>t&&!e.hidden&&e._stacked&&{keys:ws(i,!0),values:null})(e,i,this.chart),h={min:Number.POSITIVE_INFINITY,max:Number.NEGATIVE_INFINITY},{min:c,max:d}=function(t){const{min:e,max:i,minDefined:s,maxDefined:n}=t.getUserBounds();return{min:s?e:Number.NEGATIVE_INFINITY,max:n?i:Number.POSITIVE_INFINITY}}(r);let u,f;function g(){f=s[u];const e=f[r.axis];return!o(f[t.axis])||c>e||d<e}for(u=0;u<a&&(g()||(this.updateRangeFromParsed(h,t,f,l),!n));++u);if(n)for(u=a-1;u>=0;--u)if(!g()){this.updateRangeFromParsed(h,t,f,l);break}return h}getAllParsedValues(t){const e=this._cachedMeta._parsed,i=[];let s,n,a;for(s=0,n=e.length;s<n;++s)a=e[s][t.axis],o(a)&&i.push(a);return i}getMaxOverflow(){return!1}getLabelAndValue(t){const e=this._cachedMeta,i=e.iScale,s=e.vScale,n=this.getParsed(t);return{label:i?""+i.getLabelForValue(n[i.axis]):"",value:s?""+s.getLabelForValue(n[s.axis]):""}}_update(t){const e=this._cachedMeta;this.update(t||"default"),e._clip=function(t){let e,i,s,o;return n(t)?(e=t.top,i=t.right,s=t.bottom,o=t.left):e=i=s=o=t,{top:e,right:i,bottom:s,left:o,disabled:!1===t}}(r(this.options.clip,function(t,e,i){if(!1===i)return!1;const s=vs(t,i),n=vs(e,i);return{top:n.end,right:s.end,bottom:n.start,left:s.start}}(e.xScale,e.yScale,this.getMaxOverflow())))}update(t){}draw(){const t=this._ctx,e=this.chart,i=this._cachedMeta,s=i.data||[],n=e.chartArea,o=[],a=this._drawStart||0,r=this._drawCount||s.length-a,l=this.options.drawActiveElementsOnTop;let h;for(i.dataset&&i.dataset.draw(t,n,a,r),h=a;h<a+r;++h){const e=s[h];e.hidden||(e.active&&l?o.push(e):e.draw(t,n))}for(h=0;h<o.length;++h)o[h].draw(t,n)}getStyle(t,e){const i=e?"active":"default";return void 0===t&&this._cachedMeta.dataset?this.resolveDatasetElementOptions(i):this.resolveDataElementOptions(t||0,i)}getContext(t,e,i){const s=this.getDataset();let n;if(t>=0&&t<this._cachedMeta.data.length){const e=this._cachedMeta.data[t];n=e.$context||(e.$context=function(t,e,i){return _i(t,{active:!1,dataIndex:e,parsed:void 0,raw:void 0,element:i,index:e,mode:"default",type:"data"})}(this.getContext(),t,e)),n.parsed=this.getParsed(t),n.raw=s.data[t],n.index=n.dataIndex=t}else n=this.$context||(this.$context=function(t,e){return _i(t,{active:!1,dataset:void 0,datasetIndex:e,index:e,mode:"default",type:"dataset"})}(this.chart.getContext(),this.index)),n.dataset=s,n.index=n.datasetIndex=this.index;return n.active=!!e,n.mode=i,n}resolveDatasetElementOptions(t){return this._resolveElementOptions(this.datasetElementType.id,t)}resolveDataElementOptions(t,e){return this._resolveElementOptions(this.dataElementType.id,e,t)}_resolveElementOptions(t,e="default",i){const s="active"===e,n=this._cachedDataOpts,o=t+"-"+e,a=n[o],r=this.enableOptionSharing&&M(i);if(a)return Ts(a,r);const l=this.chart.config,h=l.datasetElementScopeKeys(this._type,t),c=s?[`${t}Hover`,"hover",t,""]:[t,""],d=l.getOptionScopes(this.getDataset(),h),u=Object.keys(ne.elements[t]),f=l.resolveNamedOptions(d,u,(()=>this.getContext(i,s)),c);return f.$shared&&(f.$shared=r,n[o]=Object.freeze(Ts(f,r))),f}_resolveAnimations(t,e,i){const s=this.chart,n=this._cachedDataOpts,o=`animation-${e}`,a=n[o];if(a)return a;let r;if(!1!==s.options.animation){const s=this.chart.config,n=s.datasetAnimationScopeKeys(this._type,e),o=s.getOptionScopes(this.getDataset(),n);r=s.createResolver(o,this.getContext(t,i,e))}const l=new ys(s,r&&r.animations);return r&&r._cacheable&&(n[o]=Object.freeze(l)),l}getSharedOptions(t){if(t.$shared)return this._sharedOptions||(this._sharedOptions=Object.assign({},t))}includeOptions(t,e){return!e||As(t)||this.chart._animationsDisabled}_getSharedOptions(t,e){const i=this.resolveDataElementOptions(t,e),s=this._sharedOptions,n=this.getSharedOptions(i),o=this.includeOptions(e,n)||n!==s;return this.updateSharedOptions(n,e,i),{sharedOptions:n,includeOptions:o}}updateElement(t,e,i,s){As(s)?Object.assign(t,i):this._resolveAnimations(e,s).update(t,i)}updateSharedOptions(t,e,i){t&&!As(e)&&this._resolveAnimations(void 0,e).update(t,i)}_setStyle(t,e,i,s){t.active=s;const n=this.getStyle(e,s);this._resolveAnimations(e,i,s).update(t,{options:!s&&this.getSharedOptions(n)||n})}removeHoverStyle(t,e,i){this._setStyle(t,i,"active",!1)}setHoverStyle(t,e,i){this._setStyle(t,i,"active",!0)}_removeDatasetHoverStyle(){const t=this._cachedMeta.dataset;t&&this._setStyle(t,void 0,"active",!1)}_setDatasetHoverStyle(){const t=this._cachedMeta.dataset;t&&this._setStyle(t,void 0,"active",!0)}_resyncElements(t){const e=this._data,i=this._cachedMeta.data;for(const[t,e,i]of this._syncList)this[t](e,i);this._syncList=[];const s=i.length,n=e.length,o=Math.min(n,s);o&&this.parse(0,o),n>s?this._insertElements(s,n-s,t):n<s&&this._removeElements(n,s-n)}_insertElements(t,e,i=!0){const s=this._cachedMeta,n=s.data,o=t+e;let a;const r=t=>{for(t.length+=e,a=t.length-1;a>=o;a--)t[a]=t[a-e]};for(r(n),a=t;a<o;++a)n[a]=new this.dataElementType;this._parsing&&r(s._parsed),this.parse(t,e),i&&this.updateElements(n,t,e,"reset")}updateElements(t,e,i,s){}_removeElements(t,e){const i=this._cachedMeta;if(this._parsing){const s=i._parsed.splice(t,e);i._stacked&&Cs(i,s)}i.data.splice(t,e)}_sync(t){if(this._parsing)this._syncList.push(t);else{const[e,i,s]=t;this[e](i,s)}this.chart._dataChanges.push([this.index,...t])}_onDataPush(){const t=arguments.length;this._sync(["_insertElements",this.getDataset().data.length-t,t])}_onDataPop(){this._sync(["_removeElements",this._cachedMeta.data.length-1,1])}_onDataShift(){this._sync(["_removeElements",0,1])}_onDataSplice(t,e){e&&this._sync(["_removeElements",t,e]);const i=arguments.length-2;i&&this._sync(["_insertElements",t,i])}_onDataUnshift(){this._sync(["_insertElements",0,arguments.length])}}Ls.defaults={},Ls.prototype.datasetElementType=null,Ls.prototype.dataElementType=null;class Es{constructor(){this.x=void 0,this.y=void 0,this.active=!1,this.options=void 0,this.$animations=void 0}tooltipPosition(t){const{x:e,y:i}=this.getProps(["x","y"],t);return{x:e,y:i}}hasValue(){return B(this.x)&&B(this.y)}getProps(t,e){const i=this.$animations;if(!e||!i)return this;const s={};return t.forEach((t=>{s[t]=i[t]&&i[t].active()?i[t]._to:this[t]})),s}}Es.defaults={},Es.defaultRoutes=void 0;const Rs={values:t=>s(t)?t:""+t,numeric(t,e,i){if(0===t)return"0";const s=this.chart.options.locale;let n,o=t;if(i.length>1){const e=Math.max(Math.abs(i[0].value),Math.abs(i[i.length-1].value));(e<1e-4||e>1e15)&&(n="scientific"),o=function(t,e){let i=e.length>3?e[2].value-e[1].value:e[1].value-e[0].value;Math.abs(i)>=1&&t!==Math.floor(t)&&(i=t-Math.floor(t));return i}(t,i)}const a=I(Math.abs(o)),r=Math.max(Math.min(-1*Math.floor(a),20),0),l={notation:n,minimumFractionDigits:r,maximumFractionDigits:r};return Object.assign(l,this.options.ticks.format),li(t,s,l)},logarithmic(t,e,i){if(0===t)return"0";const s=t/Math.pow(10,Math.floor(I(t)));return 1===s||2===s||5===s?Rs.numeric.call(this,t,e,i):""}};var Is={formatters:Rs};function zs(t,e){const s=t.options.ticks,n=s.maxTicksLimit||function(t){const e=t.options.offset,i=t._tickSize(),s=t._length/i+(e?0:1),n=t._maxLength/i;return Math.floor(Math.min(s,n))}(t),o=s.major.enabled?function(t){const e=[];let i,s;for(i=0,s=t.length;i<s;i++)t[i].major&&e.push(i);return e}(e):[],a=o.length,r=o[0],l=o[a-1],h=[];if(a>n)return function(t,e,i,s){let n,o=0,a=i[0];for(s=Math.ceil(s),n=0;n<t.length;n++)n===a&&(e.push(t[n]),o++,a=i[o*s])}(e,h,o,a/n),h;const c=function(t,e,i){const s=function(t){const e=t.length;let i,s;if(e<2)return!1;for(s=t[0],i=1;i<e;++i)if(t[i]-t[i-1]!==s)return!1;return s}(t),n=e.length/i;if(!s)return Math.max(n,1);const o=V(s);for(let t=0,e=o.length-1;t<e;t++){const e=o[t];if(e>n)return e}return Math.max(n,1)}(o,e,n);if(a>0){let t,s;const n=a>1?Math.round((l-r)/(a-1)):null;for(Fs(e,h,c,i(n)?0:r-n,r),t=0,s=a-1;t<s;t++)Fs(e,h,c,o[t],o[t+1]);return Fs(e,h,c,l,i(n)?e.length:l+n),h}return Fs(e,h,c),h}function Fs(t,e,i,s,n){const o=r(s,0),a=Math.min(r(n,t.length),t.length);let l,h,c,d=0;for(i=Math.ceil(i),n&&(l=n-s,i=l/Math.floor(l/i)),c=o;c<0;)d++,c=Math.round(o+d*i);for(h=Math.max(o,0);h<a;h++)h===c&&(e.push(t[h]),d++,c=Math.round(o+d*i))}ne.set("scale",{display:!0,offset:!1,reverse:!1,beginAtZero:!1,bounds:"ticks",grace:0,grid:{display:!0,lineWidth:1,drawBorder:!0,drawOnChartArea:!0,drawTicks:!0,tickLength:8,tickWidth:(t,e)=>e.lineWidth,tickColor:(t,e)=>e.color,offset:!1,borderDash:[],borderDashOffset:0,borderWidth:1},title:{display:!1,text:"",padding:{top:4,bottom:4}},ticks:{minRotation:0,maxRotation:50,mirror:!1,textStrokeWidth:0,textStrokeColor:"",padding:3,display:!0,autoSkip:!0,autoSkipPadding:3,labelOffset:0,callback:Is.formatters.values,minor:{},major:{},align:"center",crossAlign:"near",showLabelBackdrop:!1,backdropColor:"rgba(255, 255, 255, 0.75)",backdropPadding:2}}),ne.route("scale.ticks","color","","color"),ne.route("scale.grid","color","","borderColor"),ne.route("scale.grid","borderColor","","borderColor"),ne.route("scale.title","color","","color"),ne.describe("scale",{_fallback:!1,_scriptable:t=>!t.startsWith("before")&&!t.startsWith("after")&&"callback"!==t&&"parser"!==t,_indexable:t=>"borderDash"!==t&&"tickBorderDash"!==t}),ne.describe("scales",{_fallback:"scale"}),ne.describe("scale.ticks",{_scriptable:t=>"backdropPadding"!==t&&"callback"!==t,_indexable:t=>"backdropPadding"!==t});const Vs=(t,e,i)=>"top"===e||"left"===e?t[e]+i:t[e]-i;function Bs(t,e){const i=[],s=t.length/e,n=t.length;let o=0;for(;o<n;o+=s)i.push(t[Math.floor(o)]);return i}function Ns(t,e,i){const s=t.ticks.length,n=Math.min(e,s-1),o=t._startPixel,a=t._endPixel,r=1e-6;let l,h=t.getPixelForTick(n);if(!(i&&(l=1===s?Math.max(h-o,a-h):0===e?(t.getPixelForTick(1)-h)/2:(h-t.getPixelForTick(n-1))/2,h+=n<e?l:-l,h<o-r||h>a+r)))return h}function Ws(t){return t.drawTicks?t.tickLength:0}function js(t,e){if(!t.display)return 0;const i=mi(t.font,e),n=pi(t.padding);return(s(t.text)?t.text.length:1)*i.lineHeight+n.height}function Hs(t,e,i){let s=dt(t);return(i&&"right"!==e||!i&&"right"===e)&&(s=(t=>"left"===t?"right":"right"===t?"left":t)(s)),s}class $s extends Es{constructor(t){super(),this.id=t.id,this.type=t.type,this.options=void 0,this.ctx=t.ctx,this.chart=t.chart,this.top=void 0,this.bottom=void 0,this.left=void 0,this.right=void 0,this.width=void 0,this.height=void 0,this._margins={left:0,right:0,top:0,bottom:0},this.maxWidth=void 0,this.maxHeight=void 0,this.paddingTop=void 0,this.paddingBottom=void 0,this.paddingLeft=void 0,this.paddingRight=void 0,this.axis=void 0,this.labelRotation=void 0,this.min=void 0,this.max=void 0,this._range=void 0,this.ticks=[],this._gridLineItems=null,this._labelItems=null,this._labelSizes=null,this._length=0,this._maxLength=0,this._longestTextCache={},this._startPixel=void 0,this._endPixel=void 0,this._reversePixels=!1,this._userMax=void 0,this._userMin=void 0,this._suggestedMax=void 0,this._suggestedMin=void 0,this._ticksLength=0,this._borderValue=0,this._cache={},this._dataLimitsCached=!1,this.$context=void 0}init(t){this.options=t.setContext(this.getContext()),this.axis=t.axis,this._userMin=this.parse(t.min),this._userMax=this.parse(t.max),this._suggestedMin=this.parse(t.suggestedMin),this._suggestedMax=this.parse(t.suggestedMax)}parse(t,e){return t}getUserBounds(){let{_userMin:t,_userMax:e,_suggestedMin:i,_suggestedMax:s}=this;return t=a(t,Number.POSITIVE_INFINITY),e=a(e,Number.NEGATIVE_INFINITY),i=a(i,Number.POSITIVE_INFINITY),s=a(s,Number.NEGATIVE_INFINITY),{min:a(t,i),max:a(e,s),minDefined:o(t),maxDefined:o(e)}}getMinMax(t){let e,{min:i,max:s,minDefined:n,maxDefined:o}=this.getUserBounds();if(n&&o)return{min:i,max:s};const r=this.getMatchingVisibleMetas();for(let a=0,l=r.length;a<l;++a)e=r[a].controller.getMinMax(this,t),n||(i=Math.min(i,e.min)),o||(s=Math.max(s,e.max));return i=o&&i>s?s:i,s=n&&i>s?i:s,{min:a(i,a(s,i)),max:a(s,a(i,s))}}getPadding(){return{left:this.paddingLeft||0,top:this.paddingTop||0,right:this.paddingRight||0,bottom:this.paddingBottom||0}}getTicks(){return this.ticks}getLabels(){const t=this.chart.data;return this.options.labels||(this.isHorizontal()?t.xLabels:t.yLabels)||t.labels||[]}beforeLayout(){this._cache={},this._dataLimitsCached=!1}beforeUpdate(){c(this.options.beforeUpdate,[this])}update(t,e,i){const{beginAtZero:s,grace:n,ticks:o}=this.options,a=o.sampleSize;this.beforeUpdate(),this.maxWidth=t,this.maxHeight=e,this._margins=i=Object.assign({left:0,right:0,top:0,bottom:0},i),this.ticks=null,this._labelSizes=null,this._gridLineItems=null,this._labelItems=null,this.beforeSetDimensions(),this.setDimensions(),this.afterSetDimensions(),this._maxLength=this.isHorizontal()?this.width+i.left+i.right:this.height+i.top+i.bottom,this._dataLimitsCached||(this.beforeDataLimits(),this.determineDataLimits(),this.afterDataLimits(),this._range=xi(this,n,s),this._dataLimitsCached=!0),this.beforeBuildTicks(),this.ticks=this.buildTicks()||[],this.afterBuildTicks();const r=a<this.ticks.length;this._convertTicksToLabels(r?Bs(this.ticks,a):this.ticks),this.configure(),this.beforeCalculateLabelRotation(),this.calculateLabelRotation(),this.afterCalculateLabelRotation(),o.display&&(o.autoSkip||"auto"===o.source)&&(this.ticks=zs(this,this.ticks),this._labelSizes=null,this.afterAutoSkip()),r&&this._convertTicksToLabels(this.ticks),this.beforeFit(),this.fit(),this.afterFit(),this.afterUpdate()}configure(){let t,e,i=this.options.reverse;this.isHorizontal()?(t=this.left,e=this.right):(t=this.top,e=this.bottom,i=!i),this._startPixel=t,this._endPixel=e,this._reversePixels=i,this._length=e-t,this._alignToPixels=this.options.alignToPixels}afterUpdate(){c(this.options.afterUpdate,[this])}beforeSetDimensions(){c(this.options.beforeSetDimensions,[this])}setDimensions(){this.isHorizontal()?(this.width=this.maxWidth,this.left=0,this.right=this.width):(this.height=this.maxHeight,this.top=0,this.bottom=this.height),this.paddingLeft=0,this.paddingTop=0,this.paddingRight=0,this.paddingBottom=0}afterSetDimensions(){c(this.options.afterSetDimensions,[this])}_callHooks(t){this.chart.notifyPlugins(t,this.getContext()),c(this.options[t],[this])}beforeDataLimits(){this._callHooks("beforeDataLimits")}determineDataLimits(){}afterDataLimits(){this._callHooks("afterDataLimits")}beforeBuildTicks(){this._callHooks("beforeBuildTicks")}buildTicks(){return[]}afterBuildTicks(){this._callHooks("afterBuildTicks")}beforeTickToLabelConversion(){c(this.options.beforeTickToLabelConversion,[this])}generateTickLabels(t){const e=this.options.ticks;let i,s,n;for(i=0,s=t.length;i<s;i++)n=t[i],n.label=c(e.callback,[n.value,i,t],this)}afterTickToLabelConversion(){c(this.options.afterTickToLabelConversion,[this])}beforeCalculateLabelRotation(){c(this.options.beforeCalculateLabelRotation,[this])}calculateLabelRotation(){const t=this.options,e=t.ticks,i=this.ticks.length,s=e.minRotation||0,n=e.maxRotation;let o,a,r,l=s;if(!this._isVisible()||!e.display||s>=n||i<=1||!this.isHorizontal())return void(this.labelRotation=s);const h=this._getLabelSizes(),c=h.widest.width,d=h.highest.height,u=Z(this.chart.width-c,0,this.maxWidth);o=t.offset?this.maxWidth/i:u/(i-1),c+6>o&&(o=u/(i-(t.offset?.5:1)),a=this.maxHeight-Ws(t.grid)-e.padding-js(t.title,this.chart.options.font),r=Math.sqrt(c*c+d*d),l=$(Math.min(Math.asin(Z((h.highest.height+6)/o,-1,1)),Math.asin(Z(a/r,-1,1))-Math.asin(Z(d/r,-1,1)))),l=Math.max(s,Math.min(n,l))),this.labelRotation=l}afterCalculateLabelRotation(){c(this.options.afterCalculateLabelRotation,[this])}afterAutoSkip(){}beforeFit(){c(this.options.beforeFit,[this])}fit(){const t={width:0,height:0},{chart:e,options:{ticks:i,title:s,grid:n}}=this,o=this._isVisible(),a=this.isHorizontal();if(o){const o=js(s,e.options.font);if(a?(t.width=this.maxWidth,t.height=Ws(n)+o):(t.height=this.maxHeight,t.width=Ws(n)+o),i.display&&this.ticks.length){const{first:e,last:s,widest:n,highest:o}=this._getLabelSizes(),r=2*i.padding,l=H(this.labelRotation),h=Math.cos(l),c=Math.sin(l);if(a){const e=i.mirror?0:c*n.width+h*o.height;t.height=Math.min(this.maxHeight,t.height+e+r)}else{const e=i.mirror?0:h*n.width+c*o.height;t.width=Math.min(this.maxWidth,t.width+e+r)}this._calculatePadding(e,s,c,h)}}this._handleMargins(),a?(this.width=this._length=e.width-this._margins.left-this._margins.right,this.height=t.height):(this.width=t.width,this.height=this._length=e.height-this._margins.top-this._margins.bottom)}_calculatePadding(t,e,i,s){const{ticks:{align:n,padding:o},position:a}=this.options,r=0!==this.labelRotation,l="top"!==a&&"x"===this.axis;if(this.isHorizontal()){const a=this.getPixelForTick(0)-this.left,h=this.right-this.getPixelForTick(this.ticks.length-1);let c=0,d=0;r?l?(c=s*t.width,d=i*e.height):(c=i*t.height,d=s*e.width):"start"===n?d=e.width:"end"===n?c=t.width:"inner"!==n&&(c=t.width/2,d=e.width/2),this.paddingLeft=Math.max((c-a+o)*this.width/(this.width-a),0),this.paddingRight=Math.max((d-h+o)*this.width/(this.width-h),0)}else{let i=e.height/2,s=t.height/2;"start"===n?(i=0,s=t.height):"end"===n&&(i=e.height,s=0),this.paddingTop=i+o,this.paddingBottom=s+o}}_handleMargins(){this._margins&&(this._margins.left=Math.max(this.paddingLeft,this._margins.left),this._margins.top=Math.max(this.paddingTop,this._margins.top),this._margins.right=Math.max(this.paddingRight,this._margins.right),this._margins.bottom=Math.max(this.paddingBottom,this._margins.bottom))}afterFit(){c(this.options.afterFit,[this])}isHorizontal(){const{axis:t,position:e}=this.options;return"top"===e||"bottom"===e||"x"===t}isFullSize(){return this.options.fullSize}_convertTicksToLabels(t){let e,s;for(this.beforeTickToLabelConversion(),this.generateTickLabels(t),e=0,s=t.length;e<s;e++)i(t[e].label)&&(t.splice(e,1),s--,e--);this.afterTickToLabelConversion()}_getLabelSizes(){let t=this._labelSizes;if(!t){const e=this.options.ticks.sampleSize;let i=this.ticks;e<i.length&&(i=Bs(i,e)),this._labelSizes=t=this._computeLabelSizes(i,i.length)}return t}_computeLabelSizes(t,e){const{ctx:n,_longestTextCache:o}=this,a=[],r=[];let l,h,c,u,f,g,p,m,b,x,_,y=0,v=0;for(l=0;l<e;++l){if(u=t[l].label,f=this._resolveTickFontOptions(l),n.font=g=f.string,p=o[g]=o[g]||{data:{},gc:[]},m=f.lineHeight,b=x=0,i(u)||s(u)){if(s(u))for(h=0,c=u.length;h<c;++h)_=u[h],i(_)||s(_)||(b=_e(n,p.data,p.gc,b,_),x+=m)}else b=_e(n,p.data,p.gc,b,u),x=m;a.push(b),r.push(x),y=Math.max(b,y),v=Math.max(x,v)}!function(t,e){d(t,(t=>{const i=t.gc,s=i.length/2;let n;if(s>e){for(n=0;n<s;++n)delete t.data[i[n]];i.splice(0,s)}}))}(o,e);const w=a.indexOf(y),M=r.indexOf(v),k=t=>({width:a[t]||0,height:r[t]||0});return{first:k(0),last:k(e-1),widest:k(w),highest:k(M),widths:a,heights:r}}getLabelForValue(t){return t}getPixelForValue(t,e){return NaN}getValueForPixel(t){}getPixelForTick(t){const e=this.ticks;return t<0||t>e.length-1?null:this.getPixelForValue(e[t].value)}getPixelForDecimal(t){this._reversePixels&&(t=1-t);const e=this._startPixel+t*this._length;return J(this._alignToPixels?ve(this.chart,e,0):e)}getDecimalForPixel(t){const e=(t-this._startPixel)/this._length;return this._reversePixels?1-e:e}getBasePixel(){return this.getPixelForValue(this.getBaseValue())}getBaseValue(){const{min:t,max:e}=this;return t<0&&e<0?e:t>0&&e>0?t:0}getContext(t){const e=this.ticks||[];if(t>=0&&t<e.length){const i=e[t];return i.$context||(i.$context=function(t,e,i){return _i(t,{tick:i,index:e,type:"tick"})}(this.getContext(),t,i))}return this.$context||(this.$context=_i(this.chart.getContext(),{scale:this,type:"scale"}))}_tickSize(){const t=this.options.ticks,e=H(this.labelRotation),i=Math.abs(Math.cos(e)),s=Math.abs(Math.sin(e)),n=this._getLabelSizes(),o=t.autoSkipPadding||0,a=n?n.widest.width+o:0,r=n?n.highest.height+o:0;return this.isHorizontal()?r*i>a*s?a/i:r/s:r*s<a*i?r/i:a/s}_isVisible(){const t=this.options.display;return"auto"!==t?!!t:this.getMatchingVisibleMetas().length>0}_computeGridLineItems(t){const e=this.axis,i=this.chart,s=this.options,{grid:o,position:a}=s,l=o.offset,h=this.isHorizontal(),c=this.ticks.length+(l?1:0),d=Ws(o),u=[],f=o.setContext(this.getContext()),g=f.drawBorder?f.borderWidth:0,p=g/2,m=function(t){return ve(i,t,g)};let b,x,_,y,v,w,M,k,S,P,D,O;if("top"===a)b=m(this.bottom),w=this.bottom-d,k=b-p,P=m(t.top)+p,O=t.bottom;else if("bottom"===a)b=m(this.top),P=t.top,O=m(t.bottom)-p,w=b+p,k=this.top+d;else if("left"===a)b=m(this.right),v=this.right-d,M=b-p,S=m(t.left)+p,D=t.right;else if("right"===a)b=m(this.left),S=t.left,D=m(t.right)-p,v=b+p,M=this.left+d;else if("x"===e){if("center"===a)b=m((t.top+t.bottom)/2+.5);else if(n(a)){const t=Object.keys(a)[0],e=a[t];b=m(this.chart.scales[t].getPixelForValue(e))}P=t.top,O=t.bottom,w=b+p,k=w+d}else if("y"===e){if("center"===a)b=m((t.left+t.right)/2);else if(n(a)){const t=Object.keys(a)[0],e=a[t];b=m(this.chart.scales[t].getPixelForValue(e))}v=b-p,M=v-d,S=t.left,D=t.right}const C=r(s.ticks.maxTicksLimit,c),A=Math.max(1,Math.ceil(c/C));for(x=0;x<c;x+=A){const t=o.setContext(this.getContext(x)),e=t.lineWidth,s=t.color,n=t.borderDash||[],a=t.borderDashOffset,r=t.tickWidth,c=t.tickColor,d=t.tickBorderDash||[],f=t.tickBorderDashOffset;_=Ns(this,x,l),void 0!==_&&(y=ve(i,_,e),h?v=M=S=D=y:w=k=P=O=y,u.push({tx1:v,ty1:w,tx2:M,ty2:k,x1:S,y1:P,x2:D,y2:O,width:e,color:s,borderDash:n,borderDashOffset:a,tickWidth:r,tickColor:c,tickBorderDash:d,tickBorderDashOffset:f}))}return this._ticksLength=c,this._borderValue=b,u}_computeLabelItems(t){const e=this.axis,i=this.options,{position:o,ticks:a}=i,r=this.isHorizontal(),l=this.ticks,{align:h,crossAlign:c,padding:d,mirror:u}=a,f=Ws(i.grid),g=f+d,p=u?-d:g,m=-H(this.labelRotation),b=[];let x,_,y,v,w,M,k,S,P,D,O,C,A="middle";if("top"===o)M=this.bottom-p,k=this._getXAxisLabelAlignment();else if("bottom"===o)M=this.top+p,k=this._getXAxisLabelAlignment();else if("left"===o){const t=this._getYAxisLabelAlignment(f);k=t.textAlign,w=t.x}else if("right"===o){const t=this._getYAxisLabelAlignment(f);k=t.textAlign,w=t.x}else if("x"===e){if("center"===o)M=(t.top+t.bottom)/2+g;else if(n(o)){const t=Object.keys(o)[0],e=o[t];M=this.chart.scales[t].getPixelForValue(e)+g}k=this._getXAxisLabelAlignment()}else if("y"===e){if("center"===o)w=(t.left+t.right)/2-g;else if(n(o)){const t=Object.keys(o)[0],e=o[t];w=this.chart.scales[t].getPixelForValue(e)}k=this._getYAxisLabelAlignment(f).textAlign}"y"===e&&("start"===h?A="top":"end"===h&&(A="bottom"));const T=this._getLabelSizes();for(x=0,_=l.length;x<_;++x){y=l[x],v=y.label;const t=a.setContext(this.getContext(x));S=this.getPixelForTick(x)+a.labelOffset,P=this._resolveTickFontOptions(x),D=P.lineHeight,O=s(v)?v.length:1;const e=O/2,i=t.color,n=t.textStrokeColor,h=t.textStrokeWidth;let d,f=k;if(r?(w=S,"inner"===k&&(f=x===_-1?this.options.reverse?"left":"right":0===x?this.options.reverse?"right":"left":"center"),C="top"===o?"near"===c||0!==m?-O*D+D/2:"center"===c?-T.highest.height/2-e*D+D:-T.highest.height+D/2:"near"===c||0!==m?D/2:"center"===c?T.highest.height/2-e*D:T.highest.height-O*D,u&&(C*=-1)):(M=S,C=(1-O)*D/2),t.showLabelBackdrop){const e=pi(t.backdropPadding),i=T.heights[x],s=T.widths[x];let n=M+C-e.top,o=w-e.left;switch(A){case"middle":n-=i/2;break;case"bottom":n-=i}switch(k){case"center":o-=s/2;break;case"right":o-=s}d={left:o,top:n,width:s+e.width,height:i+e.height,color:t.backdropColor}}b.push({rotation:m,label:v,font:P,color:i,strokeColor:n,strokeWidth:h,textOffset:C,textAlign:f,textBaseline:A,translation:[w,M],backdrop:d})}return b}_getXAxisLabelAlignment(){const{position:t,ticks:e}=this.options;if(-H(this.labelRotation))return"top"===t?"left":"right";let i="center";return"start"===e.align?i="left":"end"===e.align?i="right":"inner"===e.align&&(i="inner"),i}_getYAxisLabelAlignment(t){const{position:e,ticks:{crossAlign:i,mirror:s,padding:n}}=this.options,o=t+n,a=this._getLabelSizes().widest.width;let r,l;return"left"===e?s?(l=this.right+n,"near"===i?r="left":"center"===i?(r="center",l+=a/2):(r="right",l+=a)):(l=this.right-o,"near"===i?r="right":"center"===i?(r="center",l-=a/2):(r="left",l=this.left)):"right"===e?s?(l=this.left+n,"near"===i?r="right":"center"===i?(r="center",l-=a/2):(r="left",l-=a)):(l=this.left+o,"near"===i?r="left":"center"===i?(r="center",l+=a/2):(r="right",l=this.right)):r="right",{textAlign:r,x:l}}_computeLabelArea(){if(this.options.ticks.mirror)return;const t=this.chart,e=this.options.position;return"left"===e||"right"===e?{top:0,left:this.left,bottom:t.height,right:this.right}:"top"===e||"bottom"===e?{top:this.top,left:0,bottom:this.bottom,right:t.width}:void 0}drawBackground(){const{ctx:t,options:{backgroundColor:e},left:i,top:s,width:n,height:o}=this;e&&(t.save(),t.fillStyle=e,t.fillRect(i,s,n,o),t.restore())}getLineWidthForValue(t){const e=this.options.grid;if(!this._isVisible()||!e.display)return 0;const i=this.ticks.findIndex((e=>e.value===t));if(i>=0){return e.setContext(this.getContext(i)).lineWidth}return 0}drawGrid(t){const e=this.options.grid,i=this.ctx,s=this._gridLineItems||(this._gridLineItems=this._computeGridLineItems(t));let n,o;const a=(t,e,s)=>{s.width&&s.color&&(i.save(),i.lineWidth=s.width,i.strokeStyle=s.color,i.setLineDash(s.borderDash||[]),i.lineDashOffset=s.borderDashOffset,i.beginPath(),i.moveTo(t.x,t.y),i.lineTo(e.x,e.y),i.stroke(),i.restore())};if(e.display)for(n=0,o=s.length;n<o;++n){const t=s[n];e.drawOnChartArea&&a({x:t.x1,y:t.y1},{x:t.x2,y:t.y2},t),e.drawTicks&&a({x:t.tx1,y:t.ty1},{x:t.tx2,y:t.ty2},{color:t.tickColor,width:t.tickWidth,borderDash:t.tickBorderDash,borderDashOffset:t.tickBorderDashOffset})}}drawBorder(){const{chart:t,ctx:e,options:{grid:i}}=this,s=i.setContext(this.getContext()),n=i.drawBorder?s.borderWidth:0;if(!n)return;const o=i.setContext(this.getContext(0)).lineWidth,a=this._borderValue;let r,l,h,c;this.isHorizontal()?(r=ve(t,this.left,n)-n/2,l=ve(t,this.right,o)+o/2,h=c=a):(h=ve(t,this.top,n)-n/2,c=ve(t,this.bottom,o)+o/2,r=l=a),e.save(),e.lineWidth=s.borderWidth,e.strokeStyle=s.borderColor,e.beginPath(),e.moveTo(r,h),e.lineTo(l,c),e.stroke(),e.restore()}drawLabels(t){if(!this.options.ticks.display)return;const e=this.ctx,i=this._computeLabelArea();i&&Pe(e,i);const s=this._labelItems||(this._labelItems=this._computeLabelItems(t));let n,o;for(n=0,o=s.length;n<o;++n){const t=s[n],i=t.font,o=t.label;t.backdrop&&(e.fillStyle=t.backdrop.color,e.fillRect(t.backdrop.left,t.backdrop.top,t.backdrop.width,t.backdrop.height)),Ae(e,o,0,t.textOffset,i,t)}i&&De(e)}drawTitle(){const{ctx:t,options:{position:e,title:i,reverse:o}}=this;if(!i.display)return;const a=mi(i.font),r=pi(i.padding),l=i.align;let h=a.lineHeight/2;"bottom"===e||"center"===e||n(e)?(h+=r.bottom,s(i.text)&&(h+=a.lineHeight*(i.text.length-1))):h+=r.top;const{titleX:c,titleY:d,maxWidth:u,rotation:f}=function(t,e,i,s){const{top:o,left:a,bottom:r,right:l,chart:h}=t,{chartArea:c,scales:d}=h;let u,f,g,p=0;const m=r-o,b=l-a;if(t.isHorizontal()){if(f=ut(s,a,l),n(i)){const t=Object.keys(i)[0],s=i[t];g=d[t].getPixelForValue(s)+m-e}else g="center"===i?(c.bottom+c.top)/2+m-e:Vs(t,i,e);u=l-a}else{if(n(i)){const t=Object.keys(i)[0],s=i[t];f=d[t].getPixelForValue(s)-b+e}else f="center"===i?(c.left+c.right)/2-b+e:Vs(t,i,e);g=ut(s,r,o),p="left"===i?-L:L}return{titleX:f,titleY:g,maxWidth:u,rotation:p}}(this,h,e,l);Ae(t,i.text,0,0,a,{color:i.color,maxWidth:u,rotation:f,textAlign:Hs(l,e,o),textBaseline:"middle",translation:[c,d]})}draw(t){this._isVisible()&&(this.drawBackground(),this.drawGrid(t),this.drawBorder(),this.drawTitle(),this.drawLabels(t))}_layers(){const t=this.options,e=t.ticks&&t.ticks.z||0,i=r(t.grid&&t.grid.z,-1);return this._isVisible()&&this.draw===$s.prototype.draw?[{z:i,draw:t=>{this.drawBackground(),this.drawGrid(t),this.drawTitle()}},{z:i+1,draw:()=>{this.drawBorder()}},{z:e,draw:t=>{this.drawLabels(t)}}]:[{z:e,draw:t=>{this.draw(t)}}]}getMatchingVisibleMetas(t){const e=this.chart.getSortedVisibleDatasetMetas(),i=this.axis+"AxisID",s=[];let n,o;for(n=0,o=e.length;n<o;++n){const o=e[n];o[i]!==this.id||t&&o.type!==t||s.push(o)}return s}_resolveTickFontOptions(t){return mi(this.options.ticks.setContext(this.getContext(t)).font)}_maxDigits(){const t=this._resolveTickFontOptions(0).lineHeight;return(this.isHorizontal()?this.width:this.height)/t}}class Ys{constructor(t,e,i){this.type=t,this.scope=e,this.override=i,this.items=Object.create(null)}isForType(t){return Object.prototype.isPrototypeOf.call(this.type.prototype,t.prototype)}register(t){const e=Object.getPrototypeOf(t);let i;(function(t){return"id"in t&&"defaults"in t})(e)&&(i=this.register(e));const s=this.items,n=t.id,o=this.scope+"."+n;if(!n)throw new Error("class does not have id: "+t);return n in s||(s[n]=t,function(t,e,i){const s=m(Object.create(null),[i?ne.get(i):{},ne.get(e),t.defaults]);ne.set(e,s),t.defaultRoutes&&function(t,e){Object.keys(e).forEach((i=>{const s=i.split("."),n=s.pop(),o=[t].concat(s).join("."),a=e[i].split("."),r=a.pop(),l=a.join(".");ne.route(o,n,l,r)}))}(e,t.defaultRoutes);t.descriptors&&ne.describe(e,t.descriptors)}(t,o,i),this.override&&ne.override(t.id,t.overrides)),o}get(t){return this.items[t]}unregister(t){const e=this.items,i=t.id,s=this.scope;i in e&&delete e[i],s&&i in ne[s]&&(delete ne[s][i],this.override&&delete te[i])}}var Us=new class{constructor(){this.controllers=new Ys(Ls,"datasets",!0),this.elements=new Ys(Es,"elements"),this.plugins=new Ys(Object,"plugins"),this.scales=new Ys($s,"scales"),this._typedRegistries=[this.controllers,this.scales,this.elements]}add(...t){this._each("register",t)}remove(...t){this._each("unregister",t)}addControllers(...t){this._each("register",t,this.controllers)}addElements(...t){this._each("register",t,this.elements)}addPlugins(...t){this._each("register",t,this.plugins)}addScales(...t){this._each("register",t,this.scales)}getController(t){return this._get(t,this.controllers,"controller")}getElement(t){return this._get(t,this.elements,"element")}getPlugin(t){return this._get(t,this.plugins,"plugin")}getScale(t){return this._get(t,this.scales,"scale")}removeControllers(...t){this._each("unregister",t,this.controllers)}removeElements(...t){this._each("unregister",t,this.elements)}removePlugins(...t){this._each("unregister",t,this.plugins)}removeScales(...t){this._each("unregister",t,this.scales)}_each(t,e,i){[...e].forEach((e=>{const s=i||this._getRegistryForType(e);i||s.isForType(e)||s===this.plugins&&e.id?this._exec(t,s,e):d(e,(e=>{const s=i||this._getRegistryForType(e);this._exec(t,s,e)}))}))}_exec(t,e,i){const s=w(t);c(i["before"+s],[],i),e[t](i),c(i["after"+s],[],i)}_getRegistryForType(t){for(let e=0;e<this._typedRegistries.length;e++){const i=this._typedRegistries[e];if(i.isForType(t))return i}return this.plugins}_get(t,e,i){const s=e.get(t);if(void 0===s)throw new Error('"'+t+'" is not a registered '+i+".");return s}};class Xs{constructor(){this._init=[]}notify(t,e,i,s){"beforeInit"===e&&(this._init=this._createDescriptors(t,!0),this._notify(this._init,t,"install"));const n=s?this._descriptors(t).filter(s):this._descriptors(t),o=this._notify(n,t,e,i);return"afterDestroy"===e&&(this._notify(n,t,"stop"),this._notify(this._init,t,"uninstall")),o}_notify(t,e,i,s){s=s||{};for(const n of t){const t=n.plugin;if(!1===c(t[i],[e,s,n.options],t)&&s.cancelable)return!1}return!0}invalidate(){i(this._cache)||(this._oldCache=this._cache,this._cache=void 0)}_descriptors(t){if(this._cache)return this._cache;const e=this._cache=this._createDescriptors(t);return this._notifyStateChanges(t),e}_createDescriptors(t,e){const i=t&&t.config,s=r(i.options&&i.options.plugins,{}),n=function(t){const e={},i=[],s=Object.keys(Us.plugins.items);for(let t=0;t<s.length;t++)i.push(Us.getPlugin(s[t]));const n=t.plugins||[];for(let t=0;t<n.length;t++){const s=n[t];-1===i.indexOf(s)&&(i.push(s),e[s.id]=!0)}return{plugins:i,localIds:e}}(i);return!1!==s||e?function(t,{plugins:e,localIds:i},s,n){const o=[],a=t.getContext();for(const r of e){const e=r.id,l=qs(s[e],n);null!==l&&o.push({plugin:r,options:Ks(t.config,{plugin:r,local:i[e]},l,a)})}return o}(t,n,s,e):[]}_notifyStateChanges(t){const e=this._oldCache||[],i=this._cache,s=(t,e)=>t.filter((t=>!e.some((e=>t.plugin.id===e.plugin.id))));this._notify(s(e,i),t,"stop"),this._notify(s(i,e),t,"start")}}function qs(t,e){return e||!1!==t?!0===t?{}:t:null}function Ks(t,{plugin:e,local:i},s,n){const o=t.pluginScopeKeys(e),a=t.getOptionScopes(s,o);return i&&e.defaults&&a.push(e.defaults),t.createResolver(a,n,[""],{scriptable:!1,indexable:!1,allKeys:!0})}function Gs(t,e){const i=ne.datasets[t]||{};return((e.datasets||{})[t]||{}).indexAxis||e.indexAxis||i.indexAxis||"x"}function Zs(t,e){return"x"===t||"y"===t?t:e.axis||("top"===(i=e.position)||"bottom"===i?"x":"left"===i||"right"===i?"y":void 0)||t.charAt(0).toLowerCase();var i}function Js(t){const e=t.options||(t.options={});e.plugins=r(e.plugins,{}),e.scales=function(t,e){const i=te[t.type]||{scales:{}},s=e.scales||{},o=Gs(t.type,e),a=Object.create(null),r=Object.create(null);return Object.keys(s).forEach((t=>{const e=s[t];if(!n(e))return console.error(`Invalid scale configuration for scale: ${t}`);if(e._proxy)return console.warn(`Ignoring resolver passed as options for scale: ${t}`);const l=Zs(t,e),h=function(t,e){return t===e?"_index_":"_value_"}(l,o),c=i.scales||{};a[l]=a[l]||t,r[t]=b(Object.create(null),[{axis:l},e,c[l],c[h]])})),t.data.datasets.forEach((i=>{const n=i.type||t.type,o=i.indexAxis||Gs(n,e),l=(te[n]||{}).scales||{};Object.keys(l).forEach((t=>{const e=function(t,e){let i=t;return"_index_"===t?i=e:"_value_"===t&&(i="x"===e?"y":"x"),i}(t,o),n=i[e+"AxisID"]||a[e]||e;r[n]=r[n]||Object.create(null),b(r[n],[{axis:e},s[n],l[t]])}))})),Object.keys(r).forEach((t=>{const e=r[t];b(e,[ne.scales[e.type],ne.scale])})),r}(t,e)}function Qs(t){return(t=t||{}).datasets=t.datasets||[],t.labels=t.labels||[],t}const tn=new Map,en=new Set;function sn(t,e){let i=tn.get(t);return i||(i=e(),tn.set(t,i),en.add(i)),i}const nn=(t,e,i)=>{const s=y(e,i);void 0!==s&&t.add(s)};class on{constructor(t){this._config=function(t){return(t=t||{}).data=Qs(t.data),Js(t),t}(t),this._scopeCache=new Map,this._resolverCache=new Map}get platform(){return this._config.platform}get type(){return this._config.type}set type(t){this._config.type=t}get data(){return this._config.data}set data(t){this._config.data=Qs(t)}get options(){return this._config.options}set options(t){this._config.options=t}get plugins(){return this._config.plugins}update(){const t=this._config;this.clearCache(),Js(t)}clearCache(){this._scopeCache.clear(),this._resolverCache.clear()}datasetScopeKeys(t){return sn(t,(()=>[[`datasets.${t}`,""]]))}datasetAnimationScopeKeys(t,e){return sn(`${t}.transition.${e}`,(()=>[[`datasets.${t}.transitions.${e}`,`transitions.${e}`],[`datasets.${t}`,""]]))}datasetElementScopeKeys(t,e){return sn(`${t}-${e}`,(()=>[[`datasets.${t}.elements.${e}`,`datasets.${t}`,`elements.${e}`,""]]))}pluginScopeKeys(t){const e=t.id;return sn(`${this.type}-plugin-${e}`,(()=>[[`plugins.${e}`,...t.additionalOptionScopes||[]]]))}_cachedScopes(t,e){const i=this._scopeCache;let s=i.get(t);return s&&!e||(s=new Map,i.set(t,s)),s}getOptionScopes(t,e,i){const{options:s,type:n}=this,o=this._cachedScopes(t,i),a=o.get(e);if(a)return a;const r=new Set;e.forEach((e=>{t&&(r.add(t),e.forEach((e=>nn(r,t,e)))),e.forEach((t=>nn(r,s,t))),e.forEach((t=>nn(r,te[n]||{},t))),e.forEach((t=>nn(r,ne,t))),e.forEach((t=>nn(r,ee,t)))}));const l=Array.from(r);return 0===l.length&&l.push(Object.create(null)),en.has(e)&&o.set(e,l),l}chartOptionScopes(){const{options:t,type:e}=this;return[t,te[e]||{},ne.datasets[e]||{},{type:e},ne,ee]}resolveNamedOptions(t,e,i,n=[""]){const o={$shared:!0},{resolver:a,subPrefixes:r}=an(this._resolverCache,t,n);let l=a;if(function(t,e){const{isScriptable:i,isIndexable:n}=Ie(t);for(const o of e){const e=i(o),a=n(o),r=(a||e)&&t[o];if(e&&(k(r)||rn(r))||a&&s(r))return!0}return!1}(a,e)){o.$shared=!1;l=Re(a,i=k(i)?i():i,this.createResolver(t,i,r))}for(const t of e)o[t]=l[t];return o}createResolver(t,e,i=[""],s){const{resolver:o}=an(this._resolverCache,t,i);return n(e)?Re(o,e,void 0,s):o}}function an(t,e,i){let s=t.get(e);s||(s=new Map,t.set(e,s));const n=i.join();let o=s.get(n);if(!o){o={resolver:Ee(e,i),subPrefixes:i.filter((t=>!t.toLowerCase().includes("hover")))},s.set(n,o)}return o}const rn=t=>n(t)&&Object.getOwnPropertyNames(t).reduce(((e,i)=>e||k(t[i])),!1);const ln=["top","bottom","left","right","chartArea"];function hn(t,e){return"top"===t||"bottom"===t||-1===ln.indexOf(t)&&"x"===e}function cn(t,e){return function(i,s){return i[t]===s[t]?i[e]-s[e]:i[t]-s[t]}}function dn(t){const e=t.chart,i=e.options.animation;e.notifyPlugins("afterRender"),c(i&&i.onComplete,[t],e)}function un(t){const e=t.chart,i=e.options.animation;c(i&&i.onProgress,[t],e)}function fn(t){return oe()&&"string"==typeof t?t=document.getElementById(t):t&&t.length&&(t=t[0]),t&&t.canvas&&(t=t.canvas),t}const gn={},pn=t=>{const e=fn(t);return Object.values(gn).filter((t=>t.canvas===e)).pop()};function mn(t,e,i){const s=Object.keys(t);for(const n of s){const s=+n;if(s>=e){const o=t[n];delete t[n],(i>0||s>e)&&(t[s+i]=o)}}}class bn{constructor(t,i){const s=this.config=new on(i),n=fn(t),o=pn(n);if(o)throw new Error("Canvas is already in use. Chart with ID '"+o.id+"' must be destroyed before the canvas with ID '"+o.canvas.id+"' can be reused.");const a=s.createResolver(s.chartOptionScopes(),this.getContext());this.platform=new(s.platform||gs(n)),this.platform.updateConfig(s);const r=this.platform.acquireContext(n,a.aspectRatio),l=r&&r.canvas,h=l&&l.height,c=l&&l.width;this.id=e(),this.ctx=r,this.canvas=l,this.width=c,this.height=h,this._options=a,this._aspectRatio=this.aspectRatio,this._layers=[],this._metasets=[],this._stacks=void 0,this.boxes=[],this.currentDevicePixelRatio=void 0,this.chartArea=void 0,this._active=[],this._lastEvent=void 0,this._listeners={},this._responsiveListeners=void 0,this._sortedMetasets=[],this.scales={},this._plugins=new Xs,this.$proxies={},this._hiddenIndices={},this.attached=!1,this._animationsDisabled=void 0,this.$context=void 0,this._doResize=ct((t=>this.update(t)),a.resizeDelay||0),this._dataChanges=[],gn[this.id]=this,r&&l?(mt.listen(this,"complete",dn),mt.listen(this,"progress",un),this._initialize(),this.attached&&this.update()):console.error("Failed to create chart: can't acquire context from the given item")}get aspectRatio(){const{options:{aspectRatio:t,maintainAspectRatio:e},width:s,height:n,_aspectRatio:o}=this;return i(t)?e&&o?o:n?s/n:null:t}get data(){return this.config.data}set data(t){this.config.data=t}get options(){return this._options}set options(t){this.config.options=t}_initialize(){return this.notifyPlugins("beforeInit"),this.options.responsive?this.resize():pe(this,this.options.devicePixelRatio),this.bindEvents(),this.notifyPlugins("afterInit"),this}clear(){return we(this.canvas,this.ctx),this}stop(){return mt.stop(this),this}resize(t,e){mt.running(this)?this._resizeBeforeDraw={width:t,height:e}:this._resize(t,e)}_resize(t,e){const i=this.options,s=this.canvas,n=i.maintainAspectRatio&&this.aspectRatio,o=this.platform.getMaximumSize(s,t,e,n),a=i.devicePixelRatio||this.platform.getDevicePixelRatio(),r=this.width?"resize":"attach";this.width=o.width,this.height=o.height,this._aspectRatio=this.aspectRatio,pe(this,a,!0)&&(this.notifyPlugins("resize",{size:o}),c(i.onResize,[this,o],this),this.attached&&this._doResize(r)&&this.render())}ensureScalesHaveIDs(){d(this.options.scales||{},((t,e)=>{t.id=e}))}buildOrUpdateScales(){const t=this.options,e=t.scales,i=this.scales,s=Object.keys(i).reduce(((t,e)=>(t[e]=!1,t)),{});let n=[];e&&(n=n.concat(Object.keys(e).map((t=>{const i=e[t],s=Zs(t,i),n="r"===s,o="x"===s;return{options:i,dposition:n?"chartArea":o?"bottom":"left",dtype:n?"radialLinear":o?"category":"linear"}})))),d(n,(e=>{const n=e.options,o=n.id,a=Zs(o,n),l=r(n.type,e.dtype);void 0!==n.position&&hn(n.position,a)===hn(e.dposition)||(n.position=e.dposition),s[o]=!0;let h=null;if(o in i&&i[o].type===l)h=i[o];else{h=new(Us.getScale(l))({id:o,type:l,ctx:this.ctx,chart:this}),i[h.id]=h}h.init(n,t)})),d(s,((t,e)=>{t||delete i[e]})),d(i,(t=>{Zi.configure(this,t,t.options),Zi.addBox(this,t)}))}_updateMetasets(){const t=this._metasets,e=this.data.datasets.length,i=t.length;if(t.sort(((t,e)=>t.index-e.index)),i>e){for(let t=e;t<i;++t)this._destroyDatasetMeta(t);t.splice(e,i-e)}this._sortedMetasets=t.slice(0).sort(cn("order","index"))}_removeUnreferencedMetasets(){const{_metasets:t,data:{datasets:e}}=this;t.length>e.length&&delete this._stacks,t.forEach(((t,i)=>{0===e.filter((e=>e===t._dataset)).length&&this._destroyDatasetMeta(i)}))}buildOrUpdateControllers(){const t=[],e=this.data.datasets;let i,s;for(this._removeUnreferencedMetasets(),i=0,s=e.length;i<s;i++){const s=e[i];let n=this.getDatasetMeta(i);const o=s.type||this.config.type;if(n.type&&n.type!==o&&(this._destroyDatasetMeta(i),n=this.getDatasetMeta(i)),n.type=o,n.indexAxis=s.indexAxis||Gs(o,this.options),n.order=s.order||0,n.index=i,n.label=""+s.label,n.visible=this.isDatasetVisible(i),n.controller)n.controller.updateIndex(i),n.controller.linkScales();else{const e=Us.getController(o),{datasetElementType:s,dataElementType:a}=ne.datasets[o];Object.assign(e.prototype,{dataElementType:Us.getElement(a),datasetElementType:s&&Us.getElement(s)}),n.controller=new e(this,i),t.push(n.controller)}}return this._updateMetasets(),t}_resetElements(){d(this.data.datasets,((t,e)=>{this.getDatasetMeta(e).controller.reset()}),this)}reset(){this._resetElements(),this.notifyPlugins("reset")}update(t){const e=this.config;e.update();const i=this._options=e.createResolver(e.chartOptionScopes(),this.getContext()),s=this._animationsDisabled=!i.animation;if(this._updateScales(),this._checkEventBindings(),this._updateHiddenIndices(),this._plugins.invalidate(),!1===this.notifyPlugins("beforeUpdate",{mode:t,cancelable:!0}))return;const n=this.buildOrUpdateControllers();this.notifyPlugins("beforeElementsUpdate");let o=0;for(let t=0,e=this.data.datasets.length;t<e;t++){const{controller:e}=this.getDatasetMeta(t),i=!s&&-1===n.indexOf(e);e.buildOrUpdateElements(i),o=Math.max(+e.getMaxOverflow(),o)}o=this._minPadding=i.layout.autoPadding?o:0,this._updateLayout(o),s||d(n,(t=>{t.reset()})),this._updateDatasets(t),this.notifyPlugins("afterUpdate",{mode:t}),this._layers.sort(cn("z","_idx"));const{_active:a,_lastEvent:r}=this;r?this._eventHandler(r,!0):a.length&&this._updateHoverStyles(a,a,!0),this.render()}_updateScales(){d(this.scales,(t=>{Zi.removeBox(this,t)})),this.ensureScalesHaveIDs(),this.buildOrUpdateScales()}_checkEventBindings(){const t=this.options,e=new Set(Object.keys(this._listeners)),i=new Set(t.events);S(e,i)&&!!this._responsiveListeners===t.responsive||(this.unbindEvents(),this.bindEvents())}_updateHiddenIndices(){const{_hiddenIndices:t}=this,e=this._getUniformDataChanges()||[];for(const{method:i,start:s,count:n}of e){mn(t,s,"_removeElements"===i?-n:n)}}_getUniformDataChanges(){const t=this._dataChanges;if(!t||!t.length)return;this._dataChanges=[];const e=this.data.datasets.length,i=e=>new Set(t.filter((t=>t[0]===e)).map(((t,e)=>e+","+t.splice(1).join(",")))),s=i(0);for(let t=1;t<e;t++)if(!S(s,i(t)))return;return Array.from(s).map((t=>t.split(","))).map((t=>({method:t[1],start:+t[2],count:+t[3]})))}_updateLayout(t){if(!1===this.notifyPlugins("beforeLayout",{cancelable:!0}))return;Zi.update(this,this.width,this.height,t);const e=this.chartArea,i=e.width<=0||e.height<=0;this._layers=[],d(this.boxes,(t=>{i&&"chartArea"===t.position||(t.configure&&t.configure(),this._layers.push(...t._layers()))}),this),this._layers.forEach(((t,e)=>{t._idx=e})),this.notifyPlugins("afterLayout")}_updateDatasets(t){if(!1!==this.notifyPlugins("beforeDatasetsUpdate",{mode:t,cancelable:!0})){for(let t=0,e=this.data.datasets.length;t<e;++t)this.getDatasetMeta(t).controller.configure();for(let e=0,i=this.data.datasets.length;e<i;++e)this._updateDataset(e,k(t)?t({datasetIndex:e}):t);this.notifyPlugins("afterDatasetsUpdate",{mode:t})}}_updateDataset(t,e){const i=this.getDatasetMeta(t),s={meta:i,index:t,mode:e,cancelable:!0};!1!==this.notifyPlugins("beforeDatasetUpdate",s)&&(i.controller._update(e),s.cancelable=!1,this.notifyPlugins("afterDatasetUpdate",s))}render(){!1!==this.notifyPlugins("beforeRender",{cancelable:!0})&&(mt.has(this)?this.attached&&!mt.running(this)&&mt.start(this):(this.draw(),dn({chart:this})))}draw(){let t;if(this._resizeBeforeDraw){const{width:t,height:e}=this._resizeBeforeDraw;this._resize(t,e),this._resizeBeforeDraw=null}if(this.clear(),this.width<=0||this.height<=0)return;if(!1===this.notifyPlugins("beforeDraw",{cancelable:!0}))return;const e=this._layers;for(t=0;t<e.length&&e[t].z<=0;++t)e[t].draw(this.chartArea);for(this._drawDatasets();t<e.length;++t)e[t].draw(this.chartArea);this.notifyPlugins("afterDraw")}_getSortedDatasetMetas(t){const e=this._sortedMetasets,i=[];let s,n;for(s=0,n=e.length;s<n;++s){const n=e[s];t&&!n.visible||i.push(n)}return i}getSortedVisibleDatasetMetas(){return this._getSortedDatasetMetas(!0)}_drawDatasets(){if(!1===this.notifyPlugins("beforeDatasetsDraw",{cancelable:!0}))return;const t=this.getSortedVisibleDatasetMetas();for(let e=t.length-1;e>=0;--e)this._drawDataset(t[e]);this.notifyPlugins("afterDatasetsDraw")}_drawDataset(t){const e=this.ctx,i=t._clip,s=!i.disabled,n=this.chartArea,o={meta:t,index:t.index,cancelable:!0};!1!==this.notifyPlugins("beforeDatasetDraw",o)&&(s&&Pe(e,{left:!1===i.left?0:n.left-i.left,right:!1===i.right?this.width:n.right+i.right,top:!1===i.top?0:n.top-i.top,bottom:!1===i.bottom?this.height:n.bottom+i.bottom}),t.controller.draw(),s&&De(e),o.cancelable=!1,this.notifyPlugins("afterDatasetDraw",o))}isPointInArea(t){return Se(t,this.chartArea,this._minPadding)}getElementsAtEventForMode(t,e,i,s){const n=Vi.modes[e];return"function"==typeof n?n(this,t,i,s):[]}getDatasetMeta(t){const e=this.data.datasets[t],i=this._metasets;let s=i.filter((t=>t&&t._dataset===e)).pop();return s||(s={type:null,data:[],dataset:null,controller:null,hidden:null,xAxisID:null,yAxisID:null,order:e&&e.order||0,index:t,_dataset:e,_parsed:[],_sorted:!1},i.push(s)),s}getContext(){return this.$context||(this.$context=_i(null,{chart:this,type:"chart"}))}getVisibleDatasetCount(){return this.getSortedVisibleDatasetMetas().length}isDatasetVisible(t){const e=this.data.datasets[t];if(!e)return!1;const i=this.getDatasetMeta(t);return"boolean"==typeof i.hidden?!i.hidden:!e.hidden}setDatasetVisibility(t,e){this.getDatasetMeta(t).hidden=!e}toggleDataVisibility(t){this._hiddenIndices[t]=!this._hiddenIndices[t]}getDataVisibility(t){return!this._hiddenIndices[t]}_updateVisibility(t,e,i){const s=i?"show":"hide",n=this.getDatasetMeta(t),o=n.controller._resolveAnimations(void 0,s);M(e)?(n.data[e].hidden=!i,this.update()):(this.setDatasetVisibility(t,i),o.update(n,{visible:i}),this.update((e=>e.datasetIndex===t?s:void 0)))}hide(t,e){this._updateVisibility(t,e,!1)}show(t,e){this._updateVisibility(t,e,!0)}_destroyDatasetMeta(t){const e=this._metasets[t];e&&e.controller&&e.controller._destroy(),delete this._metasets[t]}_stop(){let t,e;for(this.stop(),mt.remove(this),t=0,e=this.data.datasets.length;t<e;++t)this._destroyDatasetMeta(t)}destroy(){this.notifyPlugins("beforeDestroy");const{canvas:t,ctx:e}=this;this._stop(),this.config.clearCache(),t&&(this.unbindEvents(),we(t,e),this.platform.releaseContext(e),this.canvas=null,this.ctx=null),this.notifyPlugins("destroy"),delete gn[this.id],this.notifyPlugins("afterDestroy")}toBase64Image(...t){return this.canvas.toDataURL(...t)}bindEvents(){this.bindUserEvents(),this.options.responsive?this.bindResponsiveEvents():this.attached=!0}bindUserEvents(){const t=this._listeners,e=this.platform,i=(i,s)=>{e.addEventListener(this,i,s),t[i]=s},s=(t,e,i)=>{t.offsetX=e,t.offsetY=i,this._eventHandler(t)};d(this.options.events,(t=>i(t,s)))}bindResponsiveEvents(){this._responsiveListeners||(this._responsiveListeners={});const t=this._responsiveListeners,e=this.platform,i=(i,s)=>{e.addEventListener(this,i,s),t[i]=s},s=(i,s)=>{t[i]&&(e.removeEventListener(this,i,s),delete t[i])},n=(t,e)=>{this.canvas&&this.resize(t,e)};let o;const a=()=>{s("attach",a),this.attached=!0,this.resize(),i("resize",n),i("detach",o)};o=()=>{this.attached=!1,s("resize",n),this._stop(),this._resize(0,0),i("attach",a)},e.isAttached(this.canvas)?a():o()}unbindEvents(){d(this._listeners,((t,e)=>{this.platform.removeEventListener(this,e,t)})),this._listeners={},d(this._responsiveListeners,((t,e)=>{this.platform.removeEventListener(this,e,t)})),this._responsiveListeners=void 0}updateHoverStyle(t,e,i){const s=i?"set":"remove";let n,o,a,r;for("dataset"===e&&(n=this.getDatasetMeta(t[0].datasetIndex),n.controller["_"+s+"DatasetHoverStyle"]()),a=0,r=t.length;a<r;++a){o=t[a];const e=o&&this.getDatasetMeta(o.datasetIndex).controller;e&&e[s+"HoverStyle"](o.element,o.datasetIndex,o.index)}}getActiveElements(){return this._active||[]}setActiveElements(t){const e=this._active||[],i=t.map((({datasetIndex:t,index:e})=>{const i=this.getDatasetMeta(t);if(!i)throw new Error("No dataset found at index "+t);return{datasetIndex:t,element:i.data[e],index:e}}));!u(i,e)&&(this._active=i,this._lastEvent=null,this._updateHoverStyles(i,e))}notifyPlugins(t,e,i){return this._plugins.notify(this,t,e,i)}_updateHoverStyles(t,e,i){const s=this.options.hover,n=(t,e)=>t.filter((t=>!e.some((e=>t.datasetIndex===e.datasetIndex&&t.index===e.index)))),o=n(e,t),a=i?t:n(t,e);o.length&&this.updateHoverStyle(o,s.mode,!1),a.length&&s.mode&&this.updateHoverStyle(a,s.mode,!0)}_eventHandler(t,e){const i={event:t,replay:e,cancelable:!0,inChartArea:this.isPointInArea(t)},s=e=>(e.options.events||this.options.events).includes(t.native.type);if(!1===this.notifyPlugins("beforeEvent",i,s))return;const n=this._handleEvent(t,e,i.inChartArea);return i.cancelable=!1,this.notifyPlugins("afterEvent",i,s),(n||i.changed)&&this.render(),this}_handleEvent(t,e,i){const{_active:s=[],options:n}=this,o=e,a=this._getActiveElements(t,s,i,o),r=P(t),l=function(t,e,i,s){return i&&"mouseout"!==t.type?s?e:t:null}(t,this._lastEvent,i,r);i&&(this._lastEvent=null,c(n.onHover,[t,a,this],this),r&&c(n.onClick,[t,a,this],this));const h=!u(a,s);return(h||e)&&(this._active=a,this._updateHoverStyles(a,s,e)),this._lastEvent=l,h}_getActiveElements(t,e,i,s){if("mouseout"===t.type)return[];if(!i)return e;const n=this.options.hover;return this.getElementsAtEventForMode(t,n.mode,n,s)}}const xn=()=>d(bn.instances,(t=>t._plugins.invalidate())),_n=!0;function yn(){throw new Error("This method is not implemented: Check that a complete date adapter is provided.")}Object.defineProperties(bn,{defaults:{enumerable:_n,value:ne},instances:{enumerable:_n,value:gn},overrides:{enumerable:_n,value:te},registry:{enumerable:_n,value:Us},version:{enumerable:_n,value:"3.9.1"},getChart:{enumerable:_n,value:pn},register:{enumerable:_n,value:(...t)=>{Us.add(...t),xn()}},unregister:{enumerable:_n,value:(...t)=>{Us.remove(...t),xn()}}});class vn{constructor(t){this.options=t||{}}init(t){}formats(){return yn()}parse(t,e){return yn()}format(t,e){return yn()}add(t,e,i){return yn()}diff(t,e,i){return yn()}startOf(t,e,i){return yn()}endOf(t,e){return yn()}}vn.override=function(t){Object.assign(vn.prototype,t)};var wn={_date:vn};function Mn(t){const e=t.iScale,i=function(t,e){if(!t._cache.$bar){const i=t.getMatchingVisibleMetas(e);let s=[];for(let e=0,n=i.length;e<n;e++)s=s.concat(i[e].controller.getAllParsedValues(t));t._cache.$bar=rt(s.sort(((t,e)=>t-e)))}return t._cache.$bar}(e,t.type);let s,n,o,a,r=e._length;const l=()=>{32767!==o&&-32768!==o&&(M(a)&&(r=Math.min(r,Math.abs(o-a)||r)),a=o)};for(s=0,n=i.length;s<n;++s)o=e.getPixelForValue(i[s]),l();for(a=void 0,s=0,n=e.ticks.length;s<n;++s)o=e.getPixelForTick(s),l();return r}function kn(t,e,i,n){return s(t)?function(t,e,i,s){const n=i.parse(t[0],s),o=i.parse(t[1],s),a=Math.min(n,o),r=Math.max(n,o);let l=a,h=r;Math.abs(a)>Math.abs(r)&&(l=r,h=a),e[i.axis]=h,e._custom={barStart:l,barEnd:h,start:n,end:o,min:a,max:r}}(t,e,i,n):e[i.axis]=i.parse(t,n),e}function Sn(t,e,i,s){const n=t.iScale,o=t.vScale,a=n.getLabels(),r=n===o,l=[];let h,c,d,u;for(h=i,c=i+s;h<c;++h)u=e[h],d={},d[n.axis]=r||n.parse(a[h],h),l.push(kn(u,d,o,h));return l}function Pn(t){return t&&void 0!==t.barStart&&void 0!==t.barEnd}function Dn(t,e,i,s){let n=e.borderSkipped;const o={};if(!n)return void(t.borderSkipped=o);if(!0===n)return void(t.borderSkipped={top:!0,right:!0,bottom:!0,left:!0});const{start:a,end:r,reverse:l,top:h,bottom:c}=function(t){let e,i,s,n,o;return t.horizontal?(e=t.base>t.x,i="left",s="right"):(e=t.base<t.y,i="bottom",s="top"),e?(n="end",o="start"):(n="start",o="end"),{start:i,end:s,reverse:e,top:n,bottom:o}}(t);"middle"===n&&i&&(t.enableBorderRadius=!0,(i._top||0)===s?n=h:(i._bottom||0)===s?n=c:(o[On(c,a,r,l)]=!0,n=h)),o[On(n,a,r,l)]=!0,t.borderSkipped=o}function On(t,e,i,s){var n,o,a;return s?(a=i,t=Cn(t=(n=t)===(o=e)?a:n===a?o:n,i,e)):t=Cn(t,e,i),t}function Cn(t,e,i){return"start"===t?e:"end"===t?i:t}function An(t,{inflateAmount:e},i){t.inflateAmount="auto"===e?1===i?.33:0:e}class Tn extends Ls{parsePrimitiveData(t,e,i,s){return Sn(t,e,i,s)}parseArrayData(t,e,i,s){return Sn(t,e,i,s)}parseObjectData(t,e,i,s){const{iScale:n,vScale:o}=t,{xAxisKey:a="x",yAxisKey:r="y"}=this._parsing,l="x"===n.axis?a:r,h="x"===o.axis?a:r,c=[];let d,u,f,g;for(d=i,u=i+s;d<u;++d)g=e[d],f={},f[n.axis]=n.parse(y(g,l),d),c.push(kn(y(g,h),f,o,d));return c}updateRangeFromParsed(t,e,i,s){super.updateRangeFromParsed(t,e,i,s);const n=i._custom;n&&e===this._cachedMeta.vScale&&(t.min=Math.min(t.min,n.min),t.max=Math.max(t.max,n.max))}getMaxOverflow(){return 0}getLabelAndValue(t){const e=this._cachedMeta,{iScale:i,vScale:s}=e,n=this.getParsed(t),o=n._custom,a=Pn(o)?"["+o.start+", "+o.end+"]":""+s.getLabelForValue(n[s.axis]);return{label:""+i.getLabelForValue(n[i.axis]),value:a}}initialize(){this.enableOptionSharing=!0,super.initialize();this._cachedMeta.stack=this.getDataset().stack}update(t){const e=this._cachedMeta;this.updateElements(e.data,0,e.data.length,t)}updateElements(t,e,s,n){const o="reset"===n,{index:a,_cachedMeta:{vScale:r}}=this,l=r.getBasePixel(),h=r.isHorizontal(),c=this._getRuler(),{sharedOptions:d,includeOptions:u}=this._getSharedOptions(e,n);for(let f=e;f<e+s;f++){const e=this.getParsed(f),s=o||i(e[r.axis])?{base:l,head:l}:this._calculateBarValuePixels(f),g=this._calculateBarIndexPixels(f,c),p=(e._stacks||{})[r.axis],m={horizontal:h,base:s.base,enableBorderRadius:!p||Pn(e._custom)||a===p._top||a===p._bottom,x:h?s.head:g.center,y:h?g.center:s.head,height:h?g.size:Math.abs(s.size),width:h?Math.abs(s.size):g.size};u&&(m.options=d||this.resolveDataElementOptions(f,t[f].active?"active":n));const b=m.options||t[f].options;Dn(m,b,p,a),An(m,b,c.ratio),this.updateElement(t[f],f,m,n)}}_getStacks(t,e){const{iScale:s}=this._cachedMeta,n=s.getMatchingVisibleMetas(this._type).filter((t=>t.controller.options.grouped)),o=s.options.stacked,a=[],r=t=>{const s=t.controller.getParsed(e),n=s&&s[t.vScale.axis];if(i(n)||isNaN(n))return!0};for(const i of n)if((void 0===e||!r(i))&&((!1===o||-1===a.indexOf(i.stack)||void 0===o&&void 0===i.stack)&&a.push(i.stack),i.index===t))break;return a.length||a.push(void 0),a}_getStackCount(t){return this._getStacks(void 0,t).length}_getStackIndex(t,e,i){const s=this._getStacks(t,i),n=void 0!==e?s.indexOf(e):-1;return-1===n?s.length-1:n}_getRuler(){const t=this.options,e=this._cachedMeta,i=e.iScale,s=[];let n,o;for(n=0,o=e.data.length;n<o;++n)s.push(i.getPixelForValue(this.getParsed(n)[i.axis],n));const a=t.barThickness;return{min:a||Mn(e),pixels:s,start:i._startPixel,end:i._endPixel,stackCount:this._getStackCount(),scale:i,grouped:t.grouped,ratio:a?1:t.categoryPercentage*t.barPercentage}}_calculateBarValuePixels(t){const{_cachedMeta:{vScale:e,_stacked:s},options:{base:n,minBarLength:o}}=this,a=n||0,r=this.getParsed(t),l=r._custom,h=Pn(l);let c,d,u=r[e.axis],f=0,g=s?this.applyStack(e,r,s):u;g!==u&&(f=g-u,g=u),h&&(u=l.barStart,g=l.barEnd-l.barStart,0!==u&&z(u)!==z(l.barEnd)&&(f=0),f+=u);const p=i(n)||h?f:n;let m=e.getPixelForValue(p);if(c=this.chart.getDataVisibility(t)?e.getPixelForValue(f+g):m,d=c-m,Math.abs(d)<o){d=function(t,e,i){return 0!==t?z(t):(e.isHorizontal()?1:-1)*(e.min>=i?1:-1)}(d,e,a)*o,u===a&&(m-=d/2);const t=e.getPixelForDecimal(0),i=e.getPixelForDecimal(1),s=Math.min(t,i),n=Math.max(t,i);m=Math.max(Math.min(m,n),s),c=m+d}if(m===e.getPixelForValue(a)){const t=z(d)*e.getLineWidthForValue(a)/2;m+=t,d-=t}return{size:d,base:m,head:c,center:c+d/2}}_calculateBarIndexPixels(t,e){const s=e.scale,n=this.options,o=n.skipNull,a=r(n.maxBarThickness,1/0);let l,h;if(e.grouped){const s=o?this._getStackCount(t):e.stackCount,r="flex"===n.barThickness?function(t,e,i,s){const n=e.pixels,o=n[t];let a=t>0?n[t-1]:null,r=t<n.length-1?n[t+1]:null;const l=i.categoryPercentage;null===a&&(a=o-(null===r?e.end-e.start:r-o)),null===r&&(r=o+o-a);const h=o-(o-Math.min(a,r))/2*l;return{chunk:Math.abs(r-a)/2*l/s,ratio:i.barPercentage,start:h}}(t,e,n,s):function(t,e,s,n){const o=s.barThickness;let a,r;return i(o)?(a=e.min*s.categoryPercentage,r=s.barPercentage):(a=o*n,r=1),{chunk:a/n,ratio:r,start:e.pixels[t]-a/2}}(t,e,n,s),c=this._getStackIndex(this.index,this._cachedMeta.stack,o?t:void 0);l=r.start+r.chunk*c+r.chunk/2,h=Math.min(a,r.chunk*r.ratio)}else l=s.getPixelForValue(this.getParsed(t)[s.axis],t),h=Math.min(a,e.min*e.ratio);return{base:l-h/2,head:l+h/2,center:l,size:h}}draw(){const t=this._cachedMeta,e=t.vScale,i=t.data,s=i.length;let n=0;for(;n<s;++n)null!==this.getParsed(n)[e.axis]&&i[n].draw(this._ctx)}}Tn.id="bar",Tn.defaults={datasetElementType:!1,dataElementType:"bar",categoryPercentage:.8,barPercentage:.9,grouped:!0,animations:{numbers:{type:"number",properties:["x","y","base","width","height"]}}},Tn.overrides={scales:{_index_:{type:"category",offset:!0,grid:{offset:!0}},_value_:{type:"linear",beginAtZero:!0}}};class Ln extends Ls{initialize(){this.enableOptionSharing=!0,super.initialize()}parsePrimitiveData(t,e,i,s){const n=super.parsePrimitiveData(t,e,i,s);for(let t=0;t<n.length;t++)n[t]._custom=this.resolveDataElementOptions(t+i).radius;return n}parseArrayData(t,e,i,s){const n=super.parseArrayData(t,e,i,s);for(let t=0;t<n.length;t++){const s=e[i+t];n[t]._custom=r(s[2],this.resolveDataElementOptions(t+i).radius)}return n}parseObjectData(t,e,i,s){const n=super.parseObjectData(t,e,i,s);for(let t=0;t<n.length;t++){const s=e[i+t];n[t]._custom=r(s&&s.r&&+s.r,this.resolveDataElementOptions(t+i).radius)}return n}getMaxOverflow(){const t=this._cachedMeta.data;let e=0;for(let i=t.length-1;i>=0;--i)e=Math.max(e,t[i].size(this.resolveDataElementOptions(i))/2);return e>0&&e}getLabelAndValue(t){const e=this._cachedMeta,{xScale:i,yScale:s}=e,n=this.getParsed(t),o=i.getLabelForValue(n.x),a=s.getLabelForValue(n.y),r=n._custom;return{label:e.label,value:"("+o+", "+a+(r?", "+r:"")+")"}}update(t){const e=this._cachedMeta.data;this.updateElements(e,0,e.length,t)}updateElements(t,e,i,s){const n="reset"===s,{iScale:o,vScale:a}=this._cachedMeta,{sharedOptions:r,includeOptions:l}=this._getSharedOptions(e,s),h=o.axis,c=a.axis;for(let d=e;d<e+i;d++){const e=t[d],i=!n&&this.getParsed(d),u={},f=u[h]=n?o.getPixelForDecimal(.5):o.getPixelForValue(i[h]),g=u[c]=n?a.getBasePixel():a.getPixelForValue(i[c]);u.skip=isNaN(f)||isNaN(g),l&&(u.options=r||this.resolveDataElementOptions(d,e.active?"active":s),n&&(u.options.radius=0)),this.updateElement(e,d,u,s)}}resolveDataElementOptions(t,e){const i=this.getParsed(t);let s=super.resolveDataElementOptions(t,e);s.$shared&&(s=Object.assign({},s,{$shared:!1}));const n=s.radius;return"active"!==e&&(s.radius=0),s.radius+=r(i&&i._custom,n),s}}Ln.id="bubble",Ln.defaults={datasetElementType:!1,dataElementType:"point",animations:{numbers:{type:"number",properties:["x","y","borderWidth","radius"]}}},Ln.overrides={scales:{x:{type:"linear"},y:{type:"linear"}},plugins:{tooltip:{callbacks:{title:()=>""}}}};class En extends Ls{constructor(t,e){super(t,e),this.enableOptionSharing=!0,this.innerRadius=void 0,this.outerRadius=void 0,this.offsetX=void 0,this.offsetY=void 0}linkScales(){}parse(t,e){const i=this.getDataset().data,s=this._cachedMeta;if(!1===this._parsing)s._parsed=i;else{let o,a,r=t=>+i[t];if(n(i[t])){const{key:t="value"}=this._parsing;r=e=>+y(i[e],t)}for(o=t,a=t+e;o<a;++o)s._parsed[o]=r(o)}}_getRotation(){return H(this.options.rotation-90)}_getCircumference(){return H(this.options.circumference)}_getRotationExtents(){let t=O,e=-O;for(let i=0;i<this.chart.data.datasets.length;++i)if(this.chart.isDatasetVisible(i)){const s=this.chart.getDatasetMeta(i).controller,n=s._getRotation(),o=s._getCircumference();t=Math.min(t,n),e=Math.max(e,n+o)}return{rotation:t,circumference:e-t}}update(t){const e=this.chart,{chartArea:i}=e,s=this._cachedMeta,n=s.data,o=this.getMaxBorderWidth()+this.getMaxOffset(n)+this.options.spacing,a=Math.max((Math.min(i.width,i.height)-o)/2,0),r=Math.min(l(this.options.cutout,a),1),c=this._getRingWeight(this.index),{circumference:d,rotation:u}=this._getRotationExtents(),{ratioX:f,ratioY:g,offsetX:p,offsetY:m}=function(t,e,i){let s=1,n=1,o=0,a=0;if(e<O){const r=t,l=r+e,h=Math.cos(r),c=Math.sin(r),d=Math.cos(l),u=Math.sin(l),f=(t,e,s)=>G(t,r,l,!0)?1:Math.max(e,e*i,s,s*i),g=(t,e,s)=>G(t,r,l,!0)?-1:Math.min(e,e*i,s,s*i),p=f(0,h,d),m=f(L,c,u),b=g(D,h,d),x=g(D+L,c,u);s=(p-b)/2,n=(m-x)/2,o=-(p+b)/2,a=-(m+x)/2}return{ratioX:s,ratioY:n,offsetX:o,offsetY:a}}(u,d,r),b=(i.width-o)/f,x=(i.height-o)/g,_=Math.max(Math.min(b,x)/2,0),y=h(this.options.radius,_),v=(y-Math.max(y*r,0))/this._getVisibleDatasetWeightTotal();this.offsetX=p*y,this.offsetY=m*y,s.total=this.calculateTotal(),this.outerRadius=y-v*this._getRingWeightOffset(this.index),this.innerRadius=Math.max(this.outerRadius-v*c,0),this.updateElements(n,0,n.length,t)}_circumference(t,e){const i=this.options,s=this._cachedMeta,n=this._getCircumference();return e&&i.animation.animateRotate||!this.chart.getDataVisibility(t)||null===s._parsed[t]||s.data[t].hidden?0:this.calculateCircumference(s._parsed[t]*n/O)}updateElements(t,e,i,s){const n="reset"===s,o=this.chart,a=o.chartArea,r=o.options.animation,l=(a.left+a.right)/2,h=(a.top+a.bottom)/2,c=n&&r.animateScale,d=c?0:this.innerRadius,u=c?0:this.outerRadius,{sharedOptions:f,includeOptions:g}=this._getSharedOptions(e,s);let p,m=this._getRotation();for(p=0;p<e;++p)m+=this._circumference(p,n);for(p=e;p<e+i;++p){const e=this._circumference(p,n),i=t[p],o={x:l+this.offsetX,y:h+this.offsetY,startAngle:m,endAngle:m+e,circumference:e,outerRadius:u,innerRadius:d};g&&(o.options=f||this.resolveDataElementOptions(p,i.active?"active":s)),m+=e,this.updateElement(i,p,o,s)}}calculateTotal(){const t=this._cachedMeta,e=t.data;let i,s=0;for(i=0;i<e.length;i++){const n=t._parsed[i];null===n||isNaN(n)||!this.chart.getDataVisibility(i)||e[i].hidden||(s+=Math.abs(n))}return s}calculateCircumference(t){const e=this._cachedMeta.total;return e>0&&!isNaN(t)?O*(Math.abs(t)/e):0}getLabelAndValue(t){const e=this._cachedMeta,i=this.chart,s=i.data.labels||[],n=li(e._parsed[t],i.options.locale);return{label:s[t]||"",value:n}}getMaxBorderWidth(t){let e=0;const i=this.chart;let s,n,o,a,r;if(!t)for(s=0,n=i.data.datasets.length;s<n;++s)if(i.isDatasetVisible(s)){o=i.getDatasetMeta(s),t=o.data,a=o.controller;break}if(!t)return 0;for(s=0,n=t.length;s<n;++s)r=a.resolveDataElementOptions(s),"inner"!==r.borderAlign&&(e=Math.max(e,r.borderWidth||0,r.hoverBorderWidth||0));return e}getMaxOffset(t){let e=0;for(let i=0,s=t.length;i<s;++i){const t=this.resolveDataElementOptions(i);e=Math.max(e,t.offset||0,t.hoverOffset||0)}return e}_getRingWeightOffset(t){let e=0;for(let i=0;i<t;++i)this.chart.isDatasetVisible(i)&&(e+=this._getRingWeight(i));return e}_getRingWeight(t){return Math.max(r(this.chart.data.datasets[t].weight,1),0)}_getVisibleDatasetWeightTotal(){return this._getRingWeightOffset(this.chart.data.datasets.length)||1}}En.id="doughnut",En.defaults={datasetElementType:!1,dataElementType:"arc",animation:{animateRotate:!0,animateScale:!1},animations:{numbers:{type:"number",properties:["circumference","endAngle","innerRadius","outerRadius","startAngle","x","y","offset","borderWidth","spacing"]}},cutout:"50%",rotation:0,circumference:360,radius:"100%",spacing:0,indexAxis:"r"},En.descriptors={_scriptable:t=>"spacing"!==t,_indexable:t=>"spacing"!==t},En.overrides={aspectRatio:1,plugins:{legend:{labels:{generateLabels(t){const e=t.data;if(e.labels.length&&e.datasets.length){const{labels:{pointStyle:i}}=t.legend.options;return e.labels.map(((e,s)=>{const n=t.getDatasetMeta(0).controller.getStyle(s);return{text:e,fillStyle:n.backgroundColor,strokeStyle:n.borderColor,lineWidth:n.borderWidth,pointStyle:i,hidden:!t.getDataVisibility(s),index:s}}))}return[]}},onClick(t,e,i){i.chart.toggleDataVisibility(e.index),i.chart.update()}},tooltip:{callbacks:{title:()=>"",label(t){let e=t.label;const i=": "+t.formattedValue;return s(e)?(e=e.slice(),e[0]+=i):e+=i,e}}}}};class Rn extends Ls{initialize(){this.enableOptionSharing=!0,this.supportsDecimation=!0,super.initialize()}update(t){const e=this._cachedMeta,{dataset:i,data:s=[],_dataset:n}=e,o=this.chart._animationsDisabled;let{start:a,count:r}=gt(e,s,o);this._drawStart=a,this._drawCount=r,pt(e)&&(a=0,r=s.length),i._chart=this.chart,i._datasetIndex=this.index,i._decimated=!!n._decimated,i.points=s;const l=this.resolveDatasetElementOptions(t);this.options.showLine||(l.borderWidth=0),l.segment=this.options.segment,this.updateElement(i,void 0,{animated:!o,options:l},t),this.updateElements(s,a,r,t)}updateElements(t,e,s,n){const o="reset"===n,{iScale:a,vScale:r,_stacked:l,_dataset:h}=this._cachedMeta,{sharedOptions:c,includeOptions:d}=this._getSharedOptions(e,n),u=a.axis,f=r.axis,{spanGaps:g,segment:p}=this.options,m=B(g)?g:Number.POSITIVE_INFINITY,b=this.chart._animationsDisabled||o||"none"===n;let x=e>0&&this.getParsed(e-1);for(let g=e;g<e+s;++g){const e=t[g],s=this.getParsed(g),_=b?e:{},y=i(s[f]),v=_[u]=a.getPixelForValue(s[u],g),w=_[f]=o||y?r.getBasePixel():r.getPixelForValue(l?this.applyStack(r,s,l):s[f],g);_.skip=isNaN(v)||isNaN(w)||y,_.stop=g>0&&Math.abs(s[u]-x[u])>m,p&&(_.parsed=s,_.raw=h.data[g]),d&&(_.options=c||this.resolveDataElementOptions(g,e.active?"active":n)),b||this.updateElement(e,g,_,n),x=s}}getMaxOverflow(){const t=this._cachedMeta,e=t.dataset,i=e.options&&e.options.borderWidth||0,s=t.data||[];if(!s.length)return i;const n=s[0].size(this.resolveDataElementOptions(0)),o=s[s.length-1].size(this.resolveDataElementOptions(s.length-1));return Math.max(i,n,o)/2}draw(){const t=this._cachedMeta;t.dataset.updateControlPoints(this.chart.chartArea,t.iScale.axis),super.draw()}}Rn.id="line",Rn.defaults={datasetElementType:"line",dataElementType:"point",showLine:!0,spanGaps:!1},Rn.overrides={scales:{_index_:{type:"category"},_value_:{type:"linear"}}};class In extends Ls{constructor(t,e){super(t,e),this.innerRadius=void 0,this.outerRadius=void 0}getLabelAndValue(t){const e=this._cachedMeta,i=this.chart,s=i.data.labels||[],n=li(e._parsed[t].r,i.options.locale);return{label:s[t]||"",value:n}}parseObjectData(t,e,i,s){return Ue.bind(this)(t,e,i,s)}update(t){const e=this._cachedMeta.data;this._updateRadius(),this.updateElements(e,0,e.length,t)}getMinMax(){const t=this._cachedMeta,e={min:Number.POSITIVE_INFINITY,max:Number.NEGATIVE_INFINITY};return t.data.forEach(((t,i)=>{const s=this.getParsed(i).r;!isNaN(s)&&this.chart.getDataVisibility(i)&&(s<e.min&&(e.min=s),s>e.max&&(e.max=s))})),e}_updateRadius(){const t=this.chart,e=t.chartArea,i=t.options,s=Math.min(e.right-e.left,e.bottom-e.top),n=Math.max(s/2,0),o=(n-Math.max(i.cutoutPercentage?n/100*i.cutoutPercentage:1,0))/t.getVisibleDatasetCount();this.outerRadius=n-o*this.index,this.innerRadius=this.outerRadius-o}updateElements(t,e,i,s){const n="reset"===s,o=this.chart,a=o.options.animation,r=this._cachedMeta.rScale,l=r.xCenter,h=r.yCenter,c=r.getIndexAngle(0)-.5*D;let d,u=c;const f=360/this.countVisibleElements();for(d=0;d<e;++d)u+=this._computeAngle(d,s,f);for(d=e;d<e+i;d++){const e=t[d];let i=u,g=u+this._computeAngle(d,s,f),p=o.getDataVisibility(d)?r.getDistanceFromCenterForValue(this.getParsed(d).r):0;u=g,n&&(a.animateScale&&(p=0),a.animateRotate&&(i=g=c));const m={x:l,y:h,innerRadius:0,outerRadius:p,startAngle:i,endAngle:g,options:this.resolveDataElementOptions(d,e.active?"active":s)};this.updateElement(e,d,m,s)}}countVisibleElements(){const t=this._cachedMeta;let e=0;return t.data.forEach(((t,i)=>{!isNaN(this.getParsed(i).r)&&this.chart.getDataVisibility(i)&&e++})),e}_computeAngle(t,e,i){return this.chart.getDataVisibility(t)?H(this.resolveDataElementOptions(t,e).angle||i):0}}In.id="polarArea",In.defaults={dataElementType:"arc",animation:{animateRotate:!0,animateScale:!0},animations:{numbers:{type:"number",properties:["x","y","startAngle","endAngle","innerRadius","outerRadius"]}},indexAxis:"r",startAngle:0},In.overrides={aspectRatio:1,plugins:{legend:{labels:{generateLabels(t){const e=t.data;if(e.labels.length&&e.datasets.length){const{labels:{pointStyle:i}}=t.legend.options;return e.labels.map(((e,s)=>{const n=t.getDatasetMeta(0).controller.getStyle(s);return{text:e,fillStyle:n.backgroundColor,strokeStyle:n.borderColor,lineWidth:n.borderWidth,pointStyle:i,hidden:!t.getDataVisibility(s),index:s}}))}return[]}},onClick(t,e,i){i.chart.toggleDataVisibility(e.index),i.chart.update()}},tooltip:{callbacks:{title:()=>"",label:t=>t.chart.data.labels[t.dataIndex]+": "+t.formattedValue}}},scales:{r:{type:"radialLinear",angleLines:{display:!1},beginAtZero:!0,grid:{circular:!0},pointLabels:{display:!1},startAngle:0}}};class zn extends En{}zn.id="pie",zn.defaults={cutout:0,rotation:0,circumference:360,radius:"100%"};class Fn extends Ls{getLabelAndValue(t){const e=this._cachedMeta.vScale,i=this.getParsed(t);return{label:e.getLabels()[t],value:""+e.getLabelForValue(i[e.axis])}}parseObjectData(t,e,i,s){return Ue.bind(this)(t,e,i,s)}update(t){const e=this._cachedMeta,i=e.dataset,s=e.data||[],n=e.iScale.getLabels();if(i.points=s,"resize"!==t){const e=this.resolveDatasetElementOptions(t);this.options.showLine||(e.borderWidth=0);const o={_loop:!0,_fullLoop:n.length===s.length,options:e};this.updateElement(i,void 0,o,t)}this.updateElements(s,0,s.length,t)}updateElements(t,e,i,s){const n=this._cachedMeta.rScale,o="reset"===s;for(let a=e;a<e+i;a++){const e=t[a],i=this.resolveDataElementOptions(a,e.active?"active":s),r=n.getPointPositionForValue(a,this.getParsed(a).r),l=o?n.xCenter:r.x,h=o?n.yCenter:r.y,c={x:l,y:h,angle:r.angle,skip:isNaN(l)||isNaN(h),options:i};this.updateElement(e,a,c,s)}}}Fn.id="radar",Fn.defaults={datasetElementType:"line",dataElementType:"point",indexAxis:"r",showLine:!0,elements:{line:{fill:"start"}}},Fn.overrides={aspectRatio:1,scales:{r:{type:"radialLinear"}}};class Vn extends Ls{update(t){const e=this._cachedMeta,{data:i=[]}=e,s=this.chart._animationsDisabled;let{start:n,count:o}=gt(e,i,s);if(this._drawStart=n,this._drawCount=o,pt(e)&&(n=0,o=i.length),this.options.showLine){const{dataset:n,_dataset:o}=e;n._chart=this.chart,n._datasetIndex=this.index,n._decimated=!!o._decimated,n.points=i;const a=this.resolveDatasetElementOptions(t);a.segment=this.options.segment,this.updateElement(n,void 0,{animated:!s,options:a},t)}this.updateElements(i,n,o,t)}addElements(){const{showLine:t}=this.options;!this.datasetElementType&&t&&(this.datasetElementType=Us.getElement("line")),super.addElements()}updateElements(t,e,s,n){const o="reset"===n,{iScale:a,vScale:r,_stacked:l,_dataset:h}=this._cachedMeta,c=this.resolveDataElementOptions(e,n),d=this.getSharedOptions(c),u=this.includeOptions(n,d),f=a.axis,g=r.axis,{spanGaps:p,segment:m}=this.options,b=B(p)?p:Number.POSITIVE_INFINITY,x=this.chart._animationsDisabled||o||"none"===n;let _=e>0&&this.getParsed(e-1);for(let c=e;c<e+s;++c){const e=t[c],s=this.getParsed(c),p=x?e:{},y=i(s[g]),v=p[f]=a.getPixelForValue(s[f],c),w=p[g]=o||y?r.getBasePixel():r.getPixelForValue(l?this.applyStack(r,s,l):s[g],c);p.skip=isNaN(v)||isNaN(w)||y,p.stop=c>0&&Math.abs(s[f]-_[f])>b,m&&(p.parsed=s,p.raw=h.data[c]),u&&(p.options=d||this.resolveDataElementOptions(c,e.active?"active":n)),x||this.updateElement(e,c,p,n),_=s}this.updateSharedOptions(d,n,c)}getMaxOverflow(){const t=this._cachedMeta,e=t.data||[];if(!this.options.showLine){let t=0;for(let i=e.length-1;i>=0;--i)t=Math.max(t,e[i].size(this.resolveDataElementOptions(i))/2);return t>0&&t}const i=t.dataset,s=i.options&&i.options.borderWidth||0;if(!e.length)return s;const n=e[0].size(this.resolveDataElementOptions(0)),o=e[e.length-1].size(this.resolveDataElementOptions(e.length-1));return Math.max(s,n,o)/2}}Vn.id="scatter",Vn.defaults={datasetElementType:!1,dataElementType:"point",showLine:!1,fill:!1},Vn.overrides={interaction:{mode:"point"},plugins:{tooltip:{callbacks:{title:()=>"",label:t=>"("+t.label+", "+t.formattedValue+")"}}},scales:{x:{type:"linear"},y:{type:"linear"}}};var Bn=Object.freeze({__proto__:null,BarController:Tn,BubbleController:Ln,DoughnutController:En,LineController:Rn,PolarAreaController:In,PieController:zn,RadarController:Fn,ScatterController:Vn});function Nn(t,e,i){const{startAngle:s,pixelMargin:n,x:o,y:a,outerRadius:r,innerRadius:l}=e;let h=n/r;t.beginPath(),t.arc(o,a,r,s-h,i+h),l>n?(h=n/l,t.arc(o,a,l,i+h,s-h,!0)):t.arc(o,a,n,i+L,s-L),t.closePath(),t.clip()}function Wn(t,e,i,s){const n=ui(t.options.borderRadius,["outerStart","outerEnd","innerStart","innerEnd"]);const o=(i-e)/2,a=Math.min(o,s*e/2),r=t=>{const e=(i-Math.min(o,t))*s/2;return Z(t,0,Math.min(o,e))};return{outerStart:r(n.outerStart),outerEnd:r(n.outerEnd),innerStart:Z(n.innerStart,0,a),innerEnd:Z(n.innerEnd,0,a)}}function jn(t,e,i,s){return{x:i+t*Math.cos(e),y:s+t*Math.sin(e)}}function Hn(t,e,i,s,n,o){const{x:a,y:r,startAngle:l,pixelMargin:h,innerRadius:c}=e,d=Math.max(e.outerRadius+s+i-h,0),u=c>0?c+s+i+h:0;let f=0;const g=n-l;if(s){const t=((c>0?c-s:0)+(d>0?d-s:0))/2;f=(g-(0!==t?g*t/(t+s):g))/2}const p=(g-Math.max(.001,g*d-i/D)/d)/2,m=l+p+f,b=n-p-f,{outerStart:x,outerEnd:_,innerStart:y,innerEnd:v}=Wn(e,u,d,b-m),w=d-x,M=d-_,k=m+x/w,S=b-_/M,P=u+y,O=u+v,C=m+y/P,A=b-v/O;if(t.beginPath(),o){if(t.arc(a,r,d,k,S),_>0){const e=jn(M,S,a,r);t.arc(e.x,e.y,_,S,b+L)}const e=jn(O,b,a,r);if(t.lineTo(e.x,e.y),v>0){const e=jn(O,A,a,r);t.arc(e.x,e.y,v,b+L,A+Math.PI)}if(t.arc(a,r,u,b-v/u,m+y/u,!0),y>0){const e=jn(P,C,a,r);t.arc(e.x,e.y,y,C+Math.PI,m-L)}const i=jn(w,m,a,r);if(t.lineTo(i.x,i.y),x>0){const e=jn(w,k,a,r);t.arc(e.x,e.y,x,m-L,k)}}else{t.moveTo(a,r);const e=Math.cos(k)*d+a,i=Math.sin(k)*d+r;t.lineTo(e,i);const s=Math.cos(S)*d+a,n=Math.sin(S)*d+r;t.lineTo(s,n)}t.closePath()}function $n(t,e,i,s,n,o){const{options:a}=e,{borderWidth:r,borderJoinStyle:l}=a,h="inner"===a.borderAlign;r&&(h?(t.lineWidth=2*r,t.lineJoin=l||"round"):(t.lineWidth=r,t.lineJoin=l||"bevel"),e.fullCircles&&function(t,e,i){const{x:s,y:n,startAngle:o,pixelMargin:a,fullCircles:r}=e,l=Math.max(e.outerRadius-a,0),h=e.innerRadius+a;let c;for(i&&Nn(t,e,o+O),t.beginPath(),t.arc(s,n,h,o+O,o,!0),c=0;c<r;++c)t.stroke();for(t.beginPath(),t.arc(s,n,l,o,o+O),c=0;c<r;++c)t.stroke()}(t,e,h),h&&Nn(t,e,n),Hn(t,e,i,s,n,o),t.stroke())}class Yn extends Es{constructor(t){super(),this.options=void 0,this.circumference=void 0,this.startAngle=void 0,this.endAngle=void 0,this.innerRadius=void 0,this.outerRadius=void 0,this.pixelMargin=0,this.fullCircles=0,t&&Object.assign(this,t)}inRange(t,e,i){const s=this.getProps(["x","y"],i),{angle:n,distance:o}=U(s,{x:t,y:e}),{startAngle:a,endAngle:l,innerRadius:h,outerRadius:c,circumference:d}=this.getProps(["startAngle","endAngle","innerRadius","outerRadius","circumference"],i),u=this.options.spacing/2,f=r(d,l-a)>=O||G(n,a,l),g=Q(o,h+u,c+u);return f&&g}getCenterPoint(t){const{x:e,y:i,startAngle:s,endAngle:n,innerRadius:o,outerRadius:a}=this.getProps(["x","y","startAngle","endAngle","innerRadius","outerRadius","circumference"],t),{offset:r,spacing:l}=this.options,h=(s+n)/2,c=(o+a+l+r)/2;return{x:e+Math.cos(h)*c,y:i+Math.sin(h)*c}}tooltipPosition(t){return this.getCenterPoint(t)}draw(t){const{options:e,circumference:i}=this,s=(e.offset||0)/2,n=(e.spacing||0)/2,o=e.circular;if(this.pixelMargin="inner"===e.borderAlign?.33:0,this.fullCircles=i>O?Math.floor(i/O):0,0===i||this.innerRadius<0||this.outerRadius<0)return;t.save();let a=0;if(s){a=s/2;const e=(this.startAngle+this.endAngle)/2;t.translate(Math.cos(e)*a,Math.sin(e)*a),this.circumference>=D&&(a=s)}t.fillStyle=e.backgroundColor,t.strokeStyle=e.borderColor;const r=function(t,e,i,s,n){const{fullCircles:o,startAngle:a,circumference:r}=e;let l=e.endAngle;if(o){Hn(t,e,i,s,a+O,n);for(let e=0;e<o;++e)t.fill();isNaN(r)||(l=a+r%O,r%O==0&&(l+=O))}return Hn(t,e,i,s,l,n),t.fill(),l}(t,this,a,n,o);$n(t,this,a,n,r,o),t.restore()}}function Un(t,e,i=e){t.lineCap=r(i.borderCapStyle,e.borderCapStyle),t.setLineDash(r(i.borderDash,e.borderDash)),t.lineDashOffset=r(i.borderDashOffset,e.borderDashOffset),t.lineJoin=r(i.borderJoinStyle,e.borderJoinStyle),t.lineWidth=r(i.borderWidth,e.borderWidth),t.strokeStyle=r(i.borderColor,e.borderColor)}function Xn(t,e,i){t.lineTo(i.x,i.y)}function qn(t,e,i={}){const s=t.length,{start:n=0,end:o=s-1}=i,{start:a,end:r}=e,l=Math.max(n,a),h=Math.min(o,r),c=n<a&&o<a||n>r&&o>r;return{count:s,start:l,loop:e.loop,ilen:h<l&&!c?s+h-l:h-l}}function Kn(t,e,i,s){const{points:n,options:o}=e,{count:a,start:r,loop:l,ilen:h}=qn(n,i,s),c=function(t){return t.stepped?Oe:t.tension||"monotone"===t.cubicInterpolationMode?Ce:Xn}(o);let d,u,f,{move:g=!0,reverse:p}=s||{};for(d=0;d<=h;++d)u=n[(r+(p?h-d:d))%a],u.skip||(g?(t.moveTo(u.x,u.y),g=!1):c(t,f,u,p,o.stepped),f=u);return l&&(u=n[(r+(p?h:0))%a],c(t,f,u,p,o.stepped)),!!l}function Gn(t,e,i,s){const n=e.points,{count:o,start:a,ilen:r}=qn(n,i,s),{move:l=!0,reverse:h}=s||{};let c,d,u,f,g,p,m=0,b=0;const x=t=>(a+(h?r-t:t))%o,_=()=>{f!==g&&(t.lineTo(m,g),t.lineTo(m,f),t.lineTo(m,p))};for(l&&(d=n[x(0)],t.moveTo(d.x,d.y)),c=0;c<=r;++c){if(d=n[x(c)],d.skip)continue;const e=d.x,i=d.y,s=0|e;s===u?(i<f?f=i:i>g&&(g=i),m=(b*m+e)/++b):(_(),t.lineTo(e,i),u=s,b=0,f=g=i),p=i}_()}function Zn(t){const e=t.options,i=e.borderDash&&e.borderDash.length;return!(t._decimated||t._loop||e.tension||"monotone"===e.cubicInterpolationMode||e.stepped||i)?Gn:Kn}Yn.id="arc",Yn.defaults={borderAlign:"center",borderColor:"#fff",borderJoinStyle:void 0,borderRadius:0,borderWidth:2,offset:0,spacing:0,angle:void 0,circular:!0},Yn.defaultRoutes={backgroundColor:"backgroundColor"};const Jn="function"==typeof Path2D;function Qn(t,e,i,s){Jn&&!e.options.segment?function(t,e,i,s){let n=e._path;n||(n=e._path=new Path2D,e.path(n,i,s)&&n.closePath()),Un(t,e.options),t.stroke(n)}(t,e,i,s):function(t,e,i,s){const{segments:n,options:o}=e,a=Zn(e);for(const r of n)Un(t,o,r.style),t.beginPath(),a(t,e,r,{start:i,end:i+s-1})&&t.closePath(),t.stroke()}(t,e,i,s)}class to extends Es{constructor(t){super(),this.animated=!0,this.options=void 0,this._chart=void 0,this._loop=void 0,this._fullLoop=void 0,this._path=void 0,this._points=void 0,this._segments=void 0,this._decimated=!1,this._pointsUpdated=!1,this._datasetIndex=void 0,t&&Object.assign(this,t)}updateControlPoints(t,e){const i=this.options;if((i.tension||"monotone"===i.cubicInterpolationMode)&&!i.stepped&&!this._pointsUpdated){const s=i.spanGaps?this._loop:this._fullLoop;Qe(this._points,i,t,s,e),this._pointsUpdated=!0}}set points(t){this._points=t,delete this._segments,delete this._path,this._pointsUpdated=!1}get points(){return this._points}get segments(){return this._segments||(this._segments=Di(this,this.options.segment))}first(){const t=this.segments,e=this.points;return t.length&&e[t[0].start]}last(){const t=this.segments,e=this.points,i=t.length;return i&&e[t[i-1].end]}interpolate(t,e){const i=this.options,s=t[e],n=this.points,o=Pi(this,{property:e,start:s,end:s});if(!o.length)return;const a=[],r=function(t){return t.stepped?oi:t.tension||"monotone"===t.cubicInterpolationMode?ai:ni}(i);let l,h;for(l=0,h=o.length;l<h;++l){const{start:h,end:c}=o[l],d=n[h],u=n[c];if(d===u){a.push(d);continue}const f=r(d,u,Math.abs((s-d[e])/(u[e]-d[e])),i.stepped);f[e]=t[e],a.push(f)}return 1===a.length?a[0]:a}pathSegment(t,e,i){return Zn(this)(t,this,e,i)}path(t,e,i){const s=this.segments,n=Zn(this);let o=this._loop;e=e||0,i=i||this.points.length-e;for(const a of s)o&=n(t,this,a,{start:e,end:e+i-1});return!!o}draw(t,e,i,s){const n=this.options||{};(this.points||[]).length&&n.borderWidth&&(t.save(),Qn(t,this,i,s),t.restore()),this.animated&&(this._pointsUpdated=!1,this._path=void 0)}}function eo(t,e,i,s){const n=t.options,{[i]:o}=t.getProps([i],s);return Math.abs(e-o)<n.radius+n.hitRadius}to.id="line",to.defaults={borderCapStyle:"butt",borderDash:[],borderDashOffset:0,borderJoinStyle:"miter",borderWidth:3,capBezierPoints:!0,cubicInterpolationMode:"default",fill:!1,spanGaps:!1,stepped:!1,tension:0},to.defaultRoutes={backgroundColor:"backgroundColor",borderColor:"borderColor"},to.descriptors={_scriptable:!0,_indexable:t=>"borderDash"!==t&&"fill"!==t};class io extends Es{constructor(t){super(),this.options=void 0,this.parsed=void 0,this.skip=void 0,this.stop=void 0,t&&Object.assign(this,t)}inRange(t,e,i){const s=this.options,{x:n,y:o}=this.getProps(["x","y"],i);return Math.pow(t-n,2)+Math.pow(e-o,2)<Math.pow(s.hitRadius+s.radius,2)}inXRange(t,e){return eo(this,t,"x",e)}inYRange(t,e){return eo(this,t,"y",e)}getCenterPoint(t){const{x:e,y:i}=this.getProps(["x","y"],t);return{x:e,y:i}}size(t){let e=(t=t||this.options||{}).radius||0;e=Math.max(e,e&&t.hoverRadius||0);return 2*(e+(e&&t.borderWidth||0))}draw(t,e){const i=this.options;this.skip||i.radius<.1||!Se(this,e,this.size(i)/2)||(t.strokeStyle=i.borderColor,t.lineWidth=i.borderWidth,t.fillStyle=i.backgroundColor,Me(t,i,this.x,this.y))}getRange(){const t=this.options||{};return t.radius+t.hitRadius}}function so(t,e){const{x:i,y:s,base:n,width:o,height:a}=t.getProps(["x","y","base","width","height"],e);let r,l,h,c,d;return t.horizontal?(d=a/2,r=Math.min(i,n),l=Math.max(i,n),h=s-d,c=s+d):(d=o/2,r=i-d,l=i+d,h=Math.min(s,n),c=Math.max(s,n)),{left:r,top:h,right:l,bottom:c}}function no(t,e,i,s){return t?0:Z(e,i,s)}function oo(t){const e=so(t),i=e.right-e.left,s=e.bottom-e.top,o=function(t,e,i){const s=t.options.borderWidth,n=t.borderSkipped,o=fi(s);return{t:no(n.top,o.top,0,i),r:no(n.right,o.right,0,e),b:no(n.bottom,o.bottom,0,i),l:no(n.left,o.left,0,e)}}(t,i/2,s/2),a=function(t,e,i){const{enableBorderRadius:s}=t.getProps(["enableBorderRadius"]),o=t.options.borderRadius,a=gi(o),r=Math.min(e,i),l=t.borderSkipped,h=s||n(o);return{topLeft:no(!h||l.top||l.left,a.topLeft,0,r),topRight:no(!h||l.top||l.right,a.topRight,0,r),bottomLeft:no(!h||l.bottom||l.left,a.bottomLeft,0,r),bottomRight:no(!h||l.bottom||l.right,a.bottomRight,0,r)}}(t,i/2,s/2);return{outer:{x:e.left,y:e.top,w:i,h:s,radius:a},inner:{x:e.left+o.l,y:e.top+o.t,w:i-o.l-o.r,h:s-o.t-o.b,radius:{topLeft:Math.max(0,a.topLeft-Math.max(o.t,o.l)),topRight:Math.max(0,a.topRight-Math.max(o.t,o.r)),bottomLeft:Math.max(0,a.bottomLeft-Math.max(o.b,o.l)),bottomRight:Math.max(0,a.bottomRight-Math.max(o.b,o.r))}}}}function ao(t,e,i,s){const n=null===e,o=null===i,a=t&&!(n&&o)&&so(t,s);return a&&(n||Q(e,a.left,a.right))&&(o||Q(i,a.top,a.bottom))}function ro(t,e){t.rect(e.x,e.y,e.w,e.h)}function lo(t,e,i={}){const s=t.x!==i.x?-e:0,n=t.y!==i.y?-e:0,o=(t.x+t.w!==i.x+i.w?e:0)-s,a=(t.y+t.h!==i.y+i.h?e:0)-n;return{x:t.x+s,y:t.y+n,w:t.w+o,h:t.h+a,radius:t.radius}}io.id="point",io.defaults={borderWidth:1,hitRadius:1,hoverBorderWidth:1,hoverRadius:4,pointStyle:"circle",radius:3,rotation:0},io.defaultRoutes={backgroundColor:"backgroundColor",borderColor:"borderColor"};class ho extends Es{constructor(t){super(),this.options=void 0,this.horizontal=void 0,this.base=void 0,this.width=void 0,this.height=void 0,this.inflateAmount=void 0,t&&Object.assign(this,t)}draw(t){const{inflateAmount:e,options:{borderColor:i,backgroundColor:s}}=this,{inner:n,outer:o}=oo(this),a=(r=o.radius).topLeft||r.topRight||r.bottomLeft||r.bottomRight?Le:ro;var r;t.save(),o.w===n.w&&o.h===n.h||(t.beginPath(),a(t,lo(o,e,n)),t.clip(),a(t,lo(n,-e,o)),t.fillStyle=i,t.fill("evenodd")),t.beginPath(),a(t,lo(n,e)),t.fillStyle=s,t.fill(),t.restore()}inRange(t,e,i){return ao(this,t,e,i)}inXRange(t,e){return ao(this,t,null,e)}inYRange(t,e){return ao(this,null,t,e)}getCenterPoint(t){const{x:e,y:i,base:s,horizontal:n}=this.getProps(["x","y","base","horizontal"],t);return{x:n?(e+s)/2:e,y:n?i:(i+s)/2}}getRange(t){return"x"===t?this.width/2:this.height/2}}ho.id="bar",ho.defaults={borderSkipped:"start",borderWidth:0,borderRadius:0,inflateAmount:"auto",pointStyle:void 0},ho.defaultRoutes={backgroundColor:"backgroundColor",borderColor:"borderColor"};var co=Object.freeze({__proto__:null,ArcElement:Yn,LineElement:to,PointElement:io,BarElement:ho});function uo(t){if(t._decimated){const e=t._data;delete t._decimated,delete t._data,Object.defineProperty(t,"data",{value:e})}}function fo(t){t.data.datasets.forEach((t=>{uo(t)}))}var go={id:"decimation",defaults:{algorithm:"min-max",enabled:!1},beforeElementsUpdate:(t,e,s)=>{if(!s.enabled)return void fo(t);const n=t.width;t.data.datasets.forEach(((e,o)=>{const{_data:a,indexAxis:r}=e,l=t.getDatasetMeta(o),h=a||e.data;if("y"===bi([r,t.options.indexAxis]))return;if(!l.controller.supportsDecimation)return;const c=t.scales[l.xAxisID];if("linear"!==c.type&&"time"!==c.type)return;if(t.options.parsing)return;let{start:d,count:u}=function(t,e){const i=e.length;let s,n=0;const{iScale:o}=t,{min:a,max:r,minDefined:l,maxDefined:h}=o.getUserBounds();return l&&(n=Z(et(e,o.axis,a).lo,0,i-1)),s=h?Z(et(e,o.axis,r).hi+1,n,i)-n:i-n,{start:n,count:s}}(l,h);if(u<=(s.threshold||4*n))return void uo(e);let f;switch(i(a)&&(e._data=h,delete e.data,Object.defineProperty(e,"data",{configurable:!0,enumerable:!0,get:function(){return this._decimated},set:function(t){this._data=t}})),s.algorithm){case"lttb":f=function(t,e,i,s,n){const o=n.samples||s;if(o>=i)return t.slice(e,e+i);const a=[],r=(i-2)/(o-2);let l=0;const h=e+i-1;let c,d,u,f,g,p=e;for(a[l++]=t[p],c=0;c<o-2;c++){let s,n=0,o=0;const h=Math.floor((c+1)*r)+1+e,m=Math.min(Math.floor((c+2)*r)+1,i)+e,b=m-h;for(s=h;s<m;s++)n+=t[s].x,o+=t[s].y;n/=b,o/=b;const x=Math.floor(c*r)+1+e,_=Math.min(Math.floor((c+1)*r)+1,i)+e,{x:y,y:v}=t[p];for(u=f=-1,s=x;s<_;s++)f=.5*Math.abs((y-n)*(t[s].y-v)-(y-t[s].x)*(o-v)),f>u&&(u=f,d=t[s],g=s);a[l++]=d,p=g}return a[l++]=t[h],a}(h,d,u,n,s);break;case"min-max":f=function(t,e,s,n){let o,a,r,l,h,c,d,u,f,g,p=0,m=0;const b=[],x=e+s-1,_=t[e].x,y=t[x].x-_;for(o=e;o<e+s;++o){a=t[o],r=(a.x-_)/y*n,l=a.y;const e=0|r;if(e===h)l<f?(f=l,c=o):l>g&&(g=l,d=o),p=(m*p+a.x)/++m;else{const s=o-1;if(!i(c)&&!i(d)){const e=Math.min(c,d),i=Math.max(c,d);e!==u&&e!==s&&b.push({...t[e],x:p}),i!==u&&i!==s&&b.push({...t[i],x:p})}o>0&&s!==u&&b.push(t[s]),b.push(a),h=e,m=0,f=g=l,c=d=u=o}}return b}(h,d,u,n);break;default:throw new Error(`Unsupported decimation algorithm '${s.algorithm}'`)}e._decimated=f}))},destroy(t){fo(t)}};function po(t,e,i,s){if(s)return;let n=e[t],o=i[t];return"angle"===t&&(n=K(n),o=K(o)),{property:t,start:n,end:o}}function mo(t,e,i){for(;e>t;e--){const t=i[e];if(!isNaN(t.x)&&!isNaN(t.y))break}return e}function bo(t,e,i,s){return t&&e?s(t[i],e[i]):t?t[i]:e?e[i]:0}function xo(t,e){let i=[],n=!1;return s(t)?(n=!0,i=t):i=function(t,e){const{x:i=null,y:s=null}=t||{},n=e.points,o=[];return e.segments.forEach((({start:t,end:e})=>{e=mo(t,e,n);const a=n[t],r=n[e];null!==s?(o.push({x:a.x,y:s}),o.push({x:r.x,y:s})):null!==i&&(o.push({x:i,y:a.y}),o.push({x:i,y:r.y}))})),o}(t,e),i.length?new to({points:i,options:{tension:0},_loop:n,_fullLoop:n}):null}function _o(t){return t&&!1!==t.fill}function yo(t,e,i){let s=t[e].fill;const n=[e];let a;if(!i)return s;for(;!1!==s&&-1===n.indexOf(s);){if(!o(s))return s;if(a=t[s],!a)return!1;if(a.visible)return s;n.push(s),s=a.fill}return!1}function vo(t,e,i){const s=function(t){const e=t.options,i=e.fill;let s=r(i&&i.target,i);void 0===s&&(s=!!e.backgroundColor);if(!1===s||null===s)return!1;if(!0===s)return"origin";return s}(t);if(n(s))return!isNaN(s.value)&&s;let a=parseFloat(s);return o(a)&&Math.floor(a)===a?function(t,e,i,s){"-"!==t&&"+"!==t||(i=e+i);if(i===e||i<0||i>=s)return!1;return i}(s[0],e,a,i):["origin","start","end","stack","shape"].indexOf(s)>=0&&s}function wo(t,e,i){const s=[];for(let n=0;n<i.length;n++){const o=i[n],{first:a,last:r,point:l}=Mo(o,e,"x");if(!(!l||a&&r))if(a)s.unshift(l);else if(t.push(l),!r)break}t.push(...s)}function Mo(t,e,i){const s=t.interpolate(e,i);if(!s)return{};const n=s[i],o=t.segments,a=t.points;let r=!1,l=!1;for(let t=0;t<o.length;t++){const e=o[t],s=a[e.start][i],h=a[e.end][i];if(Q(n,s,h)){r=n===s,l=n===h;break}}return{first:r,last:l,point:s}}class ko{constructor(t){this.x=t.x,this.y=t.y,this.radius=t.radius}pathSegment(t,e,i){const{x:s,y:n,radius:o}=this;return e=e||{start:0,end:O},t.arc(s,n,o,e.end,e.start,!0),!i.bounds}interpolate(t){const{x:e,y:i,radius:s}=this,n=t.angle;return{x:e+Math.cos(n)*s,y:i+Math.sin(n)*s,angle:n}}}function So(t){const{chart:e,fill:i,line:s}=t;if(o(i))return function(t,e){const i=t.getDatasetMeta(e);return i&&t.isDatasetVisible(e)?i.dataset:null}(e,i);if("stack"===i)return function(t){const{scale:e,index:i,line:s}=t,n=[],o=s.segments,a=s.points,r=function(t,e){const i=[],s=t.getMatchingVisibleMetas("line");for(let t=0;t<s.length;t++){const n=s[t];if(n.index===e)break;n.hidden||i.unshift(n.dataset)}return i}(e,i);r.push(xo({x:null,y:e.bottom},s));for(let t=0;t<o.length;t++){const e=o[t];for(let t=e.start;t<=e.end;t++)wo(n,a[t],r)}return new to({points:n,options:{}})}(t);if("shape"===i)return!0;const a=function(t){if((t.scale||{}).getPointPositionForValue)return function(t){const{scale:e,fill:i}=t,s=e.options,o=e.getLabels().length,a=s.reverse?e.max:e.min,r=function(t,e,i){let s;return s="start"===t?i:"end"===t?e.options.reverse?e.min:e.max:n(t)?t.value:e.getBaseValue(),s}(i,e,a),l=[];if(s.grid.circular){const t=e.getPointPositionForValue(0,a);return new ko({x:t.x,y:t.y,radius:e.getDistanceFromCenterForValue(r)})}for(let t=0;t<o;++t)l.push(e.getPointPositionForValue(t,r));return l}(t);return function(t){const{scale:e={},fill:i}=t,s=function(t,e){let i=null;return"start"===t?i=e.bottom:"end"===t?i=e.top:n(t)?i=e.getPixelForValue(t.value):e.getBasePixel&&(i=e.getBasePixel()),i}(i,e);if(o(s)){const t=e.isHorizontal();return{x:t?s:null,y:t?null:s}}return null}(t)}(t);return a instanceof ko?a:xo(a,s)}function Po(t,e,i){const s=So(e),{line:n,scale:o,axis:a}=e,r=n.options,l=r.fill,h=r.backgroundColor,{above:c=h,below:d=h}=l||{};s&&n.points.length&&(Pe(t,i),function(t,e){const{line:i,target:s,above:n,below:o,area:a,scale:r}=e,l=i._loop?"angle":e.axis;t.save(),"x"===l&&o!==n&&(Do(t,s,a.top),Oo(t,{line:i,target:s,color:n,scale:r,property:l}),t.restore(),t.save(),Do(t,s,a.bottom));Oo(t,{line:i,target:s,color:o,scale:r,property:l}),t.restore()}(t,{line:n,target:s,above:c,below:d,area:i,scale:o,axis:a}),De(t))}function Do(t,e,i){const{segments:s,points:n}=e;let o=!0,a=!1;t.beginPath();for(const r of s){const{start:s,end:l}=r,h=n[s],c=n[mo(s,l,n)];o?(t.moveTo(h.x,h.y),o=!1):(t.lineTo(h.x,i),t.lineTo(h.x,h.y)),a=!!e.pathSegment(t,r,{move:a}),a?t.closePath():t.lineTo(c.x,i)}t.lineTo(e.first().x,i),t.closePath(),t.clip()}function Oo(t,e){const{line:i,target:s,property:n,color:o,scale:a}=e,r=function(t,e,i){const s=t.segments,n=t.points,o=e.points,a=[];for(const t of s){let{start:s,end:r}=t;r=mo(s,r,n);const l=po(i,n[s],n[r],t.loop);if(!e.segments){a.push({source:t,target:l,start:n[s],end:n[r]});continue}const h=Pi(e,l);for(const e of h){const s=po(i,o[e.start],o[e.end],e.loop),r=Si(t,n,s);for(const t of r)a.push({source:t,target:e,start:{[i]:bo(l,s,"start",Math.max)},end:{[i]:bo(l,s,"end",Math.min)}})}}return a}(i,s,n);for(const{source:e,target:l,start:h,end:c}of r){const{style:{backgroundColor:r=o}={}}=e,d=!0!==s;t.save(),t.fillStyle=r,Co(t,a,d&&po(n,h,c)),t.beginPath();const u=!!i.pathSegment(t,e);let f;if(d){u?t.closePath():Ao(t,s,c,n);const e=!!s.pathSegment(t,l,{move:u,reverse:!0});f=u&&e,f||Ao(t,s,h,n)}t.closePath(),t.fill(f?"evenodd":"nonzero"),t.restore()}}function Co(t,e,i){const{top:s,bottom:n}=e.chart.chartArea,{property:o,start:a,end:r}=i||{};"x"===o&&(t.beginPath(),t.rect(a,s,r-a,n-s),t.clip())}function Ao(t,e,i,s){const n=e.interpolate(i,s);n&&t.lineTo(n.x,n.y)}var To={id:"filler",afterDatasetsUpdate(t,e,i){const s=(t.data.datasets||[]).length,n=[];let o,a,r,l;for(a=0;a<s;++a)o=t.getDatasetMeta(a),r=o.dataset,l=null,r&&r.options&&r instanceof to&&(l={visible:t.isDatasetVisible(a),index:a,fill:vo(r,a,s),chart:t,axis:o.controller.options.indexAxis,scale:o.vScale,line:r}),o.$filler=l,n.push(l);for(a=0;a<s;++a)l=n[a],l&&!1!==l.fill&&(l.fill=yo(n,a,i.propagate))},beforeDraw(t,e,i){const s="beforeDraw"===i.drawTime,n=t.getSortedVisibleDatasetMetas(),o=t.chartArea;for(let e=n.length-1;e>=0;--e){const i=n[e].$filler;i&&(i.line.updateControlPoints(o,i.axis),s&&i.fill&&Po(t.ctx,i,o))}},beforeDatasetsDraw(t,e,i){if("beforeDatasetsDraw"!==i.drawTime)return;const s=t.getSortedVisibleDatasetMetas();for(let e=s.length-1;e>=0;--e){const i=s[e].$filler;_o(i)&&Po(t.ctx,i,t.chartArea)}},beforeDatasetDraw(t,e,i){const s=e.meta.$filler;_o(s)&&"beforeDatasetDraw"===i.drawTime&&Po(t.ctx,s,t.chartArea)},defaults:{propagate:!0,drawTime:"beforeDatasetDraw"}};const Lo=(t,e)=>{let{boxHeight:i=e,boxWidth:s=e}=t;return t.usePointStyle&&(i=Math.min(i,e),s=t.pointStyleWidth||Math.min(s,e)),{boxWidth:s,boxHeight:i,itemHeight:Math.max(e,i)}};class Eo extends Es{constructor(t){super(),this._added=!1,this.legendHitBoxes=[],this._hoveredItem=null,this.doughnutMode=!1,this.chart=t.chart,this.options=t.options,this.ctx=t.ctx,this.legendItems=void 0,this.columnSizes=void 0,this.lineWidths=void 0,this.maxHeight=void 0,this.maxWidth=void 0,this.top=void 0,this.bottom=void 0,this.left=void 0,this.right=void 0,this.height=void 0,this.width=void 0,this._margins=void 0,this.position=void 0,this.weight=void 0,this.fullSize=void 0}update(t,e,i){this.maxWidth=t,this.maxHeight=e,this._margins=i,this.setDimensions(),this.buildLabels(),this.fit()}setDimensions(){this.isHorizontal()?(this.width=this.maxWidth,this.left=this._margins.left,this.right=this.width):(this.height=this.maxHeight,this.top=this._margins.top,this.bottom=this.height)}buildLabels(){const t=this.options.labels||{};let e=c(t.generateLabels,[this.chart],this)||[];t.filter&&(e=e.filter((e=>t.filter(e,this.chart.data)))),t.sort&&(e=e.sort(((e,i)=>t.sort(e,i,this.chart.data)))),this.options.reverse&&e.reverse(),this.legendItems=e}fit(){const{options:t,ctx:e}=this;if(!t.display)return void(this.width=this.height=0);const i=t.labels,s=mi(i.font),n=s.size,o=this._computeTitleHeight(),{boxWidth:a,itemHeight:r}=Lo(i,n);let l,h;e.font=s.string,this.isHorizontal()?(l=this.maxWidth,h=this._fitRows(o,n,a,r)+10):(h=this.maxHeight,l=this._fitCols(o,n,a,r)+10),this.width=Math.min(l,t.maxWidth||this.maxWidth),this.height=Math.min(h,t.maxHeight||this.maxHeight)}_fitRows(t,e,i,s){const{ctx:n,maxWidth:o,options:{labels:{padding:a}}}=this,r=this.legendHitBoxes=[],l=this.lineWidths=[0],h=s+a;let c=t;n.textAlign="left",n.textBaseline="middle";let d=-1,u=-h;return this.legendItems.forEach(((t,f)=>{const g=i+e/2+n.measureText(t.text).width;(0===f||l[l.length-1]+g+2*a>o)&&(c+=h,l[l.length-(f>0?0:1)]=0,u+=h,d++),r[f]={left:0,top:u,row:d,width:g,height:s},l[l.length-1]+=g+a})),c}_fitCols(t,e,i,s){const{ctx:n,maxHeight:o,options:{labels:{padding:a}}}=this,r=this.legendHitBoxes=[],l=this.columnSizes=[],h=o-t;let c=a,d=0,u=0,f=0,g=0;return this.legendItems.forEach(((t,o)=>{const p=i+e/2+n.measureText(t.text).width;o>0&&u+s+2*a>h&&(c+=d+a,l.push({width:d,height:u}),f+=d+a,g++,d=u=0),r[o]={left:f,top:u,col:g,width:p,height:s},d=Math.max(d,p),u+=s+a})),c+=d,l.push({width:d,height:u}),c}adjustHitBoxes(){if(!this.options.display)return;const t=this._computeTitleHeight(),{legendHitBoxes:e,options:{align:i,labels:{padding:s},rtl:n}}=this,o=yi(n,this.left,this.width);if(this.isHorizontal()){let n=0,a=ut(i,this.left+s,this.right-this.lineWidths[n]);for(const r of e)n!==r.row&&(n=r.row,a=ut(i,this.left+s,this.right-this.lineWidths[n])),r.top+=this.top+t+s,r.left=o.leftForLtr(o.x(a),r.width),a+=r.width+s}else{let n=0,a=ut(i,this.top+t+s,this.bottom-this.columnSizes[n].height);for(const r of e)r.col!==n&&(n=r.col,a=ut(i,this.top+t+s,this.bottom-this.columnSizes[n].height)),r.top=a,r.left+=this.left+s,r.left=o.leftForLtr(o.x(r.left),r.width),a+=r.height+s}}isHorizontal(){return"top"===this.options.position||"bottom"===this.options.position}draw(){if(this.options.display){const t=this.ctx;Pe(t,this),this._draw(),De(t)}}_draw(){const{options:t,columnSizes:e,lineWidths:i,ctx:s}=this,{align:n,labels:o}=t,a=ne.color,l=yi(t.rtl,this.left,this.width),h=mi(o.font),{color:c,padding:d}=o,u=h.size,f=u/2;let g;this.drawTitle(),s.textAlign=l.textAlign("left"),s.textBaseline="middle",s.lineWidth=.5,s.font=h.string;const{boxWidth:p,boxHeight:m,itemHeight:b}=Lo(o,u),x=this.isHorizontal(),_=this._computeTitleHeight();g=x?{x:ut(n,this.left+d,this.right-i[0]),y:this.top+d+_,line:0}:{x:this.left+d,y:ut(n,this.top+_+d,this.bottom-e[0].height),line:0},vi(this.ctx,t.textDirection);const y=b+d;this.legendItems.forEach(((v,w)=>{s.strokeStyle=v.fontColor||c,s.fillStyle=v.fontColor||c;const M=s.measureText(v.text).width,k=l.textAlign(v.textAlign||(v.textAlign=o.textAlign)),S=p+f+M;let P=g.x,D=g.y;l.setWidth(this.width),x?w>0&&P+S+d>this.right&&(D=g.y+=y,g.line++,P=g.x=ut(n,this.left+d,this.right-i[g.line])):w>0&&D+y>this.bottom&&(P=g.x=P+e[g.line].width+d,g.line++,D=g.y=ut(n,this.top+_+d,this.bottom-e[g.line].height));!function(t,e,i){if(isNaN(p)||p<=0||isNaN(m)||m<0)return;s.save();const n=r(i.lineWidth,1);if(s.fillStyle=r(i.fillStyle,a),s.lineCap=r(i.lineCap,"butt"),s.lineDashOffset=r(i.lineDashOffset,0),s.lineJoin=r(i.lineJoin,"miter"),s.lineWidth=n,s.strokeStyle=r(i.strokeStyle,a),s.setLineDash(r(i.lineDash,[])),o.usePointStyle){const a={radius:m*Math.SQRT2/2,pointStyle:i.pointStyle,rotation:i.rotation,borderWidth:n},r=l.xPlus(t,p/2);ke(s,a,r,e+f,o.pointStyleWidth&&p)}else{const o=e+Math.max((u-m)/2,0),a=l.leftForLtr(t,p),r=gi(i.borderRadius);s.beginPath(),Object.values(r).some((t=>0!==t))?Le(s,{x:a,y:o,w:p,h:m,radius:r}):s.rect(a,o,p,m),s.fill(),0!==n&&s.stroke()}s.restore()}(l.x(P),D,v),P=ft(k,P+p+f,x?P+S:this.right,t.rtl),function(t,e,i){Ae(s,i.text,t,e+b/2,h,{strikethrough:i.hidden,textAlign:l.textAlign(i.textAlign)})}(l.x(P),D,v),x?g.x+=S+d:g.y+=y})),wi(this.ctx,t.textDirection)}drawTitle(){const t=this.options,e=t.title,i=mi(e.font),s=pi(e.padding);if(!e.display)return;const n=yi(t.rtl,this.left,this.width),o=this.ctx,a=e.position,r=i.size/2,l=s.top+r;let h,c=this.left,d=this.width;if(this.isHorizontal())d=Math.max(...this.lineWidths),h=this.top+l,c=ut(t.align,c,this.right-d);else{const e=this.columnSizes.reduce(((t,e)=>Math.max(t,e.height)),0);h=l+ut(t.align,this.top,this.bottom-e-t.labels.padding-this._computeTitleHeight())}const u=ut(a,c,c+d);o.textAlign=n.textAlign(dt(a)),o.textBaseline="middle",o.strokeStyle=e.color,o.fillStyle=e.color,o.font=i.string,Ae(o,e.text,u,h,i)}_computeTitleHeight(){const t=this.options.title,e=mi(t.font),i=pi(t.padding);return t.display?e.lineHeight+i.height:0}_getLegendItemAt(t,e){let i,s,n;if(Q(t,this.left,this.right)&&Q(e,this.top,this.bottom))for(n=this.legendHitBoxes,i=0;i<n.length;++i)if(s=n[i],Q(t,s.left,s.left+s.width)&&Q(e,s.top,s.top+s.height))return this.legendItems[i];return null}handleEvent(t){const e=this.options;if(!function(t,e){if(("mousemove"===t||"mouseout"===t)&&(e.onHover||e.onLeave))return!0;if(e.onClick&&("click"===t||"mouseup"===t))return!0;return!1}(t.type,e))return;const i=this._getLegendItemAt(t.x,t.y);if("mousemove"===t.type||"mouseout"===t.type){const o=this._hoveredItem,a=(n=i,null!==(s=o)&&null!==n&&s.datasetIndex===n.datasetIndex&&s.index===n.index);o&&!a&&c(e.onLeave,[t,o,this],this),this._hoveredItem=i,i&&!a&&c(e.onHover,[t,i,this],this)}else i&&c(e.onClick,[t,i,this],this);var s,n}}var Ro={id:"legend",_element:Eo,start(t,e,i){const s=t.legend=new Eo({ctx:t.ctx,options:i,chart:t});Zi.configure(t,s,i),Zi.addBox(t,s)},stop(t){Zi.removeBox(t,t.legend),delete t.legend},beforeUpdate(t,e,i){const s=t.legend;Zi.configure(t,s,i),s.options=i},afterUpdate(t){const e=t.legend;e.buildLabels(),e.adjustHitBoxes()},afterEvent(t,e){e.replay||t.legend.handleEvent(e.event)},defaults:{display:!0,position:"top",align:"center",fullSize:!0,reverse:!1,weight:1e3,onClick(t,e,i){const s=e.datasetIndex,n=i.chart;n.isDatasetVisible(s)?(n.hide(s),e.hidden=!0):(n.show(s),e.hidden=!1)},onHover:null,onLeave:null,labels:{color:t=>t.chart.options.color,boxWidth:40,padding:10,generateLabels(t){const e=t.data.datasets,{labels:{usePointStyle:i,pointStyle:s,textAlign:n,color:o}}=t.legend.options;return t._getSortedDatasetMetas().map((t=>{const a=t.controller.getStyle(i?0:void 0),r=pi(a.borderWidth);return{text:e[t.index].label,fillStyle:a.backgroundColor,fontColor:o,hidden:!t.visible,lineCap:a.borderCapStyle,lineDash:a.borderDash,lineDashOffset:a.borderDashOffset,lineJoin:a.borderJoinStyle,lineWidth:(r.width+r.height)/4,strokeStyle:a.borderColor,pointStyle:s||a.pointStyle,rotation:a.rotation,textAlign:n||a.textAlign,borderRadius:0,datasetIndex:t.index}}),this)}},title:{color:t=>t.chart.options.color,display:!1,position:"center",text:""}},descriptors:{_scriptable:t=>!t.startsWith("on"),labels:{_scriptable:t=>!["generateLabels","filter","sort"].includes(t)}}};class Io extends Es{constructor(t){super(),this.chart=t.chart,this.options=t.options,this.ctx=t.ctx,this._padding=void 0,this.top=void 0,this.bottom=void 0,this.left=void 0,this.right=void 0,this.width=void 0,this.height=void 0,this.position=void 0,this.weight=void 0,this.fullSize=void 0}update(t,e){const i=this.options;if(this.left=0,this.top=0,!i.display)return void(this.width=this.height=this.right=this.bottom=0);this.width=this.right=t,this.height=this.bottom=e;const n=s(i.text)?i.text.length:1;this._padding=pi(i.padding);const o=n*mi(i.font).lineHeight+this._padding.height;this.isHorizontal()?this.height=o:this.width=o}isHorizontal(){const t=this.options.position;return"top"===t||"bottom"===t}_drawArgs(t){const{top:e,left:i,bottom:s,right:n,options:o}=this,a=o.align;let r,l,h,c=0;return this.isHorizontal()?(l=ut(a,i,n),h=e+t,r=n-i):("left"===o.position?(l=i+t,h=ut(a,s,e),c=-.5*D):(l=n-t,h=ut(a,e,s),c=.5*D),r=s-e),{titleX:l,titleY:h,maxWidth:r,rotation:c}}draw(){const t=this.ctx,e=this.options;if(!e.display)return;const i=mi(e.font),s=i.lineHeight/2+this._padding.top,{titleX:n,titleY:o,maxWidth:a,rotation:r}=this._drawArgs(s);Ae(t,e.text,0,0,i,{color:e.color,maxWidth:a,rotation:r,textAlign:dt(e.align),textBaseline:"middle",translation:[n,o]})}}var zo={id:"title",_element:Io,start(t,e,i){!function(t,e){const i=new Io({ctx:t.ctx,options:e,chart:t});Zi.configure(t,i,e),Zi.addBox(t,i),t.titleBlock=i}(t,i)},stop(t){const e=t.titleBlock;Zi.removeBox(t,e),delete t.titleBlock},beforeUpdate(t,e,i){const s=t.titleBlock;Zi.configure(t,s,i),s.options=i},defaults:{align:"center",display:!1,font:{weight:"bold"},fullSize:!0,padding:10,position:"top",text:"",weight:2e3},defaultRoutes:{color:"color"},descriptors:{_scriptable:!0,_indexable:!1}};const Fo=new WeakMap;var Vo={id:"subtitle",start(t,e,i){const s=new Io({ctx:t.ctx,options:i,chart:t});Zi.configure(t,s,i),Zi.addBox(t,s),Fo.set(t,s)},stop(t){Zi.removeBox(t,Fo.get(t)),Fo.delete(t)},beforeUpdate(t,e,i){const s=Fo.get(t);Zi.configure(t,s,i),s.options=i},defaults:{align:"center",display:!1,font:{weight:"normal"},fullSize:!0,padding:0,position:"top",text:"",weight:1500},defaultRoutes:{color:"color"},descriptors:{_scriptable:!0,_indexable:!1}};const Bo={average(t){if(!t.length)return!1;let e,i,s=0,n=0,o=0;for(e=0,i=t.length;e<i;++e){const i=t[e].element;if(i&&i.hasValue()){const t=i.tooltipPosition();s+=t.x,n+=t.y,++o}}return{x:s/o,y:n/o}},nearest(t,e){if(!t.length)return!1;let i,s,n,o=e.x,a=e.y,r=Number.POSITIVE_INFINITY;for(i=0,s=t.length;i<s;++i){const s=t[i].element;if(s&&s.hasValue()){const t=X(e,s.getCenterPoint());t<r&&(r=t,n=s)}}if(n){const t=n.tooltipPosition();o=t.x,a=t.y}return{x:o,y:a}}};function No(t,e){return e&&(s(e)?Array.prototype.push.apply(t,e):t.push(e)),t}function Wo(t){return("string"==typeof t||t instanceof String)&&t.indexOf("\n")>-1?t.split("\n"):t}function jo(t,e){const{element:i,datasetIndex:s,index:n}=e,o=t.getDatasetMeta(s).controller,{label:a,value:r}=o.getLabelAndValue(n);return{chart:t,label:a,parsed:o.getParsed(n),raw:t.data.datasets[s].data[n],formattedValue:r,dataset:o.getDataset(),dataIndex:n,datasetIndex:s,element:i}}function Ho(t,e){const i=t.chart.ctx,{body:s,footer:n,title:o}=t,{boxWidth:a,boxHeight:r}=e,l=mi(e.bodyFont),h=mi(e.titleFont),c=mi(e.footerFont),u=o.length,f=n.length,g=s.length,p=pi(e.padding);let m=p.height,b=0,x=s.reduce(((t,e)=>t+e.before.length+e.lines.length+e.after.length),0);if(x+=t.beforeBody.length+t.afterBody.length,u&&(m+=u*h.lineHeight+(u-1)*e.titleSpacing+e.titleMarginBottom),x){m+=g*(e.displayColors?Math.max(r,l.lineHeight):l.lineHeight)+(x-g)*l.lineHeight+(x-1)*e.bodySpacing}f&&(m+=e.footerMarginTop+f*c.lineHeight+(f-1)*e.footerSpacing);let _=0;const y=function(t){b=Math.max(b,i.measureText(t).width+_)};return i.save(),i.font=h.string,d(t.title,y),i.font=l.string,d(t.beforeBody.concat(t.afterBody),y),_=e.displayColors?a+2+e.boxPadding:0,d(s,(t=>{d(t.before,y),d(t.lines,y),d(t.after,y)})),_=0,i.font=c.string,d(t.footer,y),i.restore(),b+=p.width,{width:b,height:m}}function $o(t,e,i,s){const{x:n,width:o}=i,{width:a,chartArea:{left:r,right:l}}=t;let h="center";return"center"===s?h=n<=(r+l)/2?"left":"right":n<=o/2?h="left":n>=a-o/2&&(h="right"),function(t,e,i,s){const{x:n,width:o}=s,a=i.caretSize+i.caretPadding;return"left"===t&&n+o+a>e.width||"right"===t&&n-o-a<0||void 0}(h,t,e,i)&&(h="center"),h}function Yo(t,e,i){const s=i.yAlign||e.yAlign||function(t,e){const{y:i,height:s}=e;return i<s/2?"top":i>t.height-s/2?"bottom":"center"}(t,i);return{xAlign:i.xAlign||e.xAlign||$o(t,e,i,s),yAlign:s}}function Uo(t,e,i,s){const{caretSize:n,caretPadding:o,cornerRadius:a}=t,{xAlign:r,yAlign:l}=i,h=n+o,{topLeft:c,topRight:d,bottomLeft:u,bottomRight:f}=gi(a);let g=function(t,e){let{x:i,width:s}=t;return"right"===e?i-=s:"center"===e&&(i-=s/2),i}(e,r);const p=function(t,e,i){let{y:s,height:n}=t;return"top"===e?s+=i:s-="bottom"===e?n+i:n/2,s}(e,l,h);return"center"===l?"left"===r?g+=h:"right"===r&&(g-=h):"left"===r?g-=Math.max(c,u)+n:"right"===r&&(g+=Math.max(d,f)+n),{x:Z(g,0,s.width-e.width),y:Z(p,0,s.height-e.height)}}function Xo(t,e,i){const s=pi(i.padding);return"center"===e?t.x+t.width/2:"right"===e?t.x+t.width-s.right:t.x+s.left}function qo(t){return No([],Wo(t))}function Ko(t,e){const i=e&&e.dataset&&e.dataset.tooltip&&e.dataset.tooltip.callbacks;return i?t.override(i):t}class Go extends Es{constructor(t){super(),this.opacity=0,this._active=[],this._eventPosition=void 0,this._size=void 0,this._cachedAnimations=void 0,this._tooltipItems=[],this.$animations=void 0,this.$context=void 0,this.chart=t.chart||t._chart,this._chart=this.chart,this.options=t.options,this.dataPoints=void 0,this.title=void 0,this.beforeBody=void 0,this.body=void 0,this.afterBody=void 0,this.footer=void 0,this.xAlign=void 0,this.yAlign=void 0,this.x=void 0,this.y=void 0,this.height=void 0,this.width=void 0,this.caretX=void 0,this.caretY=void 0,this.labelColors=void 0,this.labelPointStyles=void 0,this.labelTextColors=void 0}initialize(t){this.options=t,this._cachedAnimations=void 0,this.$context=void 0}_resolveAnimations(){const t=this._cachedAnimations;if(t)return t;const e=this.chart,i=this.options.setContext(this.getContext()),s=i.enabled&&e.options.animation&&i.animations,n=new ys(this.chart,s);return s._cacheable&&(this._cachedAnimations=Object.freeze(n)),n}getContext(){return this.$context||(this.$context=(t=this.chart.getContext(),e=this,i=this._tooltipItems,_i(t,{tooltip:e,tooltipItems:i,type:"tooltip"})));var t,e,i}getTitle(t,e){const{callbacks:i}=e,s=i.beforeTitle.apply(this,[t]),n=i.title.apply(this,[t]),o=i.afterTitle.apply(this,[t]);let a=[];return a=No(a,Wo(s)),a=No(a,Wo(n)),a=No(a,Wo(o)),a}getBeforeBody(t,e){return qo(e.callbacks.beforeBody.apply(this,[t]))}getBody(t,e){const{callbacks:i}=e,s=[];return d(t,(t=>{const e={before:[],lines:[],after:[]},n=Ko(i,t);No(e.before,Wo(n.beforeLabel.call(this,t))),No(e.lines,n.label.call(this,t)),No(e.after,Wo(n.afterLabel.call(this,t))),s.push(e)})),s}getAfterBody(t,e){return qo(e.callbacks.afterBody.apply(this,[t]))}getFooter(t,e){const{callbacks:i}=e,s=i.beforeFooter.apply(this,[t]),n=i.footer.apply(this,[t]),o=i.afterFooter.apply(this,[t]);let a=[];return a=No(a,Wo(s)),a=No(a,Wo(n)),a=No(a,Wo(o)),a}_createItems(t){const e=this._active,i=this.chart.data,s=[],n=[],o=[];let a,r,l=[];for(a=0,r=e.length;a<r;++a)l.push(jo(this.chart,e[a]));return t.filter&&(l=l.filter(((e,s,n)=>t.filter(e,s,n,i)))),t.itemSort&&(l=l.sort(((e,s)=>t.itemSort(e,s,i)))),d(l,(e=>{const i=Ko(t.callbacks,e);s.push(i.labelColor.call(this,e)),n.push(i.labelPointStyle.call(this,e)),o.push(i.labelTextColor.call(this,e))})),this.labelColors=s,this.labelPointStyles=n,this.labelTextColors=o,this.dataPoints=l,l}update(t,e){const i=this.options.setContext(this.getContext()),s=this._active;let n,o=[];if(s.length){const t=Bo[i.position].call(this,s,this._eventPosition);o=this._createItems(i),this.title=this.getTitle(o,i),this.beforeBody=this.getBeforeBody(o,i),this.body=this.getBody(o,i),this.afterBody=this.getAfterBody(o,i),this.footer=this.getFooter(o,i);const e=this._size=Ho(this,i),a=Object.assign({},t,e),r=Yo(this.chart,i,a),l=Uo(i,a,r,this.chart);this.xAlign=r.xAlign,this.yAlign=r.yAlign,n={opacity:1,x:l.x,y:l.y,width:e.width,height:e.height,caretX:t.x,caretY:t.y}}else 0!==this.opacity&&(n={opacity:0});this._tooltipItems=o,this.$context=void 0,n&&this._resolveAnimations().update(this,n),t&&i.external&&i.external.call(this,{chart:this.chart,tooltip:this,replay:e})}drawCaret(t,e,i,s){const n=this.getCaretPosition(t,i,s);e.lineTo(n.x1,n.y1),e.lineTo(n.x2,n.y2),e.lineTo(n.x3,n.y3)}getCaretPosition(t,e,i){const{xAlign:s,yAlign:n}=this,{caretSize:o,cornerRadius:a}=i,{topLeft:r,topRight:l,bottomLeft:h,bottomRight:c}=gi(a),{x:d,y:u}=t,{width:f,height:g}=e;let p,m,b,x,_,y;return"center"===n?(_=u+g/2,"left"===s?(p=d,m=p-o,x=_+o,y=_-o):(p=d+f,m=p+o,x=_-o,y=_+o),b=p):(m="left"===s?d+Math.max(r,h)+o:"right"===s?d+f-Math.max(l,c)-o:this.caretX,"top"===n?(x=u,_=x-o,p=m-o,b=m+o):(x=u+g,_=x+o,p=m+o,b=m-o),y=x),{x1:p,x2:m,x3:b,y1:x,y2:_,y3:y}}drawTitle(t,e,i){const s=this.title,n=s.length;let o,a,r;if(n){const l=yi(i.rtl,this.x,this.width);for(t.x=Xo(this,i.titleAlign,i),e.textAlign=l.textAlign(i.titleAlign),e.textBaseline="middle",o=mi(i.titleFont),a=i.titleSpacing,e.fillStyle=i.titleColor,e.font=o.string,r=0;r<n;++r)e.fillText(s[r],l.x(t.x),t.y+o.lineHeight/2),t.y+=o.lineHeight+a,r+1===n&&(t.y+=i.titleMarginBottom-a)}}_drawColorBox(t,e,i,s,o){const a=this.labelColors[i],r=this.labelPointStyles[i],{boxHeight:l,boxWidth:h,boxPadding:c}=o,d=mi(o.bodyFont),u=Xo(this,"left",o),f=s.x(u),g=l<d.lineHeight?(d.lineHeight-l)/2:0,p=e.y+g;if(o.usePointStyle){const e={radius:Math.min(h,l)/2,pointStyle:r.pointStyle,rotation:r.rotation,borderWidth:1},i=s.leftForLtr(f,h)+h/2,n=p+l/2;t.strokeStyle=o.multiKeyBackground,t.fillStyle=o.multiKeyBackground,Me(t,e,i,n),t.strokeStyle=a.borderColor,t.fillStyle=a.backgroundColor,Me(t,e,i,n)}else{t.lineWidth=n(a.borderWidth)?Math.max(...Object.values(a.borderWidth)):a.borderWidth||1,t.strokeStyle=a.borderColor,t.setLineDash(a.borderDash||[]),t.lineDashOffset=a.borderDashOffset||0;const e=s.leftForLtr(f,h-c),i=s.leftForLtr(s.xPlus(f,1),h-c-2),r=gi(a.borderRadius);Object.values(r).some((t=>0!==t))?(t.beginPath(),t.fillStyle=o.multiKeyBackground,Le(t,{x:e,y:p,w:h,h:l,radius:r}),t.fill(),t.stroke(),t.fillStyle=a.backgroundColor,t.beginPath(),Le(t,{x:i,y:p+1,w:h-2,h:l-2,radius:r}),t.fill()):(t.fillStyle=o.multiKeyBackground,t.fillRect(e,p,h,l),t.strokeRect(e,p,h,l),t.fillStyle=a.backgroundColor,t.fillRect(i,p+1,h-2,l-2))}t.fillStyle=this.labelTextColors[i]}drawBody(t,e,i){const{body:s}=this,{bodySpacing:n,bodyAlign:o,displayColors:a,boxHeight:r,boxWidth:l,boxPadding:h}=i,c=mi(i.bodyFont);let u=c.lineHeight,f=0;const g=yi(i.rtl,this.x,this.width),p=function(i){e.fillText(i,g.x(t.x+f),t.y+u/2),t.y+=u+n},m=g.textAlign(o);let b,x,_,y,v,w,M;for(e.textAlign=o,e.textBaseline="middle",e.font=c.string,t.x=Xo(this,m,i),e.fillStyle=i.bodyColor,d(this.beforeBody,p),f=a&&"right"!==m?"center"===o?l/2+h:l+2+h:0,y=0,w=s.length;y<w;++y){for(b=s[y],x=this.labelTextColors[y],e.fillStyle=x,d(b.before,p),_=b.lines,a&&_.length&&(this._drawColorBox(e,t,y,g,i),u=Math.max(c.lineHeight,r)),v=0,M=_.length;v<M;++v)p(_[v]),u=c.lineHeight;d(b.after,p)}f=0,u=c.lineHeight,d(this.afterBody,p),t.y-=n}drawFooter(t,e,i){const s=this.footer,n=s.length;let o,a;if(n){const r=yi(i.rtl,this.x,this.width);for(t.x=Xo(this,i.footerAlign,i),t.y+=i.footerMarginTop,e.textAlign=r.textAlign(i.footerAlign),e.textBaseline="middle",o=mi(i.footerFont),e.fillStyle=i.footerColor,e.font=o.string,a=0;a<n;++a)e.fillText(s[a],r.x(t.x),t.y+o.lineHeight/2),t.y+=o.lineHeight+i.footerSpacing}}drawBackground(t,e,i,s){const{xAlign:n,yAlign:o}=this,{x:a,y:r}=t,{width:l,height:h}=i,{topLeft:c,topRight:d,bottomLeft:u,bottomRight:f}=gi(s.cornerRadius);e.fillStyle=s.backgroundColor,e.strokeStyle=s.borderColor,e.lineWidth=s.borderWidth,e.beginPath(),e.moveTo(a+c,r),"top"===o&&this.drawCaret(t,e,i,s),e.lineTo(a+l-d,r),e.quadraticCurveTo(a+l,r,a+l,r+d),"center"===o&&"right"===n&&this.drawCaret(t,e,i,s),e.lineTo(a+l,r+h-f),e.quadraticCurveTo(a+l,r+h,a+l-f,r+h),"bottom"===o&&this.drawCaret(t,e,i,s),e.lineTo(a+u,r+h),e.quadraticCurveTo(a,r+h,a,r+h-u),"center"===o&&"left"===n&&this.drawCaret(t,e,i,s),e.lineTo(a,r+c),e.quadraticCurveTo(a,r,a+c,r),e.closePath(),e.fill(),s.borderWidth>0&&e.stroke()}_updateAnimationTarget(t){const e=this.chart,i=this.$animations,s=i&&i.x,n=i&&i.y;if(s||n){const i=Bo[t.position].call(this,this._active,this._eventPosition);if(!i)return;const o=this._size=Ho(this,t),a=Object.assign({},i,this._size),r=Yo(e,t,a),l=Uo(t,a,r,e);s._to===l.x&&n._to===l.y||(this.xAlign=r.xAlign,this.yAlign=r.yAlign,this.width=o.width,this.height=o.height,this.caretX=i.x,this.caretY=i.y,this._resolveAnimations().update(this,l))}}_willRender(){return!!this.opacity}draw(t){const e=this.options.setContext(this.getContext());let i=this.opacity;if(!i)return;this._updateAnimationTarget(e);const s={width:this.width,height:this.height},n={x:this.x,y:this.y};i=Math.abs(i)<.001?0:i;const o=pi(e.padding),a=this.title.length||this.beforeBody.length||this.body.length||this.afterBody.length||this.footer.length;e.enabled&&a&&(t.save(),t.globalAlpha=i,this.drawBackground(n,t,s,e),vi(t,e.textDirection),n.y+=o.top,this.drawTitle(n,t,e),this.drawBody(n,t,e),this.drawFooter(n,t,e),wi(t,e.textDirection),t.restore())}getActiveElements(){return this._active||[]}setActiveElements(t,e){const i=this._active,s=t.map((({datasetIndex:t,index:e})=>{const i=this.chart.getDatasetMeta(t);if(!i)throw new Error("Cannot find a dataset at index "+t);return{datasetIndex:t,element:i.data[e],index:e}})),n=!u(i,s),o=this._positionChanged(s,e);(n||o)&&(this._active=s,this._eventPosition=e,this._ignoreReplayEvents=!0,this.update(!0))}handleEvent(t,e,i=!0){if(e&&this._ignoreReplayEvents)return!1;this._ignoreReplayEvents=!1;const s=this.options,n=this._active||[],o=this._getActiveElements(t,n,e,i),a=this._positionChanged(o,t),r=e||!u(o,n)||a;return r&&(this._active=o,(s.enabled||s.external)&&(this._eventPosition={x:t.x,y:t.y},this.update(!0,e))),r}_getActiveElements(t,e,i,s){const n=this.options;if("mouseout"===t.type)return[];if(!s)return e;const o=this.chart.getElementsAtEventForMode(t,n.mode,n,i);return n.reverse&&o.reverse(),o}_positionChanged(t,e){const{caretX:i,caretY:s,options:n}=this,o=Bo[n.position].call(this,t,e);return!1!==o&&(i!==o.x||s!==o.y)}}Go.positioners=Bo;var Zo={id:"tooltip",_element:Go,positioners:Bo,afterInit(t,e,i){i&&(t.tooltip=new Go({chart:t,options:i}))},beforeUpdate(t,e,i){t.tooltip&&t.tooltip.initialize(i)},reset(t,e,i){t.tooltip&&t.tooltip.initialize(i)},afterDraw(t){const e=t.tooltip;if(e&&e._willRender()){const i={tooltip:e};if(!1===t.notifyPlugins("beforeTooltipDraw",i))return;e.draw(t.ctx),t.notifyPlugins("afterTooltipDraw",i)}},afterEvent(t,e){if(t.tooltip){const i=e.replay;t.tooltip.handleEvent(e.event,i,e.inChartArea)&&(e.changed=!0)}},defaults:{enabled:!0,external:null,position:"average",backgroundColor:"rgba(0,0,0,0.8)",titleColor:"#fff",titleFont:{weight:"bold"},titleSpacing:2,titleMarginBottom:6,titleAlign:"left",bodyColor:"#fff",bodySpacing:2,bodyFont:{},bodyAlign:"left",footerColor:"#fff",footerSpacing:2,footerMarginTop:6,footerFont:{weight:"bold"},footerAlign:"left",padding:6,caretPadding:2,caretSize:5,cornerRadius:6,boxHeight:(t,e)=>e.bodyFont.size,boxWidth:(t,e)=>e.bodyFont.size,multiKeyBackground:"#fff",displayColors:!0,boxPadding:0,borderColor:"rgba(0,0,0,0)",borderWidth:0,animation:{duration:400,easing:"easeOutQuart"},animations:{numbers:{type:"number",properties:["x","y","width","height","caretX","caretY"]},opacity:{easing:"linear",duration:200}},callbacks:{beforeTitle:t,title(t){if(t.length>0){const e=t[0],i=e.chart.data.labels,s=i?i.length:0;if(this&&this.options&&"dataset"===this.options.mode)return e.dataset.label||"";if(e.label)return e.label;if(s>0&&e.dataIndex<s)return i[e.dataIndex]}return""},afterTitle:t,beforeBody:t,beforeLabel:t,label(t){if(this&&this.options&&"dataset"===this.options.mode)return t.label+": "+t.formattedValue||t.formattedValue;let e=t.dataset.label||"";e&&(e+=": ");const s=t.formattedValue;return i(s)||(e+=s),e},labelColor(t){const e=t.chart.getDatasetMeta(t.datasetIndex).controller.getStyle(t.dataIndex);return{borderColor:e.borderColor,backgroundColor:e.backgroundColor,borderWidth:e.borderWidth,borderDash:e.borderDash,borderDashOffset:e.borderDashOffset,borderRadius:0}},labelTextColor(){return this.options.bodyColor},labelPointStyle(t){const e=t.chart.getDatasetMeta(t.datasetIndex).controller.getStyle(t.dataIndex);return{pointStyle:e.pointStyle,rotation:e.rotation}},afterLabel:t,afterBody:t,beforeFooter:t,footer:t,afterFooter:t}},defaultRoutes:{bodyFont:"font",footerFont:"font",titleFont:"font"},descriptors:{_scriptable:t=>"filter"!==t&&"itemSort"!==t&&"external"!==t,_indexable:!1,callbacks:{_scriptable:!1,_indexable:!1},animation:{_fallback:!1},animations:{_fallback:"animation"}},additionalOptionScopes:["interaction"]},Jo=Object.freeze({__proto__:null,Decimation:go,Filler:To,Legend:Ro,SubTitle:Vo,Title:zo,Tooltip:Zo});function Qo(t,e,i,s){const n=t.indexOf(e);if(-1===n)return((t,e,i,s)=>("string"==typeof e?(i=t.push(e)-1,s.unshift({index:i,label:e})):isNaN(e)&&(i=null),i))(t,e,i,s);return n!==t.lastIndexOf(e)?i:n}class ta extends $s{constructor(t){super(t),this._startValue=void 0,this._valueRange=0,this._addedLabels=[]}init(t){const e=this._addedLabels;if(e.length){const t=this.getLabels();for(const{index:i,label:s}of e)t[i]===s&&t.splice(i,1);this._addedLabels=[]}super.init(t)}parse(t,e){if(i(t))return null;const s=this.getLabels();return((t,e)=>null===t?null:Z(Math.round(t),0,e))(e=isFinite(e)&&s[e]===t?e:Qo(s,t,r(e,t),this._addedLabels),s.length-1)}determineDataLimits(){const{minDefined:t,maxDefined:e}=this.getUserBounds();let{min:i,max:s}=this.getMinMax(!0);"ticks"===this.options.bounds&&(t||(i=0),e||(s=this.getLabels().length-1)),this.min=i,this.max=s}buildTicks(){const t=this.min,e=this.max,i=this.options.offset,s=[];let n=this.getLabels();n=0===t&&e===n.length-1?n:n.slice(t,e+1),this._valueRange=Math.max(n.length-(i?0:1),1),this._startValue=this.min-(i?.5:0);for(let i=t;i<=e;i++)s.push({value:i});return s}getLabelForValue(t){const e=this.getLabels();return t>=0&&t<e.length?e[t]:t}configure(){super.configure(),this.isHorizontal()||(this._reversePixels=!this._reversePixels)}getPixelForValue(t){return"number"!=typeof t&&(t=this.parse(t)),null===t?NaN:this.getPixelForDecimal((t-this._startValue)/this._valueRange)}getPixelForTick(t){const e=this.ticks;return t<0||t>e.length-1?null:this.getPixelForValue(e[t].value)}getValueForPixel(t){return Math.round(this._startValue+this.getDecimalForPixel(t)*this._valueRange)}getBasePixel(){return this.bottom}}function ea(t,e,{horizontal:i,minRotation:s}){const n=H(s),o=(i?Math.sin(n):Math.cos(n))||.001,a=.75*e*(""+t).length;return Math.min(e/o,a)}ta.id="category",ta.defaults={ticks:{callback:ta.prototype.getLabelForValue}};class ia extends $s{constructor(t){super(t),this.start=void 0,this.end=void 0,this._startValue=void 0,this._endValue=void 0,this._valueRange=0}parse(t,e){return i(t)||("number"==typeof t||t instanceof Number)&&!isFinite(+t)?null:+t}handleTickRangeOptions(){const{beginAtZero:t}=this.options,{minDefined:e,maxDefined:i}=this.getUserBounds();let{min:s,max:n}=this;const o=t=>s=e?s:t,a=t=>n=i?n:t;if(t){const t=z(s),e=z(n);t<0&&e<0?a(0):t>0&&e>0&&o(0)}if(s===n){let e=1;(n>=Number.MAX_SAFE_INTEGER||s<=Number.MIN_SAFE_INTEGER)&&(e=Math.abs(.05*n)),a(n+e),t||o(s-e)}this.min=s,this.max=n}getTickLimit(){const t=this.options.ticks;let e,{maxTicksLimit:i,stepSize:s}=t;return s?(e=Math.ceil(this.max/s)-Math.floor(this.min/s)+1,e>1e3&&(console.warn(`scales.${this.id}.ticks.stepSize: ${s} would result generating up to ${e} ticks. Limiting to 1000.`),e=1e3)):(e=this.computeTickLimit(),i=i||11),i&&(e=Math.min(i,e)),e}computeTickLimit(){return Number.POSITIVE_INFINITY}buildTicks(){const t=this.options,e=t.ticks;let s=this.getTickLimit();s=Math.max(2,s);const n=function(t,e){const s=[],{bounds:n,step:o,min:a,max:r,precision:l,count:h,maxTicks:c,maxDigits:d,includeBounds:u}=t,f=o||1,g=c-1,{min:p,max:m}=e,b=!i(a),x=!i(r),_=!i(h),y=(m-p)/(d+1);let v,w,M,k,S=F((m-p)/g/f)*f;if(S<1e-14&&!b&&!x)return[{value:p},{value:m}];k=Math.ceil(m/S)-Math.floor(p/S),k>g&&(S=F(k*S/g/f)*f),i(l)||(v=Math.pow(10,l),S=Math.ceil(S*v)/v),"ticks"===n?(w=Math.floor(p/S)*S,M=Math.ceil(m/S)*S):(w=p,M=m),b&&x&&o&&W((r-a)/o,S/1e3)?(k=Math.round(Math.min((r-a)/S,c)),S=(r-a)/k,w=a,M=r):_?(w=b?a:w,M=x?r:M,k=h-1,S=(M-w)/k):(k=(M-w)/S,k=N(k,Math.round(k),S/1e3)?Math.round(k):Math.ceil(k));const P=Math.max(Y(S),Y(w));v=Math.pow(10,i(l)?P:l),w=Math.round(w*v)/v,M=Math.round(M*v)/v;let D=0;for(b&&(u&&w!==a?(s.push({value:a}),w<a&&D++,N(Math.round((w+D*S)*v)/v,a,ea(a,y,t))&&D++):w<a&&D++);D<k;++D)s.push({value:Math.round((w+D*S)*v)/v});return x&&u&&M!==r?s.length&&N(s[s.length-1].value,r,ea(r,y,t))?s[s.length-1].value=r:s.push({value:r}):x&&M!==r||s.push({value:M}),s}({maxTicks:s,bounds:t.bounds,min:t.min,max:t.max,precision:e.precision,step:e.stepSize,count:e.count,maxDigits:this._maxDigits(),horizontal:this.isHorizontal(),minRotation:e.minRotation||0,includeBounds:!1!==e.includeBounds},this._range||this);return"ticks"===t.bounds&&j(n,this,"value"),t.reverse?(n.reverse(),this.start=this.max,this.end=this.min):(this.start=this.min,this.end=this.max),n}configure(){const t=this.ticks;let e=this.min,i=this.max;if(super.configure(),this.options.offset&&t.length){const s=(i-e)/Math.max(t.length-1,1)/2;e-=s,i+=s}this._startValue=e,this._endValue=i,this._valueRange=i-e}getLabelForValue(t){return li(t,this.chart.options.locale,this.options.ticks.format)}}class sa extends ia{determineDataLimits(){const{min:t,max:e}=this.getMinMax(!0);this.min=o(t)?t:0,this.max=o(e)?e:1,this.handleTickRangeOptions()}computeTickLimit(){const t=this.isHorizontal(),e=t?this.width:this.height,i=H(this.options.ticks.minRotation),s=(t?Math.sin(i):Math.cos(i))||.001,n=this._resolveTickFontOptions(0);return Math.ceil(e/Math.min(40,n.lineHeight/s))}getPixelForValue(t){return null===t?NaN:this.getPixelForDecimal((t-this._startValue)/this._valueRange)}getValueForPixel(t){return this._startValue+this.getDecimalForPixel(t)*this._valueRange}}function na(t){return 1===t/Math.pow(10,Math.floor(I(t)))}sa.id="linear",sa.defaults={ticks:{callback:Is.formatters.numeric}};class oa extends $s{constructor(t){super(t),this.start=void 0,this.end=void 0,this._startValue=void 0,this._valueRange=0}parse(t,e){const i=ia.prototype.parse.apply(this,[t,e]);if(0!==i)return o(i)&&i>0?i:null;this._zero=!0}determineDataLimits(){const{min:t,max:e}=this.getMinMax(!0);this.min=o(t)?Math.max(0,t):null,this.max=o(e)?Math.max(0,e):null,this.options.beginAtZero&&(this._zero=!0),this.handleTickRangeOptions()}handleTickRangeOptions(){const{minDefined:t,maxDefined:e}=this.getUserBounds();let i=this.min,s=this.max;const n=e=>i=t?i:e,o=t=>s=e?s:t,a=(t,e)=>Math.pow(10,Math.floor(I(t))+e);i===s&&(i<=0?(n(1),o(10)):(n(a(i,-1)),o(a(s,1)))),i<=0&&n(a(s,-1)),s<=0&&o(a(i,1)),this._zero&&this.min!==this._suggestedMin&&i===a(this.min,0)&&n(a(i,-1)),this.min=i,this.max=s}buildTicks(){const t=this.options,e=function(t,e){const i=Math.floor(I(e.max)),s=Math.ceil(e.max/Math.pow(10,i)),n=[];let o=a(t.min,Math.pow(10,Math.floor(I(e.min)))),r=Math.floor(I(o)),l=Math.floor(o/Math.pow(10,r)),h=r<0?Math.pow(10,Math.abs(r)):1;do{n.push({value:o,major:na(o)}),++l,10===l&&(l=1,++r,h=r>=0?1:h),o=Math.round(l*Math.pow(10,r)*h)/h}while(r<i||r===i&&l<s);const c=a(t.max,o);return n.push({value:c,major:na(o)}),n}({min:this._userMin,max:this._userMax},this);return"ticks"===t.bounds&&j(e,this,"value"),t.reverse?(e.reverse(),this.start=this.max,this.end=this.min):(this.start=this.min,this.end=this.max),e}getLabelForValue(t){return void 0===t?"0":li(t,this.chart.options.locale,this.options.ticks.format)}configure(){const t=this.min;super.configure(),this._startValue=I(t),this._valueRange=I(this.max)-I(t)}getPixelForValue(t){return void 0!==t&&0!==t||(t=this.min),null===t||isNaN(t)?NaN:this.getPixelForDecimal(t===this.min?0:(I(t)-this._startValue)/this._valueRange)}getValueForPixel(t){const e=this.getDecimalForPixel(t);return Math.pow(10,this._startValue+e*this._valueRange)}}function aa(t){const e=t.ticks;if(e.display&&t.display){const t=pi(e.backdropPadding);return r(e.font&&e.font.size,ne.font.size)+t.height}return 0}function ra(t,e,i,s,n){return t===s||t===n?{start:e-i/2,end:e+i/2}:t<s||t>n?{start:e-i,end:e}:{start:e,end:e+i}}function la(t){const e={l:t.left+t._padding.left,r:t.right-t._padding.right,t:t.top+t._padding.top,b:t.bottom-t._padding.bottom},i=Object.assign({},e),n=[],o=[],a=t._pointLabels.length,r=t.options.pointLabels,l=r.centerPointLabels?D/a:0;for(let u=0;u<a;u++){const a=r.setContext(t.getPointLabelContext(u));o[u]=a.padding;const f=t.getPointPosition(u,t.drawingArea+o[u],l),g=mi(a.font),p=(h=t.ctx,c=g,d=s(d=t._pointLabels[u])?d:[d],{w:ye(h,c.string,d),h:d.length*c.lineHeight});n[u]=p;const m=K(t.getIndexAngle(u)+l),b=Math.round($(m));ha(i,e,m,ra(b,f.x,p.w,0,180),ra(b,f.y,p.h,90,270))}var h,c,d;t.setCenterPoint(e.l-i.l,i.r-e.r,e.t-i.t,i.b-e.b),t._pointLabelItems=function(t,e,i){const s=[],n=t._pointLabels.length,o=t.options,a=aa(o)/2,r=t.drawingArea,l=o.pointLabels.centerPointLabels?D/n:0;for(let o=0;o<n;o++){const n=t.getPointPosition(o,r+a+i[o],l),h=Math.round($(K(n.angle+L))),c=e[o],d=ua(n.y,c.h,h),u=ca(h),f=da(n.x,c.w,u);s.push({x:n.x,y:d,textAlign:u,left:f,top:d,right:f+c.w,bottom:d+c.h})}return s}(t,n,o)}function ha(t,e,i,s,n){const o=Math.abs(Math.sin(i)),a=Math.abs(Math.cos(i));let r=0,l=0;s.start<e.l?(r=(e.l-s.start)/o,t.l=Math.min(t.l,e.l-r)):s.end>e.r&&(r=(s.end-e.r)/o,t.r=Math.max(t.r,e.r+r)),n.start<e.t?(l=(e.t-n.start)/a,t.t=Math.min(t.t,e.t-l)):n.end>e.b&&(l=(n.end-e.b)/a,t.b=Math.max(t.b,e.b+l))}function ca(t){return 0===t||180===t?"center":t<180?"left":"right"}function da(t,e,i){return"right"===i?t-=e:"center"===i&&(t-=e/2),t}function ua(t,e,i){return 90===i||270===i?t-=e/2:(i>270||i<90)&&(t-=e),t}function fa(t,e,i,s){const{ctx:n}=t;if(i)n.arc(t.xCenter,t.yCenter,e,0,O);else{let i=t.getPointPosition(0,e);n.moveTo(i.x,i.y);for(let o=1;o<s;o++)i=t.getPointPosition(o,e),n.lineTo(i.x,i.y)}}oa.id="logarithmic",oa.defaults={ticks:{callback:Is.formatters.logarithmic,major:{enabled:!0}}};class ga extends ia{constructor(t){super(t),this.xCenter=void 0,this.yCenter=void 0,this.drawingArea=void 0,this._pointLabels=[],this._pointLabelItems=[]}setDimensions(){const t=this._padding=pi(aa(this.options)/2),e=this.width=this.maxWidth-t.width,i=this.height=this.maxHeight-t.height;this.xCenter=Math.floor(this.left+e/2+t.left),this.yCenter=Math.floor(this.top+i/2+t.top),this.drawingArea=Math.floor(Math.min(e,i)/2)}determineDataLimits(){const{min:t,max:e}=this.getMinMax(!1);this.min=o(t)&&!isNaN(t)?t:0,this.max=o(e)&&!isNaN(e)?e:0,this.handleTickRangeOptions()}computeTickLimit(){return Math.ceil(this.drawingArea/aa(this.options))}generateTickLabels(t){ia.prototype.generateTickLabels.call(this,t),this._pointLabels=this.getLabels().map(((t,e)=>{const i=c(this.options.pointLabels.callback,[t,e],this);return i||0===i?i:""})).filter(((t,e)=>this.chart.getDataVisibility(e)))}fit(){const t=this.options;t.display&&t.pointLabels.display?la(this):this.setCenterPoint(0,0,0,0)}setCenterPoint(t,e,i,s){this.xCenter+=Math.floor((t-e)/2),this.yCenter+=Math.floor((i-s)/2),this.drawingArea-=Math.min(this.drawingArea/2,Math.max(t,e,i,s))}getIndexAngle(t){return K(t*(O/(this._pointLabels.length||1))+H(this.options.startAngle||0))}getDistanceFromCenterForValue(t){if(i(t))return NaN;const e=this.drawingArea/(this.max-this.min);return this.options.reverse?(this.max-t)*e:(t-this.min)*e}getValueForDistanceFromCenter(t){if(i(t))return NaN;const e=t/(this.drawingArea/(this.max-this.min));return this.options.reverse?this.max-e:this.min+e}getPointLabelContext(t){const e=this._pointLabels||[];if(t>=0&&t<e.length){const i=e[t];return function(t,e,i){return _i(t,{label:i,index:e,type:"pointLabel"})}(this.getContext(),t,i)}}getPointPosition(t,e,i=0){const s=this.getIndexAngle(t)-L+i;return{x:Math.cos(s)*e+this.xCenter,y:Math.sin(s)*e+this.yCenter,angle:s}}getPointPositionForValue(t,e){return this.getPointPosition(t,this.getDistanceFromCenterForValue(e))}getBasePosition(t){return this.getPointPositionForValue(t||0,this.getBaseValue())}getPointLabelPosition(t){const{left:e,top:i,right:s,bottom:n}=this._pointLabelItems[t];return{left:e,top:i,right:s,bottom:n}}drawBackground(){const{backgroundColor:t,grid:{circular:e}}=this.options;if(t){const i=this.ctx;i.save(),i.beginPath(),fa(this,this.getDistanceFromCenterForValue(this._endValue),e,this._pointLabels.length),i.closePath(),i.fillStyle=t,i.fill(),i.restore()}}drawGrid(){const t=this.ctx,e=this.options,{angleLines:s,grid:n}=e,o=this._pointLabels.length;let a,r,l;if(e.pointLabels.display&&function(t,e){const{ctx:s,options:{pointLabels:n}}=t;for(let o=e-1;o>=0;o--){const e=n.setContext(t.getPointLabelContext(o)),a=mi(e.font),{x:r,y:l,textAlign:h,left:c,top:d,right:u,bottom:f}=t._pointLabelItems[o],{backdropColor:g}=e;if(!i(g)){const t=gi(e.borderRadius),i=pi(e.backdropPadding);s.fillStyle=g;const n=c-i.left,o=d-i.top,a=u-c+i.width,r=f-d+i.height;Object.values(t).some((t=>0!==t))?(s.beginPath(),Le(s,{x:n,y:o,w:a,h:r,radius:t}),s.fill()):s.fillRect(n,o,a,r)}Ae(s,t._pointLabels[o],r,l+a.lineHeight/2,a,{color:e.color,textAlign:h,textBaseline:"middle"})}}(this,o),n.display&&this.ticks.forEach(((t,e)=>{if(0!==e){r=this.getDistanceFromCenterForValue(t.value);!function(t,e,i,s){const n=t.ctx,o=e.circular,{color:a,lineWidth:r}=e;!o&&!s||!a||!r||i<0||(n.save(),n.strokeStyle=a,n.lineWidth=r,n.setLineDash(e.borderDash),n.lineDashOffset=e.borderDashOffset,n.beginPath(),fa(t,i,o,s),n.closePath(),n.stroke(),n.restore())}(this,n.setContext(this.getContext(e-1)),r,o)}})),s.display){for(t.save(),a=o-1;a>=0;a--){const i=s.setContext(this.getPointLabelContext(a)),{color:n,lineWidth:o}=i;o&&n&&(t.lineWidth=o,t.strokeStyle=n,t.setLineDash(i.borderDash),t.lineDashOffset=i.borderDashOffset,r=this.getDistanceFromCenterForValue(e.ticks.reverse?this.min:this.max),l=this.getPointPosition(a,r),t.beginPath(),t.moveTo(this.xCenter,this.yCenter),t.lineTo(l.x,l.y),t.stroke())}t.restore()}}drawBorder(){}drawLabels(){const t=this.ctx,e=this.options,i=e.ticks;if(!i.display)return;const s=this.getIndexAngle(0);let n,o;t.save(),t.translate(this.xCenter,this.yCenter),t.rotate(s),t.textAlign="center",t.textBaseline="middle",this.ticks.forEach(((s,a)=>{if(0===a&&!e.reverse)return;const r=i.setContext(this.getContext(a)),l=mi(r.font);if(n=this.getDistanceFromCenterForValue(this.ticks[a].value),r.showLabelBackdrop){t.font=l.string,o=t.measureText(s.label).width,t.fillStyle=r.backdropColor;const e=pi(r.backdropPadding);t.fillRect(-o/2-e.left,-n-l.size/2-e.top,o+e.width,l.size+e.height)}Ae(t,s.label,0,-n,l,{color:r.color})})),t.restore()}drawTitle(){}}ga.id="radialLinear",ga.defaults={display:!0,animate:!0,position:"chartArea",angleLines:{display:!0,lineWidth:1,borderDash:[],borderDashOffset:0},grid:{circular:!1},startAngle:0,ticks:{showLabelBackdrop:!0,callback:Is.formatters.numeric},pointLabels:{backdropColor:void 0,backdropPadding:2,display:!0,font:{size:10},callback:t=>t,padding:5,centerPointLabels:!1}},ga.defaultRoutes={"angleLines.color":"borderColor","pointLabels.color":"color","ticks.color":"color"},ga.descriptors={angleLines:{_fallback:"grid"}};const pa={millisecond:{common:!0,size:1,steps:1e3},second:{common:!0,size:1e3,steps:60},minute:{common:!0,size:6e4,steps:60},hour:{common:!0,size:36e5,steps:24},day:{common:!0,size:864e5,steps:30},week:{common:!1,size:6048e5,steps:4},month:{common:!0,size:2628e6,steps:12},quarter:{common:!1,size:7884e6,steps:4},year:{common:!0,size:3154e7}},ma=Object.keys(pa);function ba(t,e){return t-e}function xa(t,e){if(i(e))return null;const s=t._adapter,{parser:n,round:a,isoWeekday:r}=t._parseOpts;let l=e;return"function"==typeof n&&(l=n(l)),o(l)||(l="string"==typeof n?s.parse(l,n):s.parse(l)),null===l?null:(a&&(l="week"!==a||!B(r)&&!0!==r?s.startOf(l,a):s.startOf(l,"isoWeek",r)),+l)}function _a(t,e,i,s){const n=ma.length;for(let o=ma.indexOf(t);o<n-1;++o){const t=pa[ma[o]],n=t.steps?t.steps:Number.MAX_SAFE_INTEGER;if(t.common&&Math.ceil((i-e)/(n*t.size))<=s)return ma[o]}return ma[n-1]}function ya(t,e,i){if(i){if(i.length){const{lo:s,hi:n}=tt(i,e);t[i[s]>=e?i[s]:i[n]]=!0}}else t[e]=!0}function va(t,e,i){const s=[],n={},o=e.length;let a,r;for(a=0;a<o;++a)r=e[a],n[r]=a,s.push({value:r,major:!1});return 0!==o&&i?function(t,e,i,s){const n=t._adapter,o=+n.startOf(e[0].value,s),a=e[e.length-1].value;let r,l;for(r=o;r<=a;r=+n.add(r,1,s))l=i[r],l>=0&&(e[l].major=!0);return e}(t,s,n,i):s}class wa extends $s{constructor(t){super(t),this._cache={data:[],labels:[],all:[]},this._unit="day",this._majorUnit=void 0,this._offsets={},this._normalized=!1,this._parseOpts=void 0}init(t,e){const i=t.time||(t.time={}),s=this._adapter=new wn._date(t.adapters.date);s.init(e),b(i.displayFormats,s.formats()),this._parseOpts={parser:i.parser,round:i.round,isoWeekday:i.isoWeekday},super.init(t),this._normalized=e.normalized}parse(t,e){return void 0===t?null:xa(this,t)}beforeLayout(){super.beforeLayout(),this._cache={data:[],labels:[],all:[]}}determineDataLimits(){const t=this.options,e=this._adapter,i=t.time.unit||"day";let{min:s,max:n,minDefined:a,maxDefined:r}=this.getUserBounds();function l(t){a||isNaN(t.min)||(s=Math.min(s,t.min)),r||isNaN(t.max)||(n=Math.max(n,t.max))}a&&r||(l(this._getLabelBounds()),"ticks"===t.bounds&&"labels"===t.ticks.source||l(this.getMinMax(!1))),s=o(s)&&!isNaN(s)?s:+e.startOf(Date.now(),i),n=o(n)&&!isNaN(n)?n:+e.endOf(Date.now(),i)+1,this.min=Math.min(s,n-1),this.max=Math.max(s+1,n)}_getLabelBounds(){const t=this.getLabelTimestamps();let e=Number.POSITIVE_INFINITY,i=Number.NEGATIVE_INFINITY;return t.length&&(e=t[0],i=t[t.length-1]),{min:e,max:i}}buildTicks(){const t=this.options,e=t.time,i=t.ticks,s="labels"===i.source?this.getLabelTimestamps():this._generate();"ticks"===t.bounds&&s.length&&(this.min=this._userMin||s[0],this.max=this._userMax||s[s.length-1]);const n=this.min,o=st(s,n,this.max);return this._unit=e.unit||(i.autoSkip?_a(e.minUnit,this.min,this.max,this._getLabelCapacity(n)):function(t,e,i,s,n){for(let o=ma.length-1;o>=ma.indexOf(i);o--){const i=ma[o];if(pa[i].common&&t._adapter.diff(n,s,i)>=e-1)return i}return ma[i?ma.indexOf(i):0]}(this,o.length,e.minUnit,this.min,this.max)),this._majorUnit=i.major.enabled&&"year"!==this._unit?function(t){for(let e=ma.indexOf(t)+1,i=ma.length;e<i;++e)if(pa[ma[e]].common)return ma[e]}(this._unit):void 0,this.initOffsets(s),t.reverse&&o.reverse(),va(this,o,this._majorUnit)}afterAutoSkip(){this.options.offsetAfterAutoskip&&this.initOffsets(this.ticks.map((t=>+t.value)))}initOffsets(t){let e,i,s=0,n=0;this.options.offset&&t.length&&(e=this.getDecimalForValue(t[0]),s=1===t.length?1-e:(this.getDecimalForValue(t[1])-e)/2,i=this.getDecimalForValue(t[t.length-1]),n=1===t.length?i:(i-this.getDecimalForValue(t[t.length-2]))/2);const o=t.length<3?.5:.25;s=Z(s,0,o),n=Z(n,0,o),this._offsets={start:s,end:n,factor:1/(s+1+n)}}_generate(){const t=this._adapter,e=this.min,i=this.max,s=this.options,n=s.time,o=n.unit||_a(n.minUnit,e,i,this._getLabelCapacity(e)),a=r(n.stepSize,1),l="week"===o&&n.isoWeekday,h=B(l)||!0===l,c={};let d,u,f=e;if(h&&(f=+t.startOf(f,"isoWeek",l)),f=+t.startOf(f,h?"day":o),t.diff(i,e,o)>1e5*a)throw new Error(e+" and "+i+" are too far apart with stepSize of "+a+" "+o);const g="data"===s.ticks.source&&this.getDataTimestamps();for(d=f,u=0;d<i;d=+t.add(d,a,o),u++)ya(c,d,g);return d!==i&&"ticks"!==s.bounds&&1!==u||ya(c,d,g),Object.keys(c).sort(((t,e)=>t-e)).map((t=>+t))}getLabelForValue(t){const e=this._adapter,i=this.options.time;return i.tooltipFormat?e.format(t,i.tooltipFormat):e.format(t,i.displayFormats.datetime)}_tickFormatFunction(t,e,i,s){const n=this.options,o=n.time.displayFormats,a=this._unit,r=this._majorUnit,l=a&&o[a],h=r&&o[r],d=i[e],u=r&&h&&d&&d.major,f=this._adapter.format(t,s||(u?h:l)),g=n.ticks.callback;return g?c(g,[f,e,i],this):f}generateTickLabels(t){let e,i,s;for(e=0,i=t.length;e<i;++e)s=t[e],s.label=this._tickFormatFunction(s.value,e,t)}getDecimalForValue(t){return null===t?NaN:(t-this.min)/(this.max-this.min)}getPixelForValue(t){const e=this._offsets,i=this.getDecimalForValue(t);return this.getPixelForDecimal((e.start+i)*e.factor)}getValueForPixel(t){const e=this._offsets,i=this.getDecimalForPixel(t)/e.factor-e.end;return this.min+i*(this.max-this.min)}_getLabelSize(t){const e=this.options.ticks,i=this.ctx.measureText(t).width,s=H(this.isHorizontal()?e.maxRotation:e.minRotation),n=Math.cos(s),o=Math.sin(s),a=this._resolveTickFontOptions(0).size;return{w:i*n+a*o,h:i*o+a*n}}_getLabelCapacity(t){const e=this.options.time,i=e.displayFormats,s=i[e.unit]||i.millisecond,n=this._tickFormatFunction(t,0,va(this,[t],this._majorUnit),s),o=this._getLabelSize(n),a=Math.floor(this.isHorizontal()?this.width/o.w:this.height/o.h)-1;return a>0?a:1}getDataTimestamps(){let t,e,i=this._cache.data||[];if(i.length)return i;const s=this.getMatchingVisibleMetas();if(this._normalized&&s.length)return this._cache.data=s[0].controller.getAllParsedValues(this);for(t=0,e=s.length;t<e;++t)i=i.concat(s[t].controller.getAllParsedValues(this));return this._cache.data=this.normalize(i)}getLabelTimestamps(){const t=this._cache.labels||[];let e,i;if(t.length)return t;const s=this.getLabels();for(e=0,i=s.length;e<i;++e)t.push(xa(this,s[e]));return this._cache.labels=this._normalized?t:this.normalize(t)}normalize(t){return rt(t.sort(ba))}}function Ma(t,e,i){let s,n,o,a,r=0,l=t.length-1;i?(e>=t[r].pos&&e<=t[l].pos&&({lo:r,hi:l}=et(t,"pos",e)),({pos:s,time:o}=t[r]),({pos:n,time:a}=t[l])):(e>=t[r].time&&e<=t[l].time&&({lo:r,hi:l}=et(t,"time",e)),({time:s,pos:o}=t[r]),({time:n,pos:a}=t[l]));const h=n-s;return h?o+(a-o)*(e-s)/h:o}wa.id="time",wa.defaults={bounds:"data",adapters:{},time:{parser:!1,unit:!1,round:!1,isoWeekday:!1,minUnit:"millisecond",displayFormats:{}},ticks:{source:"auto",major:{enabled:!1}}};class ka extends wa{constructor(t){super(t),this._table=[],this._minPos=void 0,this._tableRange=void 0}initOffsets(){const t=this._getTimestampsForTable(),e=this._table=this.buildLookupTable(t);this._minPos=Ma(e,this.min),this._tableRange=Ma(e,this.max)-this._minPos,super.initOffsets(t)}buildLookupTable(t){const{min:e,max:i}=this,s=[],n=[];let o,a,r,l,h;for(o=0,a=t.length;o<a;++o)l=t[o],l>=e&&l<=i&&s.push(l);if(s.length<2)return[{time:e,pos:0},{time:i,pos:1}];for(o=0,a=s.length;o<a;++o)h=s[o+1],r=s[o-1],l=s[o],Math.round((h+r)/2)!==l&&n.push({time:l,pos:o/(a-1)});return n}_getTimestampsForTable(){let t=this._cache.all||[];if(t.length)return t;const e=this.getDataTimestamps(),i=this.getLabelTimestamps();return t=e.length&&i.length?this.normalize(e.concat(i)):e.length?e:i,t=this._cache.all=t,t}getDecimalForValue(t){return(Ma(this._table,t)-this._minPos)/this._tableRange}getValueForPixel(t){const e=this._offsets,i=this.getDecimalForPixel(t)/e.factor-e.end;return Ma(this._table,i*this._tableRange+this._minPos,!0)}}ka.id="timeseries",ka.defaults=wa.defaults;var Sa=Object.freeze({__proto__:null,CategoryScale:ta,LinearScale:sa,LogarithmicScale:oa,RadialLinearScale:ga,TimeScale:wa,TimeSeriesScale:ka});return bn.register(Bn,Sa,co,Jo),bn.helpers={...Ti},bn._adapters=wn,bn.Animation=xs,bn.Animations=ys,bn.animator=mt,bn.controllers=Us.controllers.items,bn.DatasetController=Ls,bn.Element=Es,bn.elements=co,bn.Interaction=Vi,bn.layouts=Zi,bn.platforms=ps,bn.Scale=$s,bn.Ticks=Is,Object.assign(bn,Bn,Sa,co,Jo,ps),bn.Chart=bn,"undefined"!=typeof window&&(window.Chart=bn),bn}));
assets/js/admin/circles.min.js ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ /**
2
+ * circles - v0.0.6 - 2018-03-07
3
+ *
4
+ * Copyright (c) 2018 lugolabs
5
+ * Licensed
6
+ */
7
+ !function(a,b){"object"==typeof exports?module.exports=b():"function"==typeof define&&define.amd?define([],b):a.Circles=b()}(this,function(){"use strict";var a=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(a){setTimeout(a,1e3/60)},b=function(a){var b=a.id;if(this._el=document.getElementById(b),null!==this._el){this._radius=a.radius||10,this._duration=void 0===a.duration?500:a.duration,this._value=1e-7,this._maxValue=a.maxValue||100,this._text=void 0===a.text?function(a){return this.htmlifyNumber(a)}:a.text,this._strokeWidth=a.width||10,this._colors=a.colors||["#EEE","#F00"],this._svg=null,this._movingPath=null,this._wrapContainer=null,this._textContainer=null,this._wrpClass=a.wrpClass||"circles-wrp",this._textClass=a.textClass||"circles-text",this._valClass=a.valueStrokeClass||"circles-valueStroke",this._maxValClass=a.maxValueStrokeClass||"circles-maxValueStroke",this._styleWrapper=!1!==a.styleWrapper,this._styleText=!1!==a.styleText;var c=Math.PI/180*270;this._start=-Math.PI/180*90,this._startPrecise=this._precise(this._start),this._circ=c-this._start,this._generate().update(a.value||0)}};return b.prototype={VERSION:"0.0.6",_generate:function(){return this._svgSize=2*this._radius,this._radiusAdjusted=this._radius-this._strokeWidth/2,this._generateSvg()._generateText()._generateWrapper(),this._el.innerHTML="",this._el.appendChild(this._wrapContainer),this},_setPercentage:function(a){this._movingPath.setAttribute("d",this._calculatePath(a,!0)),this._textContainer.innerHTML=this._getText(this.getValueFromPercent(a))},_generateWrapper:function(){return this._wrapContainer=document.createElement("div"),this._wrapContainer.className=this._wrpClass,this._styleWrapper&&(this._wrapContainer.style.position="relative",this._wrapContainer.style.display="inline-block"),this._wrapContainer.appendChild(this._svg),this._wrapContainer.appendChild(this._textContainer),this},_generateText:function(){if(this._textContainer=document.createElement("div"),this._textContainer.className=this._textClass,this._styleText){var a={position:"absolute",top:0,left:0,textAlign:"center",width:"100%",fontSize:.7*this._radius+"px",height:this._svgSize+"px",lineHeight:this._svgSize+"px"};for(var b in a)this._textContainer.style[b]=a[b]}return this._textContainer.innerHTML=this._getText(0),this},_getText:function(a){return this._text?(void 0===a&&(a=this._value),a=parseFloat(a.toFixed(2)),"function"==typeof this._text?this._text.call(this,a):this._text):""},_generateSvg:function(){return this._svg=document.createElementNS("http://www.w3.org/2000/svg","svg"),this._svg.setAttribute("xmlns","http://www.w3.org/2000/svg"),this._svg.setAttribute("width",this._svgSize),this._svg.setAttribute("height",this._svgSize),this._generatePath(100,!1,this._colors[0],this._maxValClass)._generatePath(1,!0,this._colors[1],this._valClass),this._movingPath=this._svg.getElementsByTagName("path")[1],this},_generatePath:function(a,b,c,d){var e=document.createElementNS("http://www.w3.org/2000/svg","path");return e.setAttribute("fill","transparent"),e.setAttribute("stroke",c),e.setAttribute("stroke-width",this._strokeWidth),e.setAttribute("d",this._calculatePath(a,b)),e.setAttribute("class",d),this._svg.appendChild(e),this},_calculatePath:function(a,b){var c=this._start+a/100*this._circ,d=this._precise(c);return this._arc(d,b)},_arc:function(a,b){var c=a-.001,d=a-this._startPrecise<Math.PI?0:1;return["M",this._radius+this._radiusAdjusted*Math.cos(this._startPrecise),this._radius+this._radiusAdjusted*Math.sin(this._startPrecise),"A",this._radiusAdjusted,this._radiusAdjusted,0,d,1,this._radius+this._radiusAdjusted*Math.cos(c),this._radius+this._radiusAdjusted*Math.sin(c),b?"":"Z"].join(" ")},_precise:function(a){return Math.round(1e3*a)/1e3},htmlifyNumber:function(a,b,c){b=b||"circles-integer",c=c||"circles-decimals";var d=(a+"").split("."),e='<span class="'+b+'">'+d[0]+"</span>";return d.length>1&&(e+='.<span class="'+c+'">'+d[1].substring(0,2)+"</span>"),e},updateRadius:function(a){return this._radius=a,this._generate().update(!0)},updateWidth:function(a){return this._strokeWidth=a,this._generate().update(!0)},updateColors:function(a){this._colors=a;var b=this._svg.getElementsByTagName("path");return b[0].setAttribute("stroke",a[0]),b[1].setAttribute("stroke",a[1]),this},getPercent:function(){return 100*this._value/this._maxValue},getValueFromPercent:function(a){return this._maxValue*a/100},getValue:function(){return this._value},getMaxValue:function(){return this._maxValue},update:function(b,c){if(!0===b)return this._setPercentage(this.getPercent()),this;if(this._value==b||isNaN(b))return this;void 0===c&&(c=this._duration);var d,e,f,g,h=this,i=h.getPercent(),j=1;return this._value=Math.min(this._maxValue,Math.max(0,b)),c?(d=h.getPercent(),e=d>i,j+=d%1,f=Math.floor(Math.abs(d-i)/j),g=c/f,function b(c){if(e?i+=j:i-=j,e&&i>=d||!e&&i<=d)return void a(function(){h._setPercentage(d)});a(function(){h._setPercentage(i)});var f=Date.now(),k=f-c;k>=g?b(f):setTimeout(function(){b(Date.now())},g-k)}(Date.now()),this):(this._setPercentage(this.getPercent()),this)}},b.create=function(a){return new b(a)},b});
assets/js/admin/index.php ADDED
@@ -0,0 +1,2 @@
 
 
1
+ <?php
2
+ // Silence is golden.
assets/js/admin/vue.js ADDED
@@ -0,0 +1,11841 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Vue.js v2.7.8
3
+ * (c) 2014-2022 Evan You
4
+ * Released under the MIT License.
5
+ */
6
+ (function (global, factory) {
7
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
8
+ typeof define === 'function' && define.amd ? define(factory) :
9
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Vue = factory());
10
+ })(this, (function () { 'use strict';
11
+
12
+ var emptyObject = Object.freeze({});
13
+ var isArray = Array.isArray;
14
+ // These helpers produce better VM code in JS engines due to their
15
+ // explicitness and function inlining.
16
+ function isUndef(v) {
17
+ return v === undefined || v === null;
18
+ }
19
+ function isDef(v) {
20
+ return v !== undefined && v !== null;
21
+ }
22
+ function isTrue(v) {
23
+ return v === true;
24
+ }
25
+ function isFalse(v) {
26
+ return v === false;
27
+ }
28
+ /**
29
+ * Check if value is primitive.
30
+ */
31
+ function isPrimitive(value) {
32
+ return (typeof value === 'string' ||
33
+ typeof value === 'number' ||
34
+ // $flow-disable-line
35
+ typeof value === 'symbol' ||
36
+ typeof value === 'boolean');
37
+ }
38
+ function isFunction(value) {
39
+ return typeof value === 'function';
40
+ }
41
+ /**
42
+ * Quick object check - this is primarily used to tell
43
+ * objects from primitive values when we know the value
44
+ * is a JSON-compliant type.
45
+ */
46
+ function isObject(obj) {
47
+ return obj !== null && typeof obj === 'object';
48
+ }
49
+ /**
50
+ * Get the raw type string of a value, e.g., [object Object].
51
+ */
52
+ var _toString = Object.prototype.toString;
53
+ function toRawType(value) {
54
+ return _toString.call(value).slice(8, -1);
55
+ }
56
+ /**
57
+ * Strict object type check. Only returns true
58
+ * for plain JavaScript objects.
59
+ */
60
+ function isPlainObject(obj) {
61
+ return _toString.call(obj) === '[object Object]';
62
+ }
63
+ function isRegExp(v) {
64
+ return _toString.call(v) === '[object RegExp]';
65
+ }
66
+ /**
67
+ * Check if val is a valid array index.
68
+ */
69
+ function isValidArrayIndex(val) {
70
+ var n = parseFloat(String(val));
71
+ return n >= 0 && Math.floor(n) === n && isFinite(val);
72
+ }
73
+ function isPromise(val) {
74
+ return (isDef(val) &&
75
+ typeof val.then === 'function' &&
76
+ typeof val.catch === 'function');
77
+ }
78
+ /**
79
+ * Convert a value to a string that is actually rendered.
80
+ */
81
+ function toString(val) {
82
+ return val == null
83
+ ? ''
84
+ : Array.isArray(val) || (isPlainObject(val) && val.toString === _toString)
85
+ ? JSON.stringify(val, null, 2)
86
+ : String(val);
87
+ }
88
+ /**
89
+ * Convert an input value to a number for persistence.
90
+ * If the conversion fails, return original string.
91
+ */
92
+ function toNumber(val) {
93
+ var n = parseFloat(val);
94
+ return isNaN(n) ? val : n;
95
+ }
96
+ /**
97
+ * Make a map and return a function for checking if a key
98
+ * is in that map.
99
+ */
100
+ function makeMap(str, expectsLowerCase) {
101
+ var map = Object.create(null);
102
+ var list = str.split(',');
103
+ for (var i = 0; i < list.length; i++) {
104
+ map[list[i]] = true;
105
+ }
106
+ return expectsLowerCase ? function (val) { return map[val.toLowerCase()]; } : function (val) { return map[val]; };
107
+ }
108
+ /**
109
+ * Check if a tag is a built-in tag.
110
+ */
111
+ var isBuiltInTag = makeMap('slot,component', true);
112
+ /**
113
+ * Check if an attribute is a reserved attribute.
114
+ */
115
+ var isReservedAttribute = makeMap('key,ref,slot,slot-scope,is');
116
+ /**
117
+ * Remove an item from an array.
118
+ */
119
+ function remove$2(arr, item) {
120
+ if (arr.length) {
121
+ var index = arr.indexOf(item);
122
+ if (index > -1) {
123
+ return arr.splice(index, 1);
124
+ }
125
+ }
126
+ }
127
+ /**
128
+ * Check whether an object has the property.
129
+ */
130
+ var hasOwnProperty = Object.prototype.hasOwnProperty;
131
+ function hasOwn(obj, key) {
132
+ return hasOwnProperty.call(obj, key);
133
+ }
134
+ /**
135
+ * Create a cached version of a pure function.
136
+ */
137
+ function cached(fn) {
138
+ var cache = Object.create(null);
139
+ return function cachedFn(str) {
140
+ var hit = cache[str];
141
+ return hit || (cache[str] = fn(str));
142
+ };
143
+ }
144
+ /**
145
+ * Camelize a hyphen-delimited string.
146
+ */
147
+ var camelizeRE = /-(\w)/g;
148
+ var camelize = cached(function (str) {
149
+ return str.replace(camelizeRE, function (_, c) { return (c ? c.toUpperCase() : ''); });
150
+ });
151
+ /**
152
+ * Capitalize a string.
153
+ */
154
+ var capitalize = cached(function (str) {
155
+ return str.charAt(0).toUpperCase() + str.slice(1);
156
+ });
157
+ /**
158
+ * Hyphenate a camelCase string.
159
+ */
160
+ var hyphenateRE = /\B([A-Z])/g;
161
+ var hyphenate = cached(function (str) {
162
+ return str.replace(hyphenateRE, '-$1').toLowerCase();
163
+ });
164
+ /**
165
+ * Simple bind polyfill for environments that do not support it,
166
+ * e.g., PhantomJS 1.x. Technically, we don't need this anymore
167
+ * since native bind is now performant enough in most browsers.
168
+ * But removing it would mean breaking code that was able to run in
169
+ * PhantomJS 1.x, so this must be kept for backward compatibility.
170
+ */
171
+ /* istanbul ignore next */
172
+ function polyfillBind(fn, ctx) {
173
+ function boundFn(a) {
174
+ var l = arguments.length;
175
+ return l
176
+ ? l > 1
177
+ ? fn.apply(ctx, arguments)
178
+ : fn.call(ctx, a)
179
+ : fn.call(ctx);
180
+ }
181
+ boundFn._length = fn.length;
182
+ return boundFn;
183
+ }
184
+ function nativeBind(fn, ctx) {
185
+ return fn.bind(ctx);
186
+ }
187
+ // @ts-expect-error bind cannot be `undefined`
188
+ var bind$1 = Function.prototype.bind ? nativeBind : polyfillBind;
189
+ /**
190
+ * Convert an Array-like object to a real Array.
191
+ */
192
+ function toArray(list, start) {
193
+ start = start || 0;
194
+ var i = list.length - start;
195
+ var ret = new Array(i);
196
+ while (i--) {
197
+ ret[i] = list[i + start];
198
+ }
199
+ return ret;
200
+ }
201
+ /**
202
+ * Mix properties into target object.
203
+ */
204
+ function extend(to, _from) {
205
+ for (var key in _from) {
206
+ to[key] = _from[key];
207
+ }
208
+ return to;
209
+ }
210
+ /**
211
+ * Merge an Array of Objects into a single Object.
212
+ */
213
+ function toObject(arr) {
214
+ var res = {};
215
+ for (var i = 0; i < arr.length; i++) {
216
+ if (arr[i]) {
217
+ extend(res, arr[i]);
218
+ }
219
+ }
220
+ return res;
221
+ }
222
+ /* eslint-disable no-unused-vars */
223
+ /**
224
+ * Perform no operation.
225
+ * Stubbing args to make Flow happy without leaving useless transpiled code
226
+ * with ...rest (https://flow.org/blog/2017/05/07/Strict-Function-Call-Arity/).
227
+ */
228
+ function noop(a, b, c) { }
229
+ /**
230
+ * Always return false.
231
+ */
232
+ var no = function (a, b, c) { return false; };
233
+ /* eslint-enable no-unused-vars */
234
+ /**
235
+ * Return the same value.
236
+ */
237
+ var identity = function (_) { return _; };
238
+ /**
239
+ * Generate a string containing static keys from compiler modules.
240
+ */
241
+ function genStaticKeys$1(modules) {
242
+ return modules
243
+ .reduce(function (keys, m) {
244
+ return keys.concat(m.staticKeys || []);
245
+ }, [])
246
+ .join(',');
247
+ }
248
+ /**
249
+ * Check if two values are loosely equal - that is,
250
+ * if they are plain objects, do they have the same shape?
251
+ */
252
+ function looseEqual(a, b) {
253
+ if (a === b)
254
+ return true;
255
+ var isObjectA = isObject(a);
256
+ var isObjectB = isObject(b);
257
+ if (isObjectA && isObjectB) {
258
+ try {
259
+ var isArrayA = Array.isArray(a);
260
+ var isArrayB = Array.isArray(b);
261
+ if (isArrayA && isArrayB) {
262
+ return (a.length === b.length &&
263
+ a.every(function (e, i) {
264
+ return looseEqual(e, b[i]);
265
+ }));
266
+ }
267
+ else if (a instanceof Date && b instanceof Date) {
268
+ return a.getTime() === b.getTime();
269
+ }
270
+ else if (!isArrayA && !isArrayB) {
271
+ var keysA = Object.keys(a);
272
+ var keysB = Object.keys(b);
273
+ return (keysA.length === keysB.length &&
274
+ keysA.every(function (key) {
275
+ return looseEqual(a[key], b[key]);
276
+ }));
277
+ }
278
+ else {
279
+ /* istanbul ignore next */
280
+ return false;
281
+ }
282
+ }
283
+ catch (e) {
284
+ /* istanbul ignore next */
285
+ return false;
286
+ }
287
+ }
288
+ else if (!isObjectA && !isObjectB) {
289
+ return String(a) === String(b);
290
+ }
291
+ else {
292
+ return false;
293
+ }
294
+ }
295
+ /**
296
+ * Return the first index at which a loosely equal value can be
297
+ * found in the array (if value is a plain object, the array must
298
+ * contain an object of the same shape), or -1 if it is not present.
299
+ */
300
+ function looseIndexOf(arr, val) {
301
+ for (var i = 0; i < arr.length; i++) {
302
+ if (looseEqual(arr[i], val))
303
+ return i;
304
+ }
305
+ return -1;
306
+ }
307
+ /**
308
+ * Ensure a function is called only once.
309
+ */
310
+ function once(fn) {
311
+ var called = false;
312
+ return function () {
313
+ if (!called) {
314
+ called = true;
315
+ fn.apply(this, arguments);
316
+ }
317
+ };
318
+ }
319
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is#polyfill
320
+ function hasChanged(x, y) {
321
+ if (x === y) {
322
+ return x === 0 && 1 / x !== 1 / y;
323
+ }
324
+ else {
325
+ return x === x || y === y;
326
+ }
327
+ }
328
+
329
+ var SSR_ATTR = 'data-server-rendered';
330
+ var ASSET_TYPES = ['component', 'directive', 'filter'];
331
+ var LIFECYCLE_HOOKS = [
332
+ 'beforeCreate',
333
+ 'created',
334
+ 'beforeMount',
335
+ 'mounted',
336
+ 'beforeUpdate',
337
+ 'updated',
338
+ 'beforeDestroy',
339
+ 'destroyed',
340
+ 'activated',
341
+ 'deactivated',
342
+ 'errorCaptured',
343
+ 'serverPrefetch',
344
+ 'renderTracked',
345
+ 'renderTriggered'
346
+ ];
347
+
348
+ var config = {
349
+ /**
350
+ * Option merge strategies (used in core/util/options)
351
+ */
352
+ // $flow-disable-line
353
+ optionMergeStrategies: Object.create(null),
354
+ /**
355
+ * Whether to suppress warnings.
356
+ */
357
+ silent: false,
358
+ /**
359
+ * Show production mode tip message on boot?
360
+ */
361
+ productionTip: true,
362
+ /**
363
+ * Whether to enable devtools
364
+ */
365
+ devtools: true,
366
+ /**
367
+ * Whether to record perf
368
+ */
369
+ performance: false,
370
+ /**
371
+ * Error handler for watcher errors
372
+ */
373
+ errorHandler: null,
374
+ /**
375
+ * Warn handler for watcher warns
376
+ */
377
+ warnHandler: null,
378
+ /**
379
+ * Ignore certain custom elements
380
+ */
381
+ ignoredElements: [],
382
+ /**
383
+ * Custom user key aliases for v-on
384
+ */
385
+ // $flow-disable-line
386
+ keyCodes: Object.create(null),
387
+ /**
388
+ * Check if a tag is reserved so that it cannot be registered as a
389
+ * component. This is platform-dependent and may be overwritten.
390
+ */
391
+ isReservedTag: no,
392
+ /**
393
+ * Check if an attribute is reserved so that it cannot be used as a component
394
+ * prop. This is platform-dependent and may be overwritten.
395
+ */
396
+ isReservedAttr: no,
397
+ /**
398
+ * Check if a tag is an unknown element.
399
+ * Platform-dependent.
400
+ */
401
+ isUnknownElement: no,
402
+ /**
403
+ * Get the namespace of an element
404
+ */
405
+ getTagNamespace: noop,
406
+ /**
407
+ * Parse the real tag name for the specific platform.
408
+ */
409
+ parsePlatformTagName: identity,
410
+ /**
411
+ * Check if an attribute must be bound using property, e.g. value
412
+ * Platform-dependent.
413
+ */
414
+ mustUseProp: no,
415
+ /**
416
+ * Perform updates asynchronously. Intended to be used by Vue Test Utils
417
+ * This will significantly reduce performance if set to false.
418
+ */
419
+ async: true,
420
+ /**
421
+ * Exposed for legacy reasons
422
+ */
423
+ _lifecycleHooks: LIFECYCLE_HOOKS
424
+ };
425
+
426
+ /**
427
+ * unicode letters used for parsing html tags, component names and property paths.
428
+ * using https://www.w3.org/TR/html53/semantics-scripting.html#potentialcustomelementname
429
+ * skipping \u10000-\uEFFFF due to it freezing up PhantomJS
430
+ */
431
+ var unicodeRegExp = /a-zA-Z\u00B7\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u037D\u037F-\u1FFF\u200C-\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD/;
432
+ /**
433
+ * Check if a string starts with $ or _
434
+ */
435
+ function isReserved(str) {
436
+ var c = (str + '').charCodeAt(0);
437
+ return c === 0x24 || c === 0x5f;
438
+ }
439
+ /**
440
+ * Define a property.
441
+ */
442
+ function def(obj, key, val, enumerable) {
443
+ Object.defineProperty(obj, key, {
444
+ value: val,
445
+ enumerable: !!enumerable,
446
+ writable: true,
447
+ configurable: true
448
+ });
449
+ }
450
+ /**
451
+ * Parse simple path.
452
+ */
453
+ var bailRE = new RegExp("[^".concat(unicodeRegExp.source, ".$_\\d]"));
454
+ function parsePath(path) {
455
+ if (bailRE.test(path)) {
456
+ return;
457
+ }
458
+ var segments = path.split('.');
459
+ return function (obj) {
460
+ for (var i = 0; i < segments.length; i++) {
461
+ if (!obj)
462
+ return;
463
+ obj = obj[segments[i]];
464
+ }
465
+ return obj;
466
+ };
467
+ }
468
+
469
+ // can we use __proto__?
470
+ var hasProto = '__proto__' in {};
471
+ // Browser environment sniffing
472
+ var inBrowser = typeof window !== 'undefined';
473
+ var UA = inBrowser && window.navigator.userAgent.toLowerCase();
474
+ var isIE = UA && /msie|trident/.test(UA);
475
+ var isIE9 = UA && UA.indexOf('msie 9.0') > 0;
476
+ var isEdge = UA && UA.indexOf('edge/') > 0;
477
+ UA && UA.indexOf('android') > 0;
478
+ var isIOS = UA && /iphone|ipad|ipod|ios/.test(UA);
479
+ UA && /chrome\/\d+/.test(UA) && !isEdge;
480
+ UA && /phantomjs/.test(UA);
481
+ var isFF = UA && UA.match(/firefox\/(\d+)/);
482
+ // Firefox has a "watch" function on Object.prototype...
483
+ // @ts-expect-error firebox support
484
+ var nativeWatch = {}.watch;
485
+ var supportsPassive = false;
486
+ if (inBrowser) {
487
+ try {
488
+ var opts = {};
489
+ Object.defineProperty(opts, 'passive', {
490
+ get: function () {
491
+ /* istanbul ignore next */
492
+ supportsPassive = true;
493
+ }
494
+ }); // https://github.com/facebook/flow/issues/285
495
+ window.addEventListener('test-passive', null, opts);
496
+ }
497
+ catch (e) { }
498
+ }
499
+ // this needs to be lazy-evaled because vue may be required before
500
+ // vue-server-renderer can set VUE_ENV
501
+ var _isServer;
502
+ var isServerRendering = function () {
503
+ if (_isServer === undefined) {
504
+ /* istanbul ignore if */
505
+ if (!inBrowser && typeof global !== 'undefined') {
506
+ // detect presence of vue-server-renderer and avoid
507
+ // Webpack shimming the process
508
+ _isServer =
509
+ global['process'] && global['process'].env.VUE_ENV === 'server';
510
+ }
511
+ else {
512
+ _isServer = false;
513
+ }
514
+ }
515
+ return _isServer;
516
+ };
517
+ // detect devtools
518
+ var devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__;
519
+ /* istanbul ignore next */
520
+ function isNative(Ctor) {
521
+ return typeof Ctor === 'function' && /native code/.test(Ctor.toString());
522
+ }
523
+ var hasSymbol = typeof Symbol !== 'undefined' &&
524
+ isNative(Symbol) &&
525
+ typeof Reflect !== 'undefined' &&
526
+ isNative(Reflect.ownKeys);
527
+ var _Set; // $flow-disable-line
528
+ /* istanbul ignore if */ if (typeof Set !== 'undefined' && isNative(Set)) {
529
+ // use native Set when available.
530
+ _Set = Set;
531
+ }
532
+ else {
533
+ // a non-standard Set polyfill that only works with primitive keys.
534
+ _Set = /** @class */ (function () {
535
+ function Set() {
536
+ this.set = Object.create(null);
537
+ }
538
+ Set.prototype.has = function (key) {
539
+ return this.set[key] === true;
540
+ };
541
+ Set.prototype.add = function (key) {
542
+ this.set[key] = true;
543
+ };
544
+ Set.prototype.clear = function () {
545
+ this.set = Object.create(null);
546
+ };
547
+ return Set;
548
+ }());
549
+ }
550
+
551
+ var currentInstance = null;
552
+ /**
553
+ * This is exposed for compatibility with v3 (e.g. some functions in VueUse
554
+ * relies on it). Do not use this internally, just use `currentInstance`.
555
+ *
556
+ * @internal this function needs manual type declaration because it relies
557
+ * on previously manually authored types from Vue 2
558
+ */
559
+ function getCurrentInstance() {
560
+ return currentInstance && { proxy: currentInstance };
561
+ }
562
+ /**
563
+ * @internal
564
+ */
565
+ function setCurrentInstance(vm) {
566
+ if (vm === void 0) { vm = null; }
567
+ if (!vm)
568
+ currentInstance && currentInstance._scope.off();
569
+ currentInstance = vm;
570
+ vm && vm._scope.on();
571
+ }
572
+
573
+ /**
574
+ * @internal
575
+ */
576
+ var VNode = /** @class */ (function () {
577
+ function VNode(tag, data, children, text, elm, context, componentOptions, asyncFactory) {
578
+ this.tag = tag;
579
+ this.data = data;
580
+ this.children = children;
581
+ this.text = text;
582
+ this.elm = elm;
583
+ this.ns = undefined;
584
+ this.context = context;
585
+ this.fnContext = undefined;
586
+ this.fnOptions = undefined;
587
+ this.fnScopeId = undefined;
588
+ this.key = data && data.key;
589
+ this.componentOptions = componentOptions;
590
+ this.componentInstance = undefined;
591
+ this.parent = undefined;
592
+ this.raw = false;
593
+ this.isStatic = false;
594
+ this.isRootInsert = true;
595
+ this.isComment = false;
596
+ this.isCloned = false;
597
+ this.isOnce = false;
598
+ this.asyncFactory = asyncFactory;
599
+ this.asyncMeta = undefined;
600
+ this.isAsyncPlaceholder = false;
601
+ }
602
+ Object.defineProperty(VNode.prototype, "child", {
603
+ // DEPRECATED: alias for componentInstance for backwards compat.
604
+ /* istanbul ignore next */
605
+ get: function () {
606
+ return this.componentInstance;
607
+ },
608
+ enumerable: false,
609
+ configurable: true
610
+ });
611
+ return VNode;
612
+ }());
613
+ var createEmptyVNode = function (text) {
614
+ if (text === void 0) { text = ''; }
615
+ var node = new VNode();
616
+ node.text = text;
617
+ node.isComment = true;
618
+ return node;
619
+ };
620
+ function createTextVNode(val) {
621
+ return new VNode(undefined, undefined, undefined, String(val));
622
+ }
623
+ // optimized shallow clone
624
+ // used for static nodes and slot nodes because they may be reused across
625
+ // multiple renders, cloning them avoids errors when DOM manipulations rely
626
+ // on their elm reference.
627
+ function cloneVNode(vnode) {
628
+ var cloned = new VNode(vnode.tag, vnode.data,
629
+ // #7975
630
+ // clone children array to avoid mutating original in case of cloning
631
+ // a child.
632
+ vnode.children && vnode.children.slice(), vnode.text, vnode.elm, vnode.context, vnode.componentOptions, vnode.asyncFactory);
633
+ cloned.ns = vnode.ns;
634
+ cloned.isStatic = vnode.isStatic;
635
+ cloned.key = vnode.key;
636
+ cloned.isComment = vnode.isComment;
637
+ cloned.fnContext = vnode.fnContext;
638
+ cloned.fnOptions = vnode.fnOptions;
639
+ cloned.fnScopeId = vnode.fnScopeId;
640
+ cloned.asyncMeta = vnode.asyncMeta;
641
+ cloned.isCloned = true;
642
+ return cloned;
643
+ }
644
+
645
+ /* not type checking this file because flow doesn't play well with Proxy */
646
+ var initProxy;
647
+ {
648
+ var allowedGlobals_1 = makeMap('Infinity,undefined,NaN,isFinite,isNaN,' +
649
+ 'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' +
650
+ 'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt,' +
651
+ 'require' // for Webpack/Browserify
652
+ );
653
+ var warnNonPresent_1 = function (target, key) {
654
+ warn$2("Property or method \"".concat(key, "\" is not defined on the instance but ") +
655
+ 'referenced during render. Make sure that this property is reactive, ' +
656
+ 'either in the data option, or for class-based components, by ' +
657
+ 'initializing the property. ' +
658
+ 'See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.', target);
659
+ };
660
+ var warnReservedPrefix_1 = function (target, key) {
661
+ warn$2("Property \"".concat(key, "\" must be accessed with \"$data.").concat(key, "\" because ") +
662
+ 'properties starting with "$" or "_" are not proxied in the Vue instance to ' +
663
+ 'prevent conflicts with Vue internals. ' +
664
+ 'See: https://vuejs.org/v2/api/#data', target);
665
+ };
666
+ var hasProxy_1 = typeof Proxy !== 'undefined' && isNative(Proxy);
667
+ if (hasProxy_1) {
668
+ var isBuiltInModifier_1 = makeMap('stop,prevent,self,ctrl,shift,alt,meta,exact');
669
+ config.keyCodes = new Proxy(config.keyCodes, {
670
+ set: function (target, key, value) {
671
+ if (isBuiltInModifier_1(key)) {
672
+ warn$2("Avoid overwriting built-in modifier in config.keyCodes: .".concat(key));
673
+ return false;
674
+ }
675
+ else {
676
+ target[key] = value;
677
+ return true;
678
+ }
679
+ }
680
+ });
681
+ }
682
+ var hasHandler_1 = {
683
+ has: function (target, key) {
684
+ var has = key in target;
685
+ var isAllowed = allowedGlobals_1(key) ||
686
+ (typeof key === 'string' &&
687
+ key.charAt(0) === '_' &&
688
+ !(key in target.$data));
689
+ if (!has && !isAllowed) {
690
+ if (key in target.$data)
691
+ warnReservedPrefix_1(target, key);
692
+ else
693
+ warnNonPresent_1(target, key);
694
+ }
695
+ return has || !isAllowed;
696
+ }
697
+ };
698
+ var getHandler_1 = {
699
+ get: function (target, key) {
700
+ if (typeof key === 'string' && !(key in target)) {
701
+ if (key in target.$data)
702
+ warnReservedPrefix_1(target, key);
703
+ else
704
+ warnNonPresent_1(target, key);
705
+ }
706
+ return target[key];
707
+ }
708
+ };
709
+ initProxy = function initProxy(vm) {
710
+ if (hasProxy_1) {
711
+ // determine which proxy handler to use
712
+ var options = vm.$options;
713
+ var handlers = options.render && options.render._withStripped ? getHandler_1 : hasHandler_1;
714
+ vm._renderProxy = new Proxy(vm, handlers);
715
+ }
716
+ else {
717
+ vm._renderProxy = vm;
718
+ }
719
+ };
720
+ }
721
+
722
+ /******************************************************************************
723
+ Copyright (c) Microsoft Corporation.
724
+
725
+ Permission to use, copy, modify, and/or distribute this software for any
726
+ purpose with or without fee is hereby granted.
727
+
728
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
729
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
730
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
731
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
732
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
733
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
734
+ PERFORMANCE OF THIS SOFTWARE.
735
+ ***************************************************************************** */
736
+
737
+ var __assign = function() {
738
+ __assign = Object.assign || function __assign(t) {
739
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
740
+ s = arguments[i];
741
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
742
+ }
743
+ return t;
744
+ };
745
+ return __assign.apply(this, arguments);
746
+ };
747
+
748
+ var uid$2 = 0;
749
+ /**
750
+ * A dep is an observable that can have multiple
751
+ * directives subscribing to it.
752
+ * @internal
753
+ */
754
+ var Dep = /** @class */ (function () {
755
+ function Dep() {
756
+ this.id = uid$2++;
757
+ this.subs = [];
758
+ }
759
+ Dep.prototype.addSub = function (sub) {
760
+ this.subs.push(sub);
761
+ };
762
+ Dep.prototype.removeSub = function (sub) {
763
+ remove$2(this.subs, sub);
764
+ };
765
+ Dep.prototype.depend = function (info) {
766
+ if (Dep.target) {
767
+ Dep.target.addDep(this);
768
+ if (info && Dep.target.onTrack) {
769
+ Dep.target.onTrack(__assign({ effect: Dep.target }, info));
770
+ }
771
+ }
772
+ };
773
+ Dep.prototype.notify = function (info) {
774
+ // stabilize the subscriber list first
775
+ var subs = this.subs.slice();
776
+ if (!config.async) {
777
+ // subs aren't sorted in scheduler if not running async
778
+ // we need to sort them now to make sure they fire in correct
779
+ // order
780
+ subs.sort(function (a, b) { return a.id - b.id; });
781
+ }
782
+ for (var i = 0, l = subs.length; i < l; i++) {
783
+ if (info) {
784
+ var sub = subs[i];
785
+ sub.onTrigger &&
786
+ sub.onTrigger(__assign({ effect: subs[i] }, info));
787
+ }
788
+ subs[i].update();
789
+ }
790
+ };
791
+ return Dep;
792
+ }());
793
+ // The current target watcher being evaluated.
794
+ // This is globally unique because only one watcher
795
+ // can be evaluated at a time.
796
+ Dep.target = null;
797
+ var targetStack = [];
798
+ function pushTarget(target) {
799
+ targetStack.push(target);
800
+ Dep.target = target;
801
+ }
802
+ function popTarget() {
803
+ targetStack.pop();
804
+ Dep.target = targetStack[targetStack.length - 1];
805
+ }
806
+
807
+ /*
808
+ * not type checking this file because flow doesn't play well with
809
+ * dynamically accessing methods on Array prototype
810
+ */
811
+ var arrayProto = Array.prototype;
812
+ var arrayMethods = Object.create(arrayProto);
813
+ var methodsToPatch = [
814
+ 'push',
815
+ 'pop',
816
+ 'shift',
817
+ 'unshift',
818
+ 'splice',
819
+ 'sort',
820
+ 'reverse'
821
+ ];
822
+ /**
823
+ * Intercept mutating methods and emit events
824
+ */
825
+ methodsToPatch.forEach(function (method) {
826
+ // cache original method
827
+ var original = arrayProto[method];
828
+ def(arrayMethods, method, function mutator() {
829
+ var args = [];
830
+ for (var _i = 0; _i < arguments.length; _i++) {
831
+ args[_i] = arguments[_i];
832
+ }
833
+ var result = original.apply(this, args);
834
+ var ob = this.__ob__;
835
+ var inserted;
836
+ switch (method) {
837
+ case 'push':
838
+ case 'unshift':
839
+ inserted = args;
840
+ break;
841
+ case 'splice':
842
+ inserted = args.slice(2);
843
+ break;
844
+ }
845
+ if (inserted)
846
+ ob.observeArray(inserted);
847
+ // notify change
848
+ {
849
+ ob.dep.notify({
850
+ type: "array mutation" /* TriggerOpTypes.ARRAY_MUTATION */,
851
+ target: this,
852
+ key: method
853
+ });
854
+ }
855
+ return result;
856
+ });
857
+ });
858
+
859
+ var arrayKeys = Object.getOwnPropertyNames(arrayMethods);
860
+ var NO_INIITIAL_VALUE = {};
861
+ /**
862
+ * In some cases we may want to disable observation inside a component's
863
+ * update computation.
864
+ */
865
+ var shouldObserve = true;
866
+ function toggleObserving(value) {
867
+ shouldObserve = value;
868
+ }
869
+ // ssr mock dep
870
+ var mockDep = {
871
+ notify: noop,
872
+ depend: noop,
873
+ addSub: noop,
874
+ removeSub: noop
875
+ };
876
+ /**
877
+ * Observer class that is attached to each observed
878
+ * object. Once attached, the observer converts the target
879
+ * object's property keys into getter/setters that
880
+ * collect dependencies and dispatch updates.
881
+ */
882
+ var Observer = /** @class */ (function () {
883
+ function Observer(value, shallow, mock) {
884
+ if (shallow === void 0) { shallow = false; }
885
+ if (mock === void 0) { mock = false; }
886
+ this.value = value;
887
+ this.shallow = shallow;
888
+ this.mock = mock;
889
+ // this.value = value
890
+ this.dep = mock ? mockDep : new Dep();
891
+ this.vmCount = 0;
892
+ def(value, '__ob__', this);
893
+ if (isArray(value)) {
894
+ if (!mock) {
895
+ if (hasProto) {
896
+ value.__proto__ = arrayMethods;
897
+ /* eslint-enable no-proto */
898
+ }
899
+ else {
900
+ for (var i = 0, l = arrayKeys.length; i < l; i++) {
901
+ var key = arrayKeys[i];
902
+ def(value, key, arrayMethods[key]);
903
+ }
904
+ }
905
+ }
906
+ if (!shallow) {
907
+ this.observeArray(value);
908
+ }
909
+ }
910
+ else {
911
+ /**
912
+ * Walk through all properties and convert them into
913
+ * getter/setters. This method should only be called when
914
+ * value type is Object.
915
+ */
916
+ var keys = Object.keys(value);
917
+ for (var i = 0; i < keys.length; i++) {
918
+ var key = keys[i];
919
+ defineReactive(value, key, NO_INIITIAL_VALUE, undefined, shallow, mock);
920
+ }
921
+ }
922
+ }
923
+ /**
924
+ * Observe a list of Array items.
925
+ */
926
+ Observer.prototype.observeArray = function (value) {
927
+ for (var i = 0, l = value.length; i < l; i++) {
928
+ observe(value[i], false, this.mock);
929
+ }
930
+ };
931
+ return Observer;
932
+ }());
933
+ // helpers
934
+ /**
935
+ * Attempt to create an observer instance for a value,
936
+ * returns the new observer if successfully observed,
937
+ * or the existing observer if the value already has one.
938
+ */
939
+ function observe(value, shallow, ssrMockReactivity) {
940
+ if (!isObject(value) || isRef(value) || value instanceof VNode) {
941
+ return;
942
+ }
943
+ var ob;
944
+ if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {
945
+ ob = value.__ob__;
946
+ }
947
+ else if (shouldObserve &&
948
+ (ssrMockReactivity || !isServerRendering()) &&
949
+ (isArray(value) || isPlainObject(value)) &&
950
+ Object.isExtensible(value) &&
951
+ !value.__v_skip /* ReactiveFlags.SKIP */) {
952
+ ob = new Observer(value, shallow, ssrMockReactivity);
953
+ }
954
+ return ob;
955
+ }
956
+ /**
957
+ * Define a reactive property on an Object.
958
+ */
959
+ function defineReactive(obj, key, val, customSetter, shallow, mock) {
960
+ var dep = new Dep();
961
+ var property = Object.getOwnPropertyDescriptor(obj, key);
962
+ if (property && property.configurable === false) {
963
+ return;
964
+ }
965
+ // cater for pre-defined getter/setters
966
+ var getter = property && property.get;
967
+ var setter = property && property.set;
968
+ if ((!getter || setter) &&
969
+ (val === NO_INIITIAL_VALUE || arguments.length === 2)) {
970
+ val = obj[key];
971
+ }
972
+ var childOb = !shallow && observe(val, false, mock);
973
+ Object.defineProperty(obj, key, {
974
+ enumerable: true,
975
+ configurable: true,
976
+ get: function reactiveGetter() {
977
+ var value = getter ? getter.call(obj) : val;
978
+ if (Dep.target) {
979
+ {
980
+ dep.depend({
981
+ target: obj,
982
+ type: "get" /* TrackOpTypes.GET */,
983
+ key: key
984
+ });
985
+ }
986
+ if (childOb) {
987
+ childOb.dep.depend();
988
+ if (isArray(value)) {
989
+ dependArray(value);
990
+ }
991
+ }
992
+ }
993
+ return isRef(value) && !shallow ? value.value : value;
994
+ },
995
+ set: function reactiveSetter(newVal) {
996
+ var value = getter ? getter.call(obj) : val;
997
+ if (!hasChanged(value, newVal)) {
998
+ return;
999
+ }
1000
+ if (customSetter) {
1001
+ customSetter();
1002
+ }
1003
+ if (setter) {
1004
+ setter.call(obj, newVal);
1005
+ }
1006
+ else if (getter) {
1007
+ // #7981: for accessor properties without setter
1008
+ return;
1009
+ }
1010
+ else if (!shallow && isRef(value) && !isRef(newVal)) {
1011
+ value.value = newVal;
1012
+ return;
1013
+ }
1014
+ else {
1015
+ val = newVal;
1016
+ }
1017
+ childOb = !shallow && observe(newVal, false, mock);
1018
+ {
1019
+ dep.notify({
1020
+ type: "set" /* TriggerOpTypes.SET */,
1021
+ target: obj,
1022
+ key: key,
1023
+ newValue: newVal,
1024
+ oldValue: value
1025
+ });
1026
+ }
1027
+ }
1028
+ });
1029
+ return dep;
1030
+ }
1031
+ function set(target, key, val) {
1032
+ if ((isUndef(target) || isPrimitive(target))) {
1033
+ warn$2("Cannot set reactive property on undefined, null, or primitive value: ".concat(target));
1034
+ }
1035
+ if (isReadonly(target)) {
1036
+ warn$2("Set operation on key \"".concat(key, "\" failed: target is readonly."));
1037
+ return;
1038
+ }
1039
+ var ob = target.__ob__;
1040
+ if (isArray(target) && isValidArrayIndex(key)) {
1041
+ target.length = Math.max(target.length, key);
1042
+ target.splice(key, 1, val);
1043
+ // when mocking for SSR, array methods are not hijacked
1044
+ if (ob && !ob.shallow && ob.mock) {
1045
+ observe(val, false, true);
1046
+ }
1047
+ return val;
1048
+ }
1049
+ if (key in target && !(key in Object.prototype)) {
1050
+ target[key] = val;
1051
+ return val;
1052
+ }
1053
+ if (target._isVue || (ob && ob.vmCount)) {
1054
+ warn$2('Avoid adding reactive properties to a Vue instance or its root $data ' +
1055
+ 'at runtime - declare it upfront in the data option.');
1056
+ return val;
1057
+ }
1058
+ if (!ob) {
1059
+ target[key] = val;
1060
+ return val;
1061
+ }
1062
+ defineReactive(ob.value, key, val, undefined, ob.shallow, ob.mock);
1063
+ {
1064
+ ob.dep.notify({
1065
+ type: "add" /* TriggerOpTypes.ADD */,
1066
+ target: target,
1067
+ key: key,
1068
+ newValue: val,
1069
+ oldValue: undefined
1070
+ });
1071
+ }
1072
+ return val;
1073
+ }
1074
+ function del(target, key) {
1075
+ if ((isUndef(target) || isPrimitive(target))) {
1076
+ warn$2("Cannot delete reactive property on undefined, null, or primitive value: ".concat(target));
1077
+ }
1078
+ if (isArray(target) && isValidArrayIndex(key)) {
1079
+ target.splice(key, 1);
1080
+ return;
1081
+ }
1082
+ var ob = target.__ob__;
1083
+ if (target._isVue || (ob && ob.vmCount)) {
1084
+ warn$2('Avoid deleting properties on a Vue instance or its root $data ' +
1085
+ '- just set it to null.');
1086
+ return;
1087
+ }
1088
+ if (isReadonly(target)) {
1089
+ warn$2("Delete operation on key \"".concat(key, "\" failed: target is readonly."));
1090
+ return;
1091
+ }
1092
+ if (!hasOwn(target, key)) {
1093
+ return;
1094
+ }
1095
+ delete target[key];
1096
+ if (!ob) {
1097
+ return;
1098
+ }
1099
+ {
1100
+ ob.dep.notify({
1101
+ type: "delete" /* TriggerOpTypes.DELETE */,
1102
+ target: target,
1103
+ key: key
1104
+ });
1105
+ }
1106
+ }
1107
+ /**
1108
+ * Collect dependencies on array elements when the array is touched, since
1109
+ * we cannot intercept array element access like property getters.
1110
+ */
1111
+ function dependArray(value) {
1112
+ for (var e = void 0, i = 0, l = value.length; i < l; i++) {
1113
+ e = value[i];
1114
+ if (e && e.__ob__) {
1115
+ e.__ob__.dep.depend();
1116
+ }
1117
+ if (isArray(e)) {
1118
+ dependArray(e);
1119
+ }
1120
+ }
1121
+ }
1122
+
1123
+ function reactive(target) {
1124
+ makeReactive(target, false);
1125
+ return target;
1126
+ }
1127
+ /**
1128
+ * Return a shallowly-reactive copy of the original object, where only the root
1129
+ * level properties are reactive. It also does not auto-unwrap refs (even at the
1130
+ * root level).
1131
+ */
1132
+ function shallowReactive(target) {
1133
+ makeReactive(target, true);
1134
+ def(target, "__v_isShallow" /* ReactiveFlags.IS_SHALLOW */, true);
1135
+ return target;
1136
+ }
1137
+ function makeReactive(target, shallow) {
1138
+ // if trying to observe a readonly proxy, return the readonly version.
1139
+ if (!isReadonly(target)) {
1140
+ {
1141
+ if (isArray(target)) {
1142
+ warn$2("Avoid using Array as root value for ".concat(shallow ? "shallowReactive()" : "reactive()", " as it cannot be tracked in watch() or watchEffect(). Use ").concat(shallow ? "shallowRef()" : "ref()", " instead. This is a Vue-2-only limitation."));
1143
+ }
1144
+ var existingOb = target && target.__ob__;
1145
+ if (existingOb && existingOb.shallow !== shallow) {
1146
+ warn$2("Target is already a ".concat(existingOb.shallow ? "" : "non-", "shallow reactive object, and cannot be converted to ").concat(shallow ? "" : "non-", "shallow."));
1147
+ }
1148
+ }
1149
+ var ob = observe(target, shallow, isServerRendering() /* ssr mock reactivity */);
1150
+ if (!ob) {
1151
+ if (target == null || isPrimitive(target)) {
1152
+ warn$2("value cannot be made reactive: ".concat(String(target)));
1153
+ }
1154
+ if (isCollectionType(target)) {
1155
+ warn$2("Vue 2 does not support reactive collection types such as Map or Set.");
1156
+ }
1157
+ }
1158
+ }
1159
+ }
1160
+ function isReactive(value) {
1161
+ if (isReadonly(value)) {
1162
+ return isReactive(value["__v_raw" /* ReactiveFlags.RAW */]);
1163
+ }
1164
+ return !!(value && value.__ob__);
1165
+ }
1166
+ function isShallow(value) {
1167
+ return !!(value && value.__v_isShallow);
1168
+ }
1169
+ function isReadonly(value) {
1170
+ return !!(value && value.__v_isReadonly);
1171
+ }
1172
+ function isProxy(value) {
1173
+ return isReactive(value) || isReadonly(value);
1174
+ }
1175
+ function toRaw(observed) {
1176
+ var raw = observed && observed["__v_raw" /* ReactiveFlags.RAW */];
1177
+ return raw ? toRaw(raw) : observed;
1178
+ }
1179
+ function markRaw(value) {
1180
+ def(value, "__v_skip" /* ReactiveFlags.SKIP */, true);
1181
+ return value;
1182
+ }
1183
+ /**
1184
+ * @internal
1185
+ */
1186
+ function isCollectionType(value) {
1187
+ var type = toRawType(value);
1188
+ return (type === 'Map' || type === 'WeakMap' || type === 'Set' || type === 'WeakSet');
1189
+ }
1190
+
1191
+ /**
1192
+ * @internal
1193
+ */
1194
+ var RefFlag = "__v_isRef";
1195
+ function isRef(r) {
1196
+ return !!(r && r.__v_isRef === true);
1197
+ }
1198
+ function ref$1(value) {
1199
+ return createRef(value, false);
1200
+ }
1201
+ function shallowRef(value) {
1202
+ return createRef(value, true);
1203
+ }
1204
+ function createRef(rawValue, shallow) {
1205
+ if (isRef(rawValue)) {
1206
+ return rawValue;
1207
+ }
1208
+ var ref = {};
1209
+ def(ref, RefFlag, true);
1210
+ def(ref, "__v_isShallow" /* ReactiveFlags.IS_SHALLOW */, shallow);
1211
+ def(ref, 'dep', defineReactive(ref, 'value', rawValue, null, shallow, isServerRendering()));
1212
+ return ref;
1213
+ }
1214
+ function triggerRef(ref) {
1215
+ if (!ref.dep) {
1216
+ warn$2("received object is not a triggerable ref.");
1217
+ }
1218
+ {
1219
+ ref.dep &&
1220
+ ref.dep.notify({
1221
+ type: "set" /* TriggerOpTypes.SET */,
1222
+ target: ref,
1223
+ key: 'value'
1224
+ });
1225
+ }
1226
+ }
1227
+ function unref(ref) {
1228
+ return isRef(ref) ? ref.value : ref;
1229
+ }
1230
+ function proxyRefs(objectWithRefs) {
1231
+ if (isReactive(objectWithRefs)) {
1232
+ return objectWithRefs;
1233
+ }
1234
+ var proxy = {};
1235
+ var keys = Object.keys(objectWithRefs);
1236
+ for (var i = 0; i < keys.length; i++) {
1237
+ proxyWithRefUnwrap(proxy, objectWithRefs, keys[i]);
1238
+ }
1239
+ return proxy;
1240
+ }
1241
+ function proxyWithRefUnwrap(target, source, key) {
1242
+ Object.defineProperty(target, key, {
1243
+ enumerable: true,
1244
+ configurable: true,
1245
+ get: function () {
1246
+ var val = source[key];
1247
+ if (isRef(val)) {
1248
+ return val.value;
1249
+ }
1250
+ else {
1251
+ var ob = val && val.__ob__;
1252
+ if (ob)
1253
+ ob.dep.depend();
1254
+ return val;
1255
+ }
1256
+ },
1257
+ set: function (value) {
1258
+ var oldValue = source[key];
1259
+ if (isRef(oldValue) && !isRef(value)) {
1260
+ oldValue.value = value;
1261
+ }
1262
+ else {
1263
+ source[key] = value;
1264
+ }
1265
+ }
1266
+ });
1267
+ }
1268
+ function customRef(factory) {
1269
+ var dep = new Dep();
1270
+ var _a = factory(function () {
1271
+ {
1272
+ dep.depend({
1273
+ target: ref,
1274
+ type: "get" /* TrackOpTypes.GET */,
1275
+ key: 'value'
1276
+ });
1277
+ }
1278
+ }, function () {
1279
+ {
1280
+ dep.notify({
1281
+ target: ref,
1282
+ type: "set" /* TriggerOpTypes.SET */,
1283
+ key: 'value'
1284
+ });
1285
+ }
1286
+ }), get = _a.get, set = _a.set;
1287
+ var ref = {
1288
+ get value() {
1289
+ return get();
1290
+ },
1291
+ set value(newVal) {
1292
+ set(newVal);
1293
+ }
1294
+ };
1295
+ def(ref, RefFlag, true);
1296
+ return ref;
1297
+ }
1298
+ function toRefs(object) {
1299
+ if (!isReactive(object)) {
1300
+ warn$2("toRefs() expects a reactive object but received a plain one.");
1301
+ }
1302
+ var ret = isArray(object) ? new Array(object.length) : {};
1303
+ for (var key in object) {
1304
+ ret[key] = toRef(object, key);
1305
+ }
1306
+ return ret;
1307
+ }
1308
+ function toRef(object, key, defaultValue) {
1309
+ var val = object[key];
1310
+ if (isRef(val)) {
1311
+ return val;
1312
+ }
1313
+ var ref = {
1314
+ get value() {
1315
+ var val = object[key];
1316
+ return val === undefined ? defaultValue : val;
1317
+ },
1318
+ set value(newVal) {
1319
+ object[key] = newVal;
1320
+ }
1321
+ };
1322
+ def(ref, RefFlag, true);
1323
+ return ref;
1324
+ }
1325
+
1326
+ var rawToReadonlyFlag = "__v_rawToReadonly";
1327
+ var rawToShallowReadonlyFlag = "__v_rawToShallowReadonly";
1328
+ function readonly(target) {
1329
+ return createReadonly(target, false);
1330
+ }
1331
+ function createReadonly(target, shallow) {
1332
+ if (!isPlainObject(target)) {
1333
+ {
1334
+ if (isArray(target)) {
1335
+ warn$2("Vue 2 does not support readonly arrays.");
1336
+ }
1337
+ else if (isCollectionType(target)) {
1338
+ warn$2("Vue 2 does not support readonly collection types such as Map or Set.");
1339
+ }
1340
+ else {
1341
+ warn$2("value cannot be made readonly: ".concat(typeof target));
1342
+ }
1343
+ }
1344
+ return target;
1345
+ }
1346
+ // already a readonly object
1347
+ if (isReadonly(target)) {
1348
+ return target;
1349
+ }
1350
+ // already has a readonly proxy
1351
+ var existingFlag = shallow ? rawToShallowReadonlyFlag : rawToReadonlyFlag;
1352
+ var existingProxy = target[existingFlag];
1353
+ if (existingProxy) {
1354
+ return existingProxy;
1355
+ }
1356
+ var proxy = Object.create(Object.getPrototypeOf(target));
1357
+ def(target, existingFlag, proxy);
1358
+ def(proxy, "__v_isReadonly" /* ReactiveFlags.IS_READONLY */, true);
1359
+ def(proxy, "__v_raw" /* ReactiveFlags.RAW */, target);
1360
+ if (isRef(target)) {
1361
+ def(proxy, RefFlag, true);
1362
+ }
1363
+ if (shallow || isShallow(target)) {
1364
+ def(proxy, "__v_isShallow" /* ReactiveFlags.IS_SHALLOW */, true);
1365
+ }
1366
+ var keys = Object.keys(target);
1367
+ for (var i = 0; i < keys.length; i++) {
1368
+ defineReadonlyProperty(proxy, target, keys[i], shallow);
1369
+ }
1370
+ return proxy;
1371
+ }
1372
+ function defineReadonlyProperty(proxy, target, key, shallow) {
1373
+ Object.defineProperty(proxy, key, {
1374
+ enumerable: true,
1375
+ configurable: true,
1376
+ get: function () {
1377
+ var val = target[key];
1378
+ return shallow || !isPlainObject(val) ? val : readonly(val);
1379
+ },
1380
+ set: function () {
1381
+ warn$2("Set operation on key \"".concat(key, "\" failed: target is readonly."));
1382
+ }
1383
+ });
1384
+ }
1385
+ /**
1386
+ * Returns a reactive-copy of the original object, where only the root level
1387
+ * properties are readonly, and does NOT unwrap refs nor recursively convert
1388
+ * returned properties.
1389
+ * This is used for creating the props proxy object for stateful components.
1390
+ */
1391
+ function shallowReadonly(target) {
1392
+ return createReadonly(target, true);
1393
+ }
1394
+
1395
+ function computed(getterOrOptions, debugOptions) {
1396
+ var getter;
1397
+ var setter;
1398
+ var onlyGetter = isFunction(getterOrOptions);
1399
+ if (onlyGetter) {
1400
+ getter = getterOrOptions;
1401
+ setter = function () {
1402
+ warn$2('Write operation failed: computed value is readonly');
1403
+ }
1404
+ ;
1405
+ }
1406
+ else {
1407
+ getter = getterOrOptions.get;
1408
+ setter = getterOrOptions.set;
1409
+ }
1410
+ var watcher = isServerRendering()
1411
+ ? null
1412
+ : new Watcher(currentInstance, getter, noop, { lazy: true });
1413
+ if (watcher && debugOptions) {
1414
+ watcher.onTrack = debugOptions.onTrack;
1415
+ watcher.onTrigger = debugOptions.onTrigger;
1416
+ }
1417
+ var ref = {
1418
+ // some libs rely on the presence effect for checking computed refs
1419
+ // from normal refs, but the implementation doesn't matter
1420
+ effect: watcher,
1421
+ get value() {
1422
+ if (watcher) {
1423
+ if (watcher.dirty) {
1424
+ watcher.evaluate();
1425
+ }
1426
+ if (Dep.target) {
1427
+ if (Dep.target.onTrack) {
1428
+ Dep.target.onTrack({
1429
+ effect: Dep.target,
1430
+ target: ref,
1431
+ type: "get" /* TrackOpTypes.GET */,
1432
+ key: 'value'
1433
+ });
1434
+ }
1435
+ watcher.depend();
1436
+ }
1437
+ return watcher.value;
1438
+ }
1439
+ else {
1440
+ return getter();
1441
+ }
1442
+ },
1443
+ set value(newVal) {
1444
+ setter(newVal);
1445
+ }
1446
+ };
1447
+ def(ref, RefFlag, true);
1448
+ def(ref, "__v_isReadonly" /* ReactiveFlags.IS_READONLY */, onlyGetter);
1449
+ return ref;
1450
+ }
1451
+
1452
+ var mark;
1453
+ var measure;
1454
+ {
1455
+ var perf_1 = inBrowser && window.performance;
1456
+ /* istanbul ignore if */
1457
+ if (perf_1 &&
1458
+ // @ts-ignore
1459
+ perf_1.mark &&
1460
+ // @ts-ignore
1461
+ perf_1.measure &&
1462
+ // @ts-ignore
1463
+ perf_1.clearMarks &&
1464
+ // @ts-ignore
1465
+ perf_1.clearMeasures) {
1466
+ mark = function (tag) { return perf_1.mark(tag); };
1467
+ measure = function (name, startTag, endTag) {
1468
+ perf_1.measure(name, startTag, endTag);
1469
+ perf_1.clearMarks(startTag);
1470
+ perf_1.clearMarks(endTag);
1471
+ // perf.clearMeasures(name)
1472
+ };
1473
+ }
1474
+ }
1475
+
1476
+ var normalizeEvent = cached(function (name) {
1477
+ var passive = name.charAt(0) === '&';
1478
+ name = passive ? name.slice(1) : name;
1479
+ var once = name.charAt(0) === '~'; // Prefixed last, checked first
1480
+ name = once ? name.slice(1) : name;
1481
+ var capture = name.charAt(0) === '!';
1482
+ name = capture ? name.slice(1) : name;
1483
+ return {
1484
+ name: name,
1485
+ once: once,
1486
+ capture: capture,
1487
+ passive: passive
1488
+ };
1489
+ });
1490
+ function createFnInvoker(fns, vm) {
1491
+ function invoker() {
1492
+ var fns = invoker.fns;
1493
+ if (isArray(fns)) {
1494
+ var cloned = fns.slice();
1495
+ for (var i = 0; i < cloned.length; i++) {
1496
+ invokeWithErrorHandling(cloned[i], null, arguments, vm, "v-on handler");
1497
+ }
1498
+ }
1499
+ else {
1500
+ // return handler return value for single handlers
1501
+ return invokeWithErrorHandling(fns, null, arguments, vm, "v-on handler");
1502
+ }
1503
+ }
1504
+ invoker.fns = fns;
1505
+ return invoker;
1506
+ }
1507
+ function updateListeners(on, oldOn, add, remove, createOnceHandler, vm) {
1508
+ var name, cur, old, event;
1509
+ for (name in on) {
1510
+ cur = on[name];
1511
+ old = oldOn[name];
1512
+ event = normalizeEvent(name);
1513
+ if (isUndef(cur)) {
1514
+ warn$2("Invalid handler for event \"".concat(event.name, "\": got ") + String(cur), vm);
1515
+ }
1516
+ else if (isUndef(old)) {
1517
+ if (isUndef(cur.fns)) {
1518
+ cur = on[name] = createFnInvoker(cur, vm);
1519
+ }
1520
+ if (isTrue(event.once)) {
1521
+ cur = on[name] = createOnceHandler(event.name, cur, event.capture);
1522
+ }
1523
+ add(event.name, cur, event.capture, event.passive, event.params);
1524
+ }
1525
+ else if (cur !== old) {
1526
+ old.fns = cur;
1527
+ on[name] = old;
1528
+ }
1529
+ }
1530
+ for (name in oldOn) {
1531
+ if (isUndef(on[name])) {
1532
+ event = normalizeEvent(name);
1533
+ remove(event.name, oldOn[name], event.capture);
1534
+ }
1535
+ }
1536
+ }
1537
+
1538
+ function mergeVNodeHook(def, hookKey, hook) {
1539
+ if (def instanceof VNode) {
1540
+ def = def.data.hook || (def.data.hook = {});
1541
+ }
1542
+ var invoker;
1543
+ var oldHook = def[hookKey];
1544
+ function wrappedHook() {
1545
+ hook.apply(this, arguments);
1546
+ // important: remove merged hook to ensure it's called only once
1547
+ // and prevent memory leak
1548
+ remove$2(invoker.fns, wrappedHook);
1549
+ }
1550
+ if (isUndef(oldHook)) {
1551
+ // no existing hook
1552
+ invoker = createFnInvoker([wrappedHook]);
1553
+ }
1554
+ else {
1555
+ /* istanbul ignore if */
1556
+ if (isDef(oldHook.fns) && isTrue(oldHook.merged)) {
1557
+ // already a merged invoker
1558
+ invoker = oldHook;
1559
+ invoker.fns.push(wrappedHook);
1560
+ }
1561
+ else {
1562
+ // existing plain hook
1563
+ invoker = createFnInvoker([oldHook, wrappedHook]);
1564
+ }
1565
+ }
1566
+ invoker.merged = true;
1567
+ def[hookKey] = invoker;
1568
+ }
1569
+
1570
+ function extractPropsFromVNodeData(data, Ctor, tag) {
1571
+ // we are only extracting raw values here.
1572
+ // validation and default values are handled in the child
1573
+ // component itself.
1574
+ var propOptions = Ctor.options.props;
1575
+ if (isUndef(propOptions)) {
1576
+ return;
1577
+ }
1578
+ var res = {};
1579
+ var attrs = data.attrs, props = data.props;
1580
+ if (isDef(attrs) || isDef(props)) {
1581
+ for (var key in propOptions) {
1582
+ var altKey = hyphenate(key);
1583
+ {
1584
+ var keyInLowerCase = key.toLowerCase();
1585
+ if (key !== keyInLowerCase && attrs && hasOwn(attrs, keyInLowerCase)) {
1586
+ tip("Prop \"".concat(keyInLowerCase, "\" is passed to component ") +
1587
+ "".concat(formatComponentName(
1588
+ // @ts-expect-error tag is string
1589
+ tag || Ctor), ", but the declared prop name is") +
1590
+ " \"".concat(key, "\". ") +
1591
+ "Note that HTML attributes are case-insensitive and camelCased " +
1592
+ "props need to use their kebab-case equivalents when using in-DOM " +
1593
+ "templates. You should probably use \"".concat(altKey, "\" instead of \"").concat(key, "\"."));
1594
+ }
1595
+ }
1596
+ checkProp(res, props, key, altKey, true) ||
1597
+ checkProp(res, attrs, key, altKey, false);
1598
+ }
1599
+ }
1600
+ return res;
1601
+ }
1602
+ function checkProp(res, hash, key, altKey, preserve) {
1603
+ if (isDef(hash)) {
1604
+ if (hasOwn(hash, key)) {
1605
+ res[key] = hash[key];
1606
+ if (!preserve) {
1607
+ delete hash[key];
1608
+ }
1609
+ return true;
1610
+ }
1611
+ else if (hasOwn(hash, altKey)) {
1612
+ res[key] = hash[altKey];
1613
+ if (!preserve) {
1614
+ delete hash[altKey];
1615
+ }
1616
+ return true;
1617
+ }
1618
+ }
1619
+ return false;
1620
+ }
1621
+
1622
+ // The template compiler attempts to minimize the need for normalization by
1623
+ // statically analyzing the template at compile time.
1624
+ //
1625
+ // For plain HTML markup, normalization can be completely skipped because the
1626
+ // generated render function is guaranteed to return Array<VNode>. There are
1627
+ // two cases where extra normalization is needed:
1628
+ // 1. When the children contains components - because a functional component
1629
+ // may return an Array instead of a single root. In this case, just a simple
1630
+ // normalization is needed - if any child is an Array, we flatten the whole
1631
+ // thing with Array.prototype.concat. It is guaranteed to be only 1-level deep
1632
+ // because functional components already normalize their own children.
1633
+ function simpleNormalizeChildren(children) {
1634
+ for (var i = 0; i < children.length; i++) {
1635
+ if (isArray(children[i])) {
1636
+ return Array.prototype.concat.apply([], children);
1637
+ }
1638
+ }
1639
+ return children;
1640
+ }
1641
+ // 2. When the children contains constructs that always generated nested Arrays,
1642
+ // e.g. <template>, <slot>, v-for, or when the children is provided by user
1643
+ // with hand-written render functions / JSX. In such cases a full normalization
1644
+ // is needed to cater to all possible types of children values.
1645
+ function normalizeChildren(children) {
1646
+ return isPrimitive(children)
1647
+ ? [createTextVNode(children)]
1648
+ : isArray(children)
1649
+ ? normalizeArrayChildren(children)
1650
+ : undefined;
1651
+ }
1652
+ function isTextNode(node) {
1653
+ return isDef(node) && isDef(node.text) && isFalse(node.isComment);
1654
+ }
1655
+ function normalizeArrayChildren(children, nestedIndex) {
1656
+ var res = [];
1657
+ var i, c, lastIndex, last;
1658
+ for (i = 0; i < children.length; i++) {
1659
+ c = children[i];
1660
+ if (isUndef(c) || typeof c === 'boolean')
1661
+ continue;
1662
+ lastIndex = res.length - 1;
1663
+ last = res[lastIndex];
1664
+ // nested
1665
+ if (isArray(c)) {
1666
+ if (c.length > 0) {
1667
+ c = normalizeArrayChildren(c, "".concat(nestedIndex || '', "_").concat(i));
1668
+ // merge adjacent text nodes
1669
+ if (isTextNode(c[0]) && isTextNode(last)) {
1670
+ res[lastIndex] = createTextVNode(last.text + c[0].text);
1671
+ c.shift();
1672
+ }
1673
+ res.push.apply(res, c);
1674
+ }
1675
+ }
1676
+ else if (isPrimitive(c)) {
1677
+ if (isTextNode(last)) {
1678
+ // merge adjacent text nodes
1679
+ // this is necessary for SSR hydration because text nodes are
1680
+ // essentially merged when rendered to HTML strings
1681
+ res[lastIndex] = createTextVNode(last.text + c);
1682
+ }
1683
+ else if (c !== '') {
1684
+ // convert primitive to vnode
1685
+ res.push(createTextVNode(c));
1686
+ }
1687
+ }
1688
+ else {
1689
+ if (isTextNode(c) && isTextNode(last)) {
1690
+ // merge adjacent text nodes
1691
+ res[lastIndex] = createTextVNode(last.text + c.text);
1692
+ }
1693
+ else {
1694
+ // default key for nested array children (likely generated by v-for)
1695
+ if (isTrue(children._isVList) &&
1696
+ isDef(c.tag) &&
1697
+ isUndef(c.key) &&
1698
+ isDef(nestedIndex)) {
1699
+ c.key = "__vlist".concat(nestedIndex, "_").concat(i, "__");
1700
+ }
1701
+ res.push(c);
1702
+ }
1703
+ }
1704
+ }
1705
+ return res;
1706
+ }
1707
+
1708
+ var SIMPLE_NORMALIZE = 1;
1709
+ var ALWAYS_NORMALIZE = 2;
1710
+ // wrapper function for providing a more flexible interface
1711
+ // without getting yelled at by flow
1712
+ function createElement$1(context, tag, data, children, normalizationType, alwaysNormalize) {
1713
+ if (isArray(data) || isPrimitive(data)) {
1714
+ normalizationType = children;
1715
+ children = data;
1716
+ data = undefined;
1717
+ }
1718
+ if (isTrue(alwaysNormalize)) {
1719
+ normalizationType = ALWAYS_NORMALIZE;
1720
+ }
1721
+ return _createElement(context, tag, data, children, normalizationType);
1722
+ }
1723
+ function _createElement(context, tag, data, children, normalizationType) {
1724
+ if (isDef(data) && isDef(data.__ob__)) {
1725
+ warn$2("Avoid using observed data object as vnode data: ".concat(JSON.stringify(data), "\n") + 'Always create fresh vnode data objects in each render!', context);
1726
+ return createEmptyVNode();
1727
+ }
1728
+ // object syntax in v-bind
1729
+ if (isDef(data) && isDef(data.is)) {
1730
+ tag = data.is;
1731
+ }
1732
+ if (!tag) {
1733
+ // in case of component :is set to falsy value
1734
+ return createEmptyVNode();
1735
+ }
1736
+ // warn against non-primitive key
1737
+ if (isDef(data) && isDef(data.key) && !isPrimitive(data.key)) {
1738
+ warn$2('Avoid using non-primitive value as key, ' +
1739
+ 'use string/number value instead.', context);
1740
+ }
1741
+ // support single function children as default scoped slot
1742
+ if (isArray(children) && isFunction(children[0])) {
1743
+ data = data || {};
1744
+ data.scopedSlots = { default: children[0] };
1745
+ children.length = 0;
1746
+ }
1747
+ if (normalizationType === ALWAYS_NORMALIZE) {
1748
+ children = normalizeChildren(children);
1749
+ }
1750
+ else if (normalizationType === SIMPLE_NORMALIZE) {
1751
+ children = simpleNormalizeChildren(children);
1752
+ }
1753
+ var vnode, ns;
1754
+ if (typeof tag === 'string') {
1755
+ var Ctor = void 0;
1756
+ ns = (context.$vnode && context.$vnode.ns) || config.getTagNamespace(tag);
1757
+ if (config.isReservedTag(tag)) {
1758
+ // platform built-in elements
1759
+ if (isDef(data) &&
1760
+ isDef(data.nativeOn) &&
1761
+ data.tag !== 'component') {
1762
+ warn$2("The .native modifier for v-on is only valid on components but it was used on <".concat(tag, ">."), context);
1763
+ }
1764
+ vnode = new VNode(config.parsePlatformTagName(tag), data, children, undefined, undefined, context);
1765
+ }
1766
+ else if ((!data || !data.pre) &&
1767
+ isDef((Ctor = resolveAsset(context.$options, 'components', tag)))) {
1768
+ // component
1769
+ vnode = createComponent(Ctor, data, context, children, tag);
1770
+ }
1771
+ else {
1772
+ // unknown or unlisted namespaced elements
1773
+ // check at runtime because it may get assigned a namespace when its
1774
+ // parent normalizes children
1775
+ vnode = new VNode(tag, data, children, undefined, undefined, context);
1776
+ }
1777
+ }
1778
+ else {
1779
+ // direct component options / constructor
1780
+ vnode = createComponent(tag, data, context, children);
1781
+ }
1782
+ if (isArray(vnode)) {
1783
+ return vnode;
1784
+ }
1785
+ else if (isDef(vnode)) {
1786
+ if (isDef(ns))
1787
+ applyNS(vnode, ns);
1788
+ if (isDef(data))
1789
+ registerDeepBindings(data);
1790
+ return vnode;
1791
+ }
1792
+ else {
1793
+ return createEmptyVNode();
1794
+ }
1795
+ }
1796
+ function applyNS(vnode, ns, force) {
1797
+ vnode.ns = ns;
1798
+ if (vnode.tag === 'foreignObject') {
1799
+ // use default namespace inside foreignObject
1800
+ ns = undefined;
1801
+ force = true;
1802
+ }
1803
+ if (isDef(vnode.children)) {
1804
+ for (var i = 0, l = vnode.children.length; i < l; i++) {
1805
+ var child = vnode.children[i];
1806
+ if (isDef(child.tag) &&
1807
+ (isUndef(child.ns) || (isTrue(force) && child.tag !== 'svg'))) {
1808
+ applyNS(child, ns, force);
1809
+ }
1810
+ }
1811
+ }
1812
+ }
1813
+ // ref #5318
1814
+ // necessary to ensure parent re-render when deep bindings like :style and
1815
+ // :class are used on slot nodes
1816
+ function registerDeepBindings(data) {
1817
+ if (isObject(data.style)) {
1818
+ traverse(data.style);
1819
+ }
1820
+ if (isObject(data.class)) {
1821
+ traverse(data.class);
1822
+ }
1823
+ }
1824
+
1825
+ /**
1826
+ * Runtime helper for rendering v-for lists.
1827
+ */
1828
+ function renderList(val, render) {
1829
+ var ret = null, i, l, keys, key;
1830
+ if (isArray(val) || typeof val === 'string') {
1831
+ ret = new Array(val.length);
1832
+ for (i = 0, l = val.length; i < l; i++) {
1833
+ ret[i] = render(val[i], i);
1834
+ }
1835
+ }
1836
+ else if (typeof val === 'number') {
1837
+ ret = new Array(val);
1838
+ for (i = 0; i < val; i++) {
1839
+ ret[i] = render(i + 1, i);
1840
+ }
1841
+ }
1842
+ else if (isObject(val)) {
1843
+ if (hasSymbol && val[Symbol.iterator]) {
1844
+ ret = [];
1845
+ var iterator = val[Symbol.iterator]();
1846
+ var result = iterator.next();
1847
+ while (!result.done) {
1848
+ ret.push(render(result.value, ret.length));
1849
+ result = iterator.next();
1850
+ }
1851
+ }
1852
+ else {
1853
+ keys = Object.keys(val);
1854
+ ret = new Array(keys.length);
1855
+ for (i = 0, l = keys.length; i < l; i++) {
1856
+ key = keys[i];
1857
+ ret[i] = render(val[key], key, i);
1858
+ }
1859
+ }
1860
+ }
1861
+ if (!isDef(ret)) {
1862
+ ret = [];
1863
+ }
1864
+ ret._isVList = true;
1865
+ return ret;
1866
+ }
1867
+
1868
+ /**
1869
+ * Runtime helper for rendering <slot>
1870
+ */
1871
+ function renderSlot(name, fallbackRender, props, bindObject) {
1872
+ var scopedSlotFn = this.$scopedSlots[name];
1873
+ var nodes;
1874
+ if (scopedSlotFn) {
1875
+ // scoped slot
1876
+ props = props || {};
1877
+ if (bindObject) {
1878
+ if (!isObject(bindObject)) {
1879
+ warn$2('slot v-bind without argument expects an Object', this);
1880
+ }
1881
+ props = extend(extend({}, bindObject), props);
1882
+ }
1883
+ nodes =
1884
+ scopedSlotFn(props) ||
1885
+ (isFunction(fallbackRender) ? fallbackRender() : fallbackRender);
1886
+ }
1887
+ else {
1888
+ nodes =
1889
+ this.$slots[name] ||
1890
+ (isFunction(fallbackRender) ? fallbackRender() : fallbackRender);
1891
+ }
1892
+ var target = props && props.slot;
1893
+ if (target) {
1894
+ return this.$createElement('template', { slot: target }, nodes);
1895
+ }
1896
+ else {
1897
+ return nodes;
1898
+ }
1899
+ }
1900
+
1901
+ /**
1902
+ * Runtime helper for resolving filters
1903
+ */
1904
+ function resolveFilter(id) {
1905
+ return resolveAsset(this.$options, 'filters', id, true) || identity;
1906
+ }
1907
+
1908
+ function isKeyNotMatch(expect, actual) {
1909
+ if (isArray(expect)) {
1910
+ return expect.indexOf(actual) === -1;
1911
+ }
1912
+ else {
1913
+ return expect !== actual;
1914
+ }
1915
+ }
1916
+ /**
1917
+ * Runtime helper for checking keyCodes from config.
1918
+ * exposed as Vue.prototype._k
1919
+ * passing in eventKeyName as last argument separately for backwards compat
1920
+ */
1921
+ function checkKeyCodes(eventKeyCode, key, builtInKeyCode, eventKeyName, builtInKeyName) {
1922
+ var mappedKeyCode = config.keyCodes[key] || builtInKeyCode;
1923
+ if (builtInKeyName && eventKeyName && !config.keyCodes[key]) {
1924
+ return isKeyNotMatch(builtInKeyName, eventKeyName);
1925
+ }
1926
+ else if (mappedKeyCode) {
1927
+ return isKeyNotMatch(mappedKeyCode, eventKeyCode);
1928
+ }
1929
+ else if (eventKeyName) {
1930
+ return hyphenate(eventKeyName) !== key;
1931
+ }
1932
+ return eventKeyCode === undefined;
1933
+ }
1934
+
1935
+ /**
1936
+ * Runtime helper for merging v-bind="object" into a VNode's data.
1937
+ */
1938
+ function bindObjectProps(data, tag, value, asProp, isSync) {
1939
+ if (value) {
1940
+ if (!isObject(value)) {
1941
+ warn$2('v-bind without argument expects an Object or Array value', this);
1942
+ }
1943
+ else {
1944
+ if (isArray(value)) {
1945
+ value = toObject(value);
1946
+ }
1947
+ var hash = void 0;
1948
+ var _loop_1 = function (key) {
1949
+ if (key === 'class' || key === 'style' || isReservedAttribute(key)) {
1950
+ hash = data;
1951
+ }
1952
+ else {
1953
+ var type = data.attrs && data.attrs.type;
1954
+ hash =
1955
+ asProp || config.mustUseProp(tag, type, key)
1956
+ ? data.domProps || (data.domProps = {})
1957
+ : data.attrs || (data.attrs = {});
1958
+ }
1959
+ var camelizedKey = camelize(key);
1960
+ var hyphenatedKey = hyphenate(key);
1961
+ if (!(camelizedKey in hash) && !(hyphenatedKey in hash)) {
1962
+ hash[key] = value[key];
1963
+ if (isSync) {
1964
+ var on = data.on || (data.on = {});
1965
+ on["update:".concat(key)] = function ($event) {
1966
+ value[key] = $event;
1967
+ };
1968
+ }
1969
+ }
1970
+ };
1971
+ for (var key in value) {
1972
+ _loop_1(key);
1973
+ }
1974
+ }
1975
+ }
1976
+ return data;
1977
+ }
1978
+
1979
+ /**
1980
+ * Runtime helper for rendering static trees.
1981
+ */
1982
+ function renderStatic(index, isInFor) {
1983
+ var cached = this._staticTrees || (this._staticTrees = []);
1984
+ var tree = cached[index];
1985
+ // if has already-rendered static tree and not inside v-for,
1986
+ // we can reuse the same tree.
1987
+ if (tree && !isInFor) {
1988
+ return tree;
1989
+ }
1990
+ // otherwise, render a fresh tree.
1991
+ tree = cached[index] = this.$options.staticRenderFns[index].call(this._renderProxy, this._c, this // for render fns generated for functional component templates
1992
+ );
1993
+ markStatic$1(tree, "__static__".concat(index), false);
1994
+ return tree;
1995
+ }
1996
+ /**
1997
+ * Runtime helper for v-once.
1998
+ * Effectively it means marking the node as static with a unique key.
1999
+ */
2000
+ function markOnce(tree, index, key) {
2001
+ markStatic$1(tree, "__once__".concat(index).concat(key ? "_".concat(key) : ""), true);
2002
+ return tree;
2003
+ }
2004
+ function markStatic$1(tree, key, isOnce) {
2005
+ if (isArray(tree)) {
2006
+ for (var i = 0; i < tree.length; i++) {
2007
+ if (tree[i] && typeof tree[i] !== 'string') {
2008
+ markStaticNode(tree[i], "".concat(key, "_").concat(i), isOnce);
2009
+ }
2010
+ }
2011
+ }
2012
+ else {
2013
+ markStaticNode(tree, key, isOnce);
2014
+ }
2015
+ }
2016
+ function markStaticNode(node, key, isOnce) {
2017
+ node.isStatic = true;
2018
+ node.key = key;
2019
+ node.isOnce = isOnce;
2020
+ }
2021
+
2022
+ function bindObjectListeners(data, value) {
2023
+ if (value) {
2024
+ if (!isPlainObject(value)) {
2025
+ warn$2('v-on without argument expects an Object value', this);
2026
+ }
2027
+ else {
2028
+ var on = (data.on = data.on ? extend({}, data.on) : {});
2029
+ for (var key in value) {
2030
+ var existing = on[key];
2031
+ var ours = value[key];
2032
+ on[key] = existing ? [].concat(existing, ours) : ours;
2033
+ }
2034
+ }
2035
+ }
2036
+ return data;
2037
+ }
2038
+
2039
+ function resolveScopedSlots(fns, res,
2040
+ // the following are added in 2.6
2041
+ hasDynamicKeys, contentHashKey) {
2042
+ res = res || { $stable: !hasDynamicKeys };
2043
+ for (var i = 0; i < fns.length; i++) {
2044
+ var slot = fns[i];
2045
+ if (isArray(slot)) {
2046
+ resolveScopedSlots(slot, res, hasDynamicKeys);
2047
+ }
2048
+ else if (slot) {
2049
+ // marker for reverse proxying v-slot without scope on this.$slots
2050
+ // @ts-expect-error
2051
+ if (slot.proxy) {
2052
+ // @ts-expect-error
2053
+ slot.fn.proxy = true;
2054
+ }
2055
+ res[slot.key] = slot.fn;
2056
+ }
2057
+ }
2058
+ if (contentHashKey) {
2059
+ res.$key = contentHashKey;
2060
+ }
2061
+ return res;
2062
+ }
2063
+
2064
+ // helper to process dynamic keys for dynamic arguments in v-bind and v-on.
2065
+ function bindDynamicKeys(baseObj, values) {
2066
+ for (var i = 0; i < values.length; i += 2) {
2067
+ var key = values[i];
2068
+ if (typeof key === 'string' && key) {
2069
+ baseObj[values[i]] = values[i + 1];
2070
+ }
2071
+ else if (key !== '' && key !== null) {
2072
+ // null is a special value for explicitly removing a binding
2073
+ warn$2("Invalid value for dynamic directive argument (expected string or null): ".concat(key), this);
2074
+ }
2075
+ }
2076
+ return baseObj;
2077
+ }
2078
+ // helper to dynamically append modifier runtime markers to event names.
2079
+ // ensure only append when value is already string, otherwise it will be cast
2080
+ // to string and cause the type check to miss.
2081
+ function prependModifier(value, symbol) {
2082
+ return typeof value === 'string' ? symbol + value : value;
2083
+ }
2084
+
2085
+ function installRenderHelpers(target) {
2086
+ target._o = markOnce;
2087
+ target._n = toNumber;
2088
+ target._s = toString;
2089
+ target._l = renderList;
2090
+ target._t = renderSlot;
2091
+ target._q = looseEqual;
2092
+ target._i = looseIndexOf;
2093
+ target._m = renderStatic;
2094
+ target._f = resolveFilter;
2095
+ target._k = checkKeyCodes;
2096
+ target._b = bindObjectProps;
2097
+ target._v = createTextVNode;
2098
+ target._e = createEmptyVNode;
2099
+ target._u = resolveScopedSlots;
2100
+ target._g = bindObjectListeners;
2101
+ target._d = bindDynamicKeys;
2102
+ target._p = prependModifier;
2103
+ }
2104
+
2105
+ /**
2106
+ * Runtime helper for resolving raw children VNodes into a slot object.
2107
+ */
2108
+ function resolveSlots(children, context) {
2109
+ if (!children || !children.length) {
2110
+ return {};
2111
+ }
2112
+ var slots = {};
2113
+ for (var i = 0, l = children.length; i < l; i++) {
2114
+ var child = children[i];
2115
+ var data = child.data;
2116
+ // remove slot attribute if the node is resolved as a Vue slot node
2117
+ if (data && data.attrs && data.attrs.slot) {
2118
+ delete data.attrs.slot;
2119
+ }
2120
+ // named slots should only be respected if the vnode was rendered in the
2121
+ // same context.
2122
+ if ((child.context === context || child.fnContext === context) &&
2123
+ data &&
2124
+ data.slot != null) {
2125
+ var name_1 = data.slot;
2126
+ var slot = slots[name_1] || (slots[name_1] = []);
2127
+ if (child.tag === 'template') {
2128
+ slot.push.apply(slot, child.children || []);
2129
+ }
2130
+ else {
2131
+ slot.push(child);
2132
+ }
2133
+ }
2134
+ else {
2135
+ (slots.default || (slots.default = [])).push(child);
2136
+ }
2137
+ }
2138
+ // ignore slots that contains only whitespace
2139
+ for (var name_2 in slots) {
2140
+ if (slots[name_2].every(isWhitespace)) {
2141
+ delete slots[name_2];
2142
+ }
2143
+ }
2144
+ return slots;
2145
+ }
2146
+ function isWhitespace(node) {
2147
+ return (node.isComment && !node.asyncFactory) || node.text === ' ';
2148
+ }
2149
+
2150
+ function isAsyncPlaceholder(node) {
2151
+ // @ts-expect-error not really boolean type
2152
+ return node.isComment && node.asyncFactory;
2153
+ }
2154
+
2155
+ function normalizeScopedSlots(ownerVm, scopedSlots, normalSlots, prevScopedSlots) {
2156
+ var res;
2157
+ var hasNormalSlots = Object.keys(normalSlots).length > 0;
2158
+ var isStable = scopedSlots ? !!scopedSlots.$stable : !hasNormalSlots;
2159
+ var key = scopedSlots && scopedSlots.$key;
2160
+ if (!scopedSlots) {
2161
+ res = {};
2162
+ }
2163
+ else if (scopedSlots._normalized) {
2164
+ // fast path 1: child component re-render only, parent did not change
2165
+ return scopedSlots._normalized;
2166
+ }
2167
+ else if (isStable &&
2168
+ prevScopedSlots &&
2169
+ prevScopedSlots !== emptyObject &&
2170
+ key === prevScopedSlots.$key &&
2171
+ !hasNormalSlots &&
2172
+ !prevScopedSlots.$hasNormal) {
2173
+ // fast path 2: stable scoped slots w/ no normal slots to proxy,
2174
+ // only need to normalize once
2175
+ return prevScopedSlots;
2176
+ }
2177
+ else {
2178
+ res = {};
2179
+ for (var key_1 in scopedSlots) {
2180
+ if (scopedSlots[key_1] && key_1[0] !== '$') {
2181
+ res[key_1] = normalizeScopedSlot(ownerVm, normalSlots, key_1, scopedSlots[key_1]);
2182
+ }
2183
+ }
2184
+ }
2185
+ // expose normal slots on scopedSlots
2186
+ for (var key_2 in normalSlots) {
2187
+ if (!(key_2 in res)) {
2188
+ res[key_2] = proxyNormalSlot(normalSlots, key_2);
2189
+ }
2190
+ }
2191
+ // avoriaz seems to mock a non-extensible $scopedSlots object
2192
+ // and when that is passed down this would cause an error
2193
+ if (scopedSlots && Object.isExtensible(scopedSlots)) {
2194
+ scopedSlots._normalized = res;
2195
+ }
2196
+ def(res, '$stable', isStable);
2197
+ def(res, '$key', key);
2198
+ def(res, '$hasNormal', hasNormalSlots);
2199
+ return res;
2200
+ }
2201
+ function normalizeScopedSlot(vm, normalSlots, key, fn) {
2202
+ var normalized = function () {
2203
+ var cur = currentInstance;
2204
+ setCurrentInstance(vm);
2205
+ var res = arguments.length ? fn.apply(null, arguments) : fn({});
2206
+ res =
2207
+ res && typeof res === 'object' && !isArray(res)
2208
+ ? [res] // single vnode
2209
+ : normalizeChildren(res);
2210
+ var vnode = res && res[0];
2211
+ setCurrentInstance(cur);
2212
+ return res &&
2213
+ (!vnode ||
2214
+ (res.length === 1 && vnode.isComment && !isAsyncPlaceholder(vnode))) // #9658, #10391
2215
+ ? undefined
2216
+ : res;
2217
+ };
2218
+ // this is a slot using the new v-slot syntax without scope. although it is
2219
+ // compiled as a scoped slot, render fn users would expect it to be present
2220
+ // on this.$slots because the usage is semantically a normal slot.
2221
+ if (fn.proxy) {
2222
+ Object.defineProperty(normalSlots, key, {
2223
+ get: normalized,
2224
+ enumerable: true,
2225
+ configurable: true
2226
+ });
2227
+ }
2228
+ return normalized;
2229
+ }
2230
+ function proxyNormalSlot(slots, key) {
2231
+ return function () { return slots[key]; };
2232
+ }
2233
+
2234
+ function initSetup(vm) {
2235
+ var options = vm.$options;
2236
+ var setup = options.setup;
2237
+ if (setup) {
2238
+ var ctx = (vm._setupContext = createSetupContext(vm));
2239
+ setCurrentInstance(vm);
2240
+ pushTarget();
2241
+ var setupResult = invokeWithErrorHandling(setup, null, [vm._props || shallowReactive({}), ctx], vm, "setup");
2242
+ popTarget();
2243
+ setCurrentInstance();
2244
+ if (isFunction(setupResult)) {
2245
+ // render function
2246
+ // @ts-ignore
2247
+ options.render = setupResult;
2248
+ }
2249
+ else if (isObject(setupResult)) {
2250
+ // bindings
2251
+ if (setupResult instanceof VNode) {
2252
+ warn$2("setup() should not return VNodes directly - " +
2253
+ "return a render function instead.");
2254
+ }
2255
+ vm._setupState = setupResult;
2256
+ // __sfc indicates compiled bindings from <script setup>
2257
+ if (!setupResult.__sfc) {
2258
+ for (var key in setupResult) {
2259
+ if (!isReserved(key)) {
2260
+ proxyWithRefUnwrap(vm, setupResult, key);
2261
+ }
2262
+ else {
2263
+ warn$2("Avoid using variables that start with _ or $ in setup().");
2264
+ }
2265
+ }
2266
+ }
2267
+ else {
2268
+ // exposed for compiled render fn
2269
+ var proxy = (vm._setupProxy = {});
2270
+ for (var key in setupResult) {
2271
+ if (key !== '__sfc') {
2272
+ proxyWithRefUnwrap(proxy, setupResult, key);
2273
+ }
2274
+ }
2275
+ }
2276
+ }
2277
+ else if (setupResult !== undefined) {
2278
+ warn$2("setup() should return an object. Received: ".concat(setupResult === null ? 'null' : typeof setupResult));
2279
+ }
2280
+ }
2281
+ }
2282
+ function createSetupContext(vm) {
2283
+ var exposeCalled = false;
2284
+ return {
2285
+ get attrs() {
2286
+ if (!vm._attrsProxy) {
2287
+ var proxy = (vm._attrsProxy = {});
2288
+ def(proxy, '_v_attr_proxy', true);
2289
+ syncSetupProxy(proxy, vm.$attrs, emptyObject, vm, '$attrs');
2290
+ }
2291
+ return vm._attrsProxy;
2292
+ },
2293
+ get listeners() {
2294
+ if (!vm._listenersProxy) {
2295
+ var proxy = (vm._listenersProxy = {});
2296
+ syncSetupProxy(proxy, vm.$listeners, emptyObject, vm, '$listeners');
2297
+ }
2298
+ return vm._listenersProxy;
2299
+ },
2300
+ get slots() {
2301
+ return initSlotsProxy(vm);
2302
+ },
2303
+ emit: bind$1(vm.$emit, vm),
2304
+ expose: function (exposed) {
2305
+ {
2306
+ if (exposeCalled) {
2307
+ warn$2("expose() should be called only once per setup().", vm);
2308
+ }
2309
+ exposeCalled = true;
2310
+ }
2311
+ if (exposed) {
2312
+ Object.keys(exposed).forEach(function (key) {
2313
+ return proxyWithRefUnwrap(vm, exposed, key);
2314
+ });
2315
+ }
2316
+ }
2317
+ };
2318
+ }
2319
+ function syncSetupProxy(to, from, prev, instance, type) {
2320
+ var changed = false;
2321
+ for (var key in from) {
2322
+ if (!(key in to)) {
2323
+ changed = true;
2324
+ defineProxyAttr(to, key, instance, type);
2325
+ }
2326
+ else if (from[key] !== prev[key]) {
2327
+ changed = true;
2328
+ }
2329
+ }
2330
+ for (var key in to) {
2331
+ if (!(key in from)) {
2332
+ changed = true;
2333
+ delete to[key];
2334
+ }
2335
+ }
2336
+ return changed;
2337
+ }
2338
+ function defineProxyAttr(proxy, key, instance, type) {
2339
+ Object.defineProperty(proxy, key, {
2340
+ enumerable: true,
2341
+ configurable: true,
2342
+ get: function () {
2343
+ return instance[type][key];
2344
+ }
2345
+ });
2346
+ }
2347
+ function initSlotsProxy(vm) {
2348
+ if (!vm._slotsProxy) {
2349
+ syncSetupSlots((vm._slotsProxy = {}), vm.$scopedSlots);
2350
+ }
2351
+ return vm._slotsProxy;
2352
+ }
2353
+ function syncSetupSlots(to, from) {
2354
+ for (var key in from) {
2355
+ to[key] = from[key];
2356
+ }
2357
+ for (var key in to) {
2358
+ if (!(key in from)) {
2359
+ delete to[key];
2360
+ }
2361
+ }
2362
+ }
2363
+ /**
2364
+ * @internal use manual type def because public setup context type relies on
2365
+ * legacy VNode types
2366
+ */
2367
+ function useSlots() {
2368
+ return getContext().slots;
2369
+ }
2370
+ /**
2371
+ * @internal use manual type def because public setup context type relies on
2372
+ * legacy VNode types
2373
+ */
2374
+ function useAttrs() {
2375
+ return getContext().attrs;
2376
+ }
2377
+ /**
2378
+ * Vue 2 only
2379
+ * @internal use manual type def because public setup context type relies on
2380
+ * legacy VNode types
2381
+ */
2382
+ function useListeners() {
2383
+ return getContext().listeners;
2384
+ }
2385
+ function getContext() {
2386
+ if (!currentInstance) {
2387
+ warn$2("useContext() called without active instance.");
2388
+ }
2389
+ var vm = currentInstance;
2390
+ return vm._setupContext || (vm._setupContext = createSetupContext(vm));
2391
+ }
2392
+ /**
2393
+ * Runtime helper for merging default declarations. Imported by compiled code
2394
+ * only.
2395
+ * @internal
2396
+ */
2397
+ function mergeDefaults(raw, defaults) {
2398
+ var props = isArray(raw)
2399
+ ? raw.reduce(function (normalized, p) { return ((normalized[p] = {}), normalized); }, {})
2400
+ : raw;
2401
+ for (var key in defaults) {
2402
+ var opt = props[key];
2403
+ if (opt) {
2404
+ if (isArray(opt) || isFunction(opt)) {
2405
+ props[key] = { type: opt, default: defaults[key] };
2406
+ }
2407
+ else {
2408
+ opt.default = defaults[key];
2409
+ }
2410
+ }
2411
+ else if (opt === null) {
2412
+ props[key] = { default: defaults[key] };
2413
+ }
2414
+ else {
2415
+ warn$2("props default key \"".concat(key, "\" has no corresponding declaration."));
2416
+ }
2417
+ }
2418
+ return props;
2419
+ }
2420
+
2421
+ function initRender(vm) {
2422
+ vm._vnode = null; // the root of the child tree
2423
+ vm._staticTrees = null; // v-once cached trees
2424
+ var options = vm.$options;
2425
+ var parentVnode = (vm.$vnode = options._parentVnode); // the placeholder node in parent tree
2426
+ var renderContext = parentVnode && parentVnode.context;
2427
+ vm.$slots = resolveSlots(options._renderChildren, renderContext);
2428
+ vm.$scopedSlots = parentVnode
2429
+ ? normalizeScopedSlots(vm.$parent, parentVnode.data.scopedSlots, vm.$slots)
2430
+ : emptyObject;
2431
+ // bind the createElement fn to this instance
2432
+ // so that we get proper render context inside it.
2433
+ // args order: tag, data, children, normalizationType, alwaysNormalize
2434
+ // internal version is used by render functions compiled from templates
2435
+ // @ts-expect-error
2436
+ vm._c = function (a, b, c, d) { return createElement$1(vm, a, b, c, d, false); };
2437
+ // normalization is always applied for the public version, used in
2438
+ // user-written render functions.
2439
+ // @ts-expect-error
2440
+ vm.$createElement = function (a, b, c, d) { return createElement$1(vm, a, b, c, d, true); };
2441
+ // $attrs & $listeners are exposed for easier HOC creation.
2442
+ // they need to be reactive so that HOCs using them are always updated
2443
+ var parentData = parentVnode && parentVnode.data;
2444
+ /* istanbul ignore else */
2445
+ {
2446
+ defineReactive(vm, '$attrs', (parentData && parentData.attrs) || emptyObject, function () {
2447
+ !isUpdatingChildComponent && warn$2("$attrs is readonly.", vm);
2448
+ }, true);
2449
+ defineReactive(vm, '$listeners', options._parentListeners || emptyObject, function () {
2450
+ !isUpdatingChildComponent && warn$2("$listeners is readonly.", vm);
2451
+ }, true);
2452
+ }
2453
+ }
2454
+ var currentRenderingInstance = null;
2455
+ function renderMixin(Vue) {
2456
+ // install runtime convenience helpers
2457
+ installRenderHelpers(Vue.prototype);
2458
+ Vue.prototype.$nextTick = function (fn) {
2459
+ return nextTick(fn, this);
2460
+ };
2461
+ Vue.prototype._render = function () {
2462
+ var vm = this;
2463
+ var _a = vm.$options, render = _a.render, _parentVnode = _a._parentVnode;
2464
+ if (_parentVnode && vm._isMounted) {
2465
+ vm.$scopedSlots = normalizeScopedSlots(vm.$parent, _parentVnode.data.scopedSlots, vm.$slots, vm.$scopedSlots);
2466
+ if (vm._slotsProxy) {
2467
+ syncSetupSlots(vm._slotsProxy, vm.$scopedSlots);
2468
+ }
2469
+ }
2470
+ // set parent vnode. this allows render functions to have access
2471
+ // to the data on the placeholder node.
2472
+ vm.$vnode = _parentVnode;
2473
+ // render self
2474
+ var vnode;
2475
+ try {
2476
+ // There's no need to maintain a stack because all render fns are called
2477
+ // separately from one another. Nested component's render fns are called
2478
+ // when parent component is patched.
2479
+ setCurrentInstance(vm);
2480
+ currentRenderingInstance = vm;
2481
+ vnode = render.call(vm._renderProxy, vm.$createElement);
2482
+ }
2483
+ catch (e) {
2484
+ handleError(e, vm, "render");
2485
+ // return error render result,
2486
+ // or previous vnode to prevent render error causing blank component
2487
+ /* istanbul ignore else */
2488
+ if (vm.$options.renderError) {
2489
+ try {
2490
+ vnode = vm.$options.renderError.call(vm._renderProxy, vm.$createElement, e);
2491
+ }
2492
+ catch (e) {
2493
+ handleError(e, vm, "renderError");
2494
+ vnode = vm._vnode;
2495
+ }
2496
+ }
2497
+ else {
2498
+ vnode = vm._vnode;
2499
+ }
2500
+ }
2501
+ finally {
2502
+ currentRenderingInstance = null;
2503
+ setCurrentInstance();
2504
+ }
2505
+ // if the returned array contains only a single node, allow it
2506
+ if (isArray(vnode) && vnode.length === 1) {
2507
+ vnode = vnode[0];
2508
+ }
2509
+ // return empty vnode in case the render function errored out
2510
+ if (!(vnode instanceof VNode)) {
2511
+ if (isArray(vnode)) {
2512
+ warn$2('Multiple root nodes returned from render function. Render function ' +
2513
+ 'should return a single root node.', vm);
2514
+ }
2515
+ vnode = createEmptyVNode();
2516
+ }
2517
+ // set parent
2518
+ vnode.parent = _parentVnode;
2519
+ return vnode;
2520
+ };
2521
+ }
2522
+
2523
+ function ensureCtor(comp, base) {
2524
+ if (comp.__esModule || (hasSymbol && comp[Symbol.toStringTag] === 'Module')) {
2525
+ comp = comp.default;
2526
+ }
2527
+ return isObject(comp) ? base.extend(comp) : comp;
2528
+ }
2529
+ function createAsyncPlaceholder(factory, data, context, children, tag) {
2530
+ var node = createEmptyVNode();
2531
+ node.asyncFactory = factory;
2532
+ node.asyncMeta = { data: data, context: context, children: children, tag: tag };
2533
+ return node;
2534
+ }
2535
+ function resolveAsyncComponent(factory, baseCtor) {
2536
+ if (isTrue(factory.error) && isDef(factory.errorComp)) {
2537
+ return factory.errorComp;
2538
+ }
2539
+ if (isDef(factory.resolved)) {
2540
+ return factory.resolved;
2541
+ }
2542
+ var owner = currentRenderingInstance;
2543
+ if (owner && isDef(factory.owners) && factory.owners.indexOf(owner) === -1) {
2544
+ // already pending
2545
+ factory.owners.push(owner);
2546
+ }
2547
+ if (isTrue(factory.loading) && isDef(factory.loadingComp)) {
2548
+ return factory.loadingComp;
2549
+ }
2550
+ if (owner && !isDef(factory.owners)) {
2551
+ var owners_1 = (factory.owners = [owner]);
2552
+ var sync_1 = true;
2553
+ var timerLoading_1 = null;
2554
+ var timerTimeout_1 = null;
2555
+ owner.$on('hook:destroyed', function () { return remove$2(owners_1, owner); });
2556
+ var forceRender_1 = function (renderCompleted) {
2557
+ for (var i = 0, l = owners_1.length; i < l; i++) {
2558
+ owners_1[i].$forceUpdate();
2559
+ }
2560
+ if (renderCompleted) {
2561
+ owners_1.length = 0;
2562
+ if (timerLoading_1 !== null) {
2563
+ clearTimeout(timerLoading_1);
2564
+ timerLoading_1 = null;
2565
+ }
2566
+ if (timerTimeout_1 !== null) {
2567
+ clearTimeout(timerTimeout_1);
2568
+ timerTimeout_1 = null;
2569
+ }
2570
+ }
2571
+ };
2572
+ var resolve = once(function (res) {
2573
+ // cache resolved
2574
+ factory.resolved = ensureCtor(res, baseCtor);
2575
+ // invoke callbacks only if this is not a synchronous resolve
2576
+ // (async resolves are shimmed as synchronous during SSR)
2577
+ if (!sync_1) {
2578
+ forceRender_1(true);
2579
+ }
2580
+ else {
2581
+ owners_1.length = 0;
2582
+ }
2583
+ });
2584
+ var reject_1 = once(function (reason) {
2585
+ warn$2("Failed to resolve async component: ".concat(String(factory)) +
2586
+ (reason ? "\nReason: ".concat(reason) : ''));
2587
+ if (isDef(factory.errorComp)) {
2588
+ factory.error = true;
2589
+ forceRender_1(true);
2590
+ }
2591
+ });
2592
+ var res_1 = factory(resolve, reject_1);
2593
+ if (isObject(res_1)) {
2594
+ if (isPromise(res_1)) {
2595
+ // () => Promise
2596
+ if (isUndef(factory.resolved)) {
2597
+ res_1.then(resolve, reject_1);
2598
+ }
2599
+ }
2600
+ else if (isPromise(res_1.component)) {
2601
+ res_1.component.then(resolve, reject_1);
2602
+ if (isDef(res_1.error)) {
2603
+ factory.errorComp = ensureCtor(res_1.error, baseCtor);
2604
+ }
2605
+ if (isDef(res_1.loading)) {
2606
+ factory.loadingComp = ensureCtor(res_1.loading, baseCtor);
2607
+ if (res_1.delay === 0) {
2608
+ factory.loading = true;
2609
+ }
2610
+ else {
2611
+ // @ts-expect-error NodeJS timeout type
2612
+ timerLoading_1 = setTimeout(function () {
2613
+ timerLoading_1 = null;
2614
+ if (isUndef(factory.resolved) && isUndef(factory.error)) {
2615
+ factory.loading = true;
2616
+ forceRender_1(false);
2617
+ }
2618
+ }, res_1.delay || 200);
2619
+ }
2620
+ }
2621
+ if (isDef(res_1.timeout)) {
2622
+ // @ts-expect-error NodeJS timeout type
2623
+ timerTimeout_1 = setTimeout(function () {
2624
+ timerTimeout_1 = null;
2625
+ if (isUndef(factory.resolved)) {
2626
+ reject_1("timeout (".concat(res_1.timeout, "ms)") );
2627
+ }
2628
+ }, res_1.timeout);
2629
+ }
2630
+ }
2631
+ }
2632
+ sync_1 = false;
2633
+ // return in case resolved synchronously
2634
+ return factory.loading ? factory.loadingComp : factory.resolved;
2635
+ }
2636
+ }
2637
+
2638
+ function getFirstComponentChild(children) {
2639
+ if (isArray(children)) {
2640
+ for (var i = 0; i < children.length; i++) {
2641
+ var c = children[i];
2642
+ if (isDef(c) && (isDef(c.componentOptions) || isAsyncPlaceholder(c))) {
2643
+ return c;
2644
+ }
2645
+ }
2646
+ }
2647
+ }
2648
+
2649
+ function initEvents(vm) {
2650
+ vm._events = Object.create(null);
2651
+ vm._hasHookEvent = false;
2652
+ // init parent attached events
2653
+ var listeners = vm.$options._parentListeners;
2654
+ if (listeners) {
2655
+ updateComponentListeners(vm, listeners);
2656
+ }
2657
+ }
2658
+ var target$1;
2659
+ function add$1(event, fn) {
2660
+ target$1.$on(event, fn);
2661
+ }
2662
+ function remove$1(event, fn) {
2663
+ target$1.$off(event, fn);
2664
+ }
2665
+ function createOnceHandler$1(event, fn) {
2666
+ var _target = target$1;
2667
+ return function onceHandler() {
2668
+ var res = fn.apply(null, arguments);
2669
+ if (res !== null) {
2670
+ _target.$off(event, onceHandler);
2671
+ }
2672
+ };
2673
+ }
2674
+ function updateComponentListeners(vm, listeners, oldListeners) {
2675
+ target$1 = vm;
2676
+ updateListeners(listeners, oldListeners || {}, add$1, remove$1, createOnceHandler$1, vm);
2677
+ target$1 = undefined;
2678
+ }
2679
+ function eventsMixin(Vue) {
2680
+ var hookRE = /^hook:/;
2681
+ Vue.prototype.$on = function (event, fn) {
2682
+ var vm = this;
2683
+ if (isArray(event)) {
2684
+ for (var i = 0, l = event.length; i < l; i++) {
2685
+ vm.$on(event[i], fn);
2686
+ }
2687
+ }
2688
+ else {
2689
+ (vm._events[event] || (vm._events[event] = [])).push(fn);
2690
+ // optimize hook:event cost by using a boolean flag marked at registration
2691
+ // instead of a hash lookup
2692
+ if (hookRE.test(event)) {
2693
+ vm._hasHookEvent = true;
2694
+ }
2695
+ }
2696
+ return vm;
2697
+ };
2698
+ Vue.prototype.$once = function (event, fn) {
2699
+ var vm = this;
2700
+ function on() {
2701
+ vm.$off(event, on);
2702
+ fn.apply(vm, arguments);
2703
+ }
2704
+ on.fn = fn;
2705
+ vm.$on(event, on);
2706
+ return vm;
2707
+ };
2708
+ Vue.prototype.$off = function (event, fn) {
2709
+ var vm = this;
2710
+ // all
2711
+ if (!arguments.length) {
2712
+ vm._events = Object.create(null);
2713
+ return vm;
2714
+ }
2715
+ // array of events
2716
+ if (isArray(event)) {
2717
+ for (var i_1 = 0, l = event.length; i_1 < l; i_1++) {
2718
+ vm.$off(event[i_1], fn);
2719
+ }
2720
+ return vm;
2721
+ }
2722
+ // specific event
2723
+ var cbs = vm._events[event];
2724
+ if (!cbs) {
2725
+ return vm;
2726
+ }
2727
+ if (!fn) {
2728
+ vm._events[event] = null;
2729
+ return vm;
2730
+ }
2731
+ // specific handler
2732
+ var cb;
2733
+ var i = cbs.length;
2734
+ while (i--) {
2735
+ cb = cbs[i];
2736
+ if (cb === fn || cb.fn === fn) {
2737
+ cbs.splice(i, 1);
2738
+ break;
2739
+ }
2740
+ }
2741
+ return vm;
2742
+ };
2743
+ Vue.prototype.$emit = function (event) {
2744
+ var vm = this;
2745
+ {
2746
+ var lowerCaseEvent = event.toLowerCase();
2747
+ if (lowerCaseEvent !== event && vm._events[lowerCaseEvent]) {
2748
+ tip("Event \"".concat(lowerCaseEvent, "\" is emitted in component ") +
2749
+ "".concat(formatComponentName(vm), " but the handler is registered for \"").concat(event, "\". ") +
2750
+ "Note that HTML attributes are case-insensitive and you cannot use " +
2751
+ "v-on to listen to camelCase events when using in-DOM templates. " +
2752
+ "You should probably use \"".concat(hyphenate(event), "\" instead of \"").concat(event, "\"."));
2753
+ }
2754
+ }
2755
+ var cbs = vm._events[event];
2756
+ if (cbs) {
2757
+ cbs = cbs.length > 1 ? toArray(cbs) : cbs;
2758
+ var args = toArray(arguments, 1);
2759
+ var info = "event handler for \"".concat(event, "\"");
2760
+ for (var i = 0, l = cbs.length; i < l; i++) {
2761
+ invokeWithErrorHandling(cbs[i], vm, args, vm, info);
2762
+ }
2763
+ }
2764
+ return vm;
2765
+ };
2766
+ }
2767
+
2768
+ var activeInstance = null;
2769
+ var isUpdatingChildComponent = false;
2770
+ function setActiveInstance(vm) {
2771
+ var prevActiveInstance = activeInstance;
2772
+ activeInstance = vm;
2773
+ return function () {
2774
+ activeInstance = prevActiveInstance;
2775
+ };
2776
+ }
2777
+ function initLifecycle(vm) {
2778
+ var options = vm.$options;
2779
+ // locate first non-abstract parent
2780
+ var parent = options.parent;
2781
+ if (parent && !options.abstract) {
2782
+ while (parent.$options.abstract && parent.$parent) {
2783
+ parent = parent.$parent;
2784
+ }
2785
+ parent.$children.push(vm);
2786
+ }
2787
+ vm.$parent = parent;
2788
+ vm.$root = parent ? parent.$root : vm;
2789
+ vm.$children = [];
2790
+ vm.$refs = {};
2791
+ vm._provided = parent ? parent._provided : Object.create(null);
2792
+ vm._watcher = null;
2793
+ vm._inactive = null;
2794
+ vm._directInactive = false;
2795
+ vm._isMounted = false;
2796
+ vm._isDestroyed = false;
2797
+ vm._isBeingDestroyed = false;
2798
+ }
2799
+ function lifecycleMixin(Vue) {
2800
+ Vue.prototype._update = function (vnode, hydrating) {
2801
+ var vm = this;
2802
+ var prevEl = vm.$el;
2803
+ var prevVnode = vm._vnode;
2804
+ var restoreActiveInstance = setActiveInstance(vm);
2805
+ vm._vnode = vnode;
2806
+ // Vue.prototype.__patch__ is injected in entry points
2807
+ // based on the rendering backend used.
2808
+ if (!prevVnode) {
2809
+ // initial render
2810
+ vm.$el = vm.__patch__(vm.$el, vnode, hydrating, false /* removeOnly */);
2811
+ }
2812
+ else {
2813
+ // updates
2814
+ vm.$el = vm.__patch__(prevVnode, vnode);
2815
+ }
2816
+ restoreActiveInstance();
2817
+ // update __vue__ reference
2818
+ if (prevEl) {
2819
+ prevEl.__vue__ = null;
2820
+ }
2821
+ if (vm.$el) {
2822
+ vm.$el.__vue__ = vm;
2823
+ }
2824
+ // if parent is an HOC, update its $el as well
2825
+ if (vm.$vnode && vm.$parent && vm.$vnode === vm.$parent._vnode) {
2826
+ vm.$parent.$el = vm.$el;
2827
+ }
2828
+ // updated hook is called by the scheduler to ensure that children are
2829
+ // updated in a parent's updated hook.
2830
+ };
2831
+ Vue.prototype.$forceUpdate = function () {
2832
+ var vm = this;
2833
+ if (vm._watcher) {
2834
+ vm._watcher.update();
2835
+ }
2836
+ };
2837
+ Vue.prototype.$destroy = function () {
2838
+ var vm = this;
2839
+ if (vm._isBeingDestroyed) {
2840
+ return;
2841
+ }
2842
+ callHook$1(vm, 'beforeDestroy');
2843
+ vm._isBeingDestroyed = true;
2844
+ // remove self from parent
2845
+ var parent = vm.$parent;
2846
+ if (parent && !parent._isBeingDestroyed && !vm.$options.abstract) {
2847
+ remove$2(parent.$children, vm);
2848
+ }
2849
+ // teardown scope. this includes both the render watcher and other
2850
+ // watchers created
2851
+ vm._scope.stop();
2852
+ // remove reference from data ob
2853
+ // frozen object may not have observer.
2854
+ if (vm._data.__ob__) {
2855
+ vm._data.__ob__.vmCount--;
2856
+ }
2857
+ // call the last hook...
2858
+ vm._isDestroyed = true;
2859
+ // invoke destroy hooks on current rendered tree
2860
+ vm.__patch__(vm._vnode, null);
2861
+ // fire destroyed hook
2862
+ callHook$1(vm, 'destroyed');
2863
+ // turn off all instance listeners.
2864
+ vm.$off();
2865
+ // remove __vue__ reference
2866
+ if (vm.$el) {
2867
+ vm.$el.__vue__ = null;
2868
+ }
2869
+ // release circular reference (#6759)
2870
+ if (vm.$vnode) {
2871
+ vm.$vnode.parent = null;
2872
+ }
2873
+ };
2874
+ }
2875
+ function mountComponent(vm, el, hydrating) {
2876
+ vm.$el = el;
2877
+ if (!vm.$options.render) {
2878
+ // @ts-expect-error invalid type
2879
+ vm.$options.render = createEmptyVNode;
2880
+ {
2881
+ /* istanbul ignore if */
2882
+ if ((vm.$options.template && vm.$options.template.charAt(0) !== '#') ||
2883
+ vm.$options.el ||
2884
+ el) {
2885
+ warn$2('You are using the runtime-only build of Vue where the template ' +
2886
+ 'compiler is not available. Either pre-compile the templates into ' +
2887
+ 'render functions, or use the compiler-included build.', vm);
2888
+ }
2889
+ else {
2890
+ warn$2('Failed to mount component: template or render function not defined.', vm);
2891
+ }
2892
+ }
2893
+ }
2894
+ callHook$1(vm, 'beforeMount');
2895
+ var updateComponent;
2896
+ /* istanbul ignore if */
2897
+ if (config.performance && mark) {
2898
+ updateComponent = function () {
2899
+ var name = vm._name;
2900
+ var id = vm._uid;
2901
+ var startTag = "vue-perf-start:".concat(id);
2902
+ var endTag = "vue-perf-end:".concat(id);
2903
+ mark(startTag);
2904
+ var vnode = vm._render();
2905
+ mark(endTag);
2906
+ measure("vue ".concat(name, " render"), startTag, endTag);
2907
+ mark(startTag);
2908
+ vm._update(vnode, hydrating);
2909
+ mark(endTag);
2910
+ measure("vue ".concat(name, " patch"), startTag, endTag);
2911
+ };
2912
+ }
2913
+ else {
2914
+ updateComponent = function () {
2915
+ vm._update(vm._render(), hydrating);
2916
+ };
2917
+ }
2918
+ var watcherOptions = {
2919
+ before: function () {
2920
+ if (vm._isMounted && !vm._isDestroyed) {
2921
+ callHook$1(vm, 'beforeUpdate');
2922
+ }
2923
+ }
2924
+ };
2925
+ {
2926
+ watcherOptions.onTrack = function (e) { return callHook$1(vm, 'renderTracked', [e]); };
2927
+ watcherOptions.onTrigger = function (e) { return callHook$1(vm, 'renderTriggered', [e]); };
2928
+ }
2929
+ // we set this to vm._watcher inside the watcher's constructor
2930
+ // since the watcher's initial patch may call $forceUpdate (e.g. inside child
2931
+ // component's mounted hook), which relies on vm._watcher being already defined
2932
+ new Watcher(vm, updateComponent, noop, watcherOptions, true /* isRenderWatcher */);
2933
+ hydrating = false;
2934
+ // flush buffer for flush: "pre" watchers queued in setup()
2935
+ var preWatchers = vm._preWatchers;
2936
+ if (preWatchers) {
2937
+ for (var i = 0; i < preWatchers.length; i++) {
2938
+ preWatchers[i].run();
2939
+ }
2940
+ }
2941
+ // manually mounted instance, call mounted on self
2942
+ // mounted is called for render-created child components in its inserted hook
2943
+ if (vm.$vnode == null) {
2944
+ vm._isMounted = true;
2945
+ callHook$1(vm, 'mounted');
2946
+ }
2947
+ return vm;
2948
+ }
2949
+ function updateChildComponent(vm, propsData, listeners, parentVnode, renderChildren) {
2950
+ {
2951
+ isUpdatingChildComponent = true;
2952
+ }
2953
+ // determine whether component has slot children
2954
+ // we need to do this before overwriting $options._renderChildren.
2955
+ // check if there are dynamic scopedSlots (hand-written or compiled but with
2956
+ // dynamic slot names). Static scoped slots compiled from template has the
2957
+ // "$stable" marker.
2958
+ var newScopedSlots = parentVnode.data.scopedSlots;
2959
+ var oldScopedSlots = vm.$scopedSlots;
2960
+ var hasDynamicScopedSlot = !!((newScopedSlots && !newScopedSlots.$stable) ||
2961
+ (oldScopedSlots !== emptyObject && !oldScopedSlots.$stable) ||
2962
+ (newScopedSlots && vm.$scopedSlots.$key !== newScopedSlots.$key) ||
2963
+ (!newScopedSlots && vm.$scopedSlots.$key));
2964
+ // Any static slot children from the parent may have changed during parent's
2965
+ // update. Dynamic scoped slots may also have changed. In such cases, a forced
2966
+ // update is necessary to ensure correctness.
2967
+ var needsForceUpdate = !!(renderChildren || // has new static slots
2968
+ vm.$options._renderChildren || // has old static slots
2969
+ hasDynamicScopedSlot);
2970
+ var prevVNode = vm.$vnode;
2971
+ vm.$options._parentVnode = parentVnode;
2972
+ vm.$vnode = parentVnode; // update vm's placeholder node without re-render
2973
+ if (vm._vnode) {
2974
+ // update child tree's parent
2975
+ vm._vnode.parent = parentVnode;
2976
+ }
2977
+ vm.$options._renderChildren = renderChildren;
2978
+ // update $attrs and $listeners hash
2979
+ // these are also reactive so they may trigger child update if the child
2980
+ // used them during render
2981
+ var attrs = parentVnode.data.attrs || emptyObject;
2982
+ if (vm._attrsProxy) {
2983
+ // force update if attrs are accessed and has changed since it may be
2984
+ // passed to a child component.
2985
+ if (syncSetupProxy(vm._attrsProxy, attrs, (prevVNode.data && prevVNode.data.attrs) || emptyObject, vm, '$attrs')) {
2986
+ needsForceUpdate = true;
2987
+ }
2988
+ }
2989
+ vm.$attrs = attrs;
2990
+ // update listeners
2991
+ listeners = listeners || emptyObject;
2992
+ var prevListeners = vm.$options._parentListeners;
2993
+ if (vm._listenersProxy) {
2994
+ syncSetupProxy(vm._listenersProxy, listeners, prevListeners || emptyObject, vm, '$listeners');
2995
+ }
2996
+ vm.$listeners = vm.$options._parentListeners = listeners;
2997
+ updateComponentListeners(vm, listeners, prevListeners);
2998
+ // update props
2999
+ if (propsData && vm.$options.props) {
3000
+ toggleObserving(false);
3001
+ var props = vm._props;
3002
+ var propKeys = vm.$options._propKeys || [];
3003
+ for (var i = 0; i < propKeys.length; i++) {
3004
+ var key = propKeys[i];
3005
+ var propOptions = vm.$options.props; // wtf flow?
3006
+ props[key] = validateProp(key, propOptions, propsData, vm);
3007
+ }
3008
+ toggleObserving(true);
3009
+ // keep a copy of raw propsData
3010
+ vm.$options.propsData = propsData;
3011
+ }
3012
+ // resolve slots + force update if has children
3013
+ if (needsForceUpdate) {
3014
+ vm.$slots = resolveSlots(renderChildren, parentVnode.context);
3015
+ vm.$forceUpdate();
3016
+ }
3017
+ {
3018
+ isUpdatingChildComponent = false;
3019
+ }
3020
+ }
3021
+ function isInInactiveTree(vm) {
3022
+ while (vm && (vm = vm.$parent)) {
3023
+ if (vm._inactive)
3024
+ return true;
3025
+ }
3026
+ return false;
3027
+ }
3028
+ function activateChildComponent(vm, direct) {
3029
+ if (direct) {
3030
+ vm._directInactive = false;
3031
+ if (isInInactiveTree(vm)) {
3032
+ return;
3033
+ }
3034
+ }
3035
+ else if (vm._directInactive) {
3036
+ return;
3037
+ }
3038
+ if (vm._inactive || vm._inactive === null) {
3039
+ vm._inactive = false;
3040
+ for (var i = 0; i < vm.$children.length; i++) {
3041
+ activateChildComponent(vm.$children[i]);
3042
+ }
3043
+ callHook$1(vm, 'activated');
3044
+ }
3045
+ }
3046
+ function deactivateChildComponent(vm, direct) {
3047
+ if (direct) {
3048
+ vm._directInactive = true;
3049
+ if (isInInactiveTree(vm)) {
3050
+ return;
3051
+ }
3052
+ }
3053
+ if (!vm._inactive) {
3054
+ vm._inactive = true;
3055
+ for (var i = 0; i < vm.$children.length; i++) {
3056
+ deactivateChildComponent(vm.$children[i]);
3057
+ }
3058
+ callHook$1(vm, 'deactivated');
3059
+ }
3060
+ }
3061
+ function callHook$1(vm, hook, args, setContext) {
3062
+ if (setContext === void 0) { setContext = true; }
3063
+ // #7573 disable dep collection when invoking lifecycle hooks
3064
+ pushTarget();
3065
+ var prev = currentInstance;
3066
+ setContext && setCurrentInstance(vm);
3067
+ var handlers = vm.$options[hook];
3068
+ var info = "".concat(hook, " hook");
3069
+ if (handlers) {
3070
+ for (var i = 0, j = handlers.length; i < j; i++) {
3071
+ invokeWithErrorHandling(handlers[i], vm, args || null, vm, info);
3072
+ }
3073
+ }
3074
+ if (vm._hasHookEvent) {
3075
+ vm.$emit('hook:' + hook);
3076
+ }
3077
+ setContext && setCurrentInstance(prev);
3078
+ popTarget();
3079
+ }
3080
+
3081
+ var MAX_UPDATE_COUNT = 100;
3082
+ var queue = [];
3083
+ var activatedChildren = [];
3084
+ var has = {};
3085
+ var circular = {};
3086
+ var waiting = false;
3087
+ var flushing = false;
3088
+ var index$1 = 0;
3089
+ /**
3090
+ * Reset the scheduler's state.
3091
+ */
3092
+ function resetSchedulerState() {
3093
+ index$1 = queue.length = activatedChildren.length = 0;
3094
+ has = {};
3095
+ {
3096
+ circular = {};
3097
+ }
3098
+ waiting = flushing = false;
3099
+ }
3100
+ // Async edge case #6566 requires saving the timestamp when event listeners are
3101
+ // attached. However, calling performance.now() has a perf overhead especially
3102
+ // if the page has thousands of event listeners. Instead, we take a timestamp
3103
+ // every time the scheduler flushes and use that for all event listeners
3104
+ // attached during that flush.
3105
+ var currentFlushTimestamp = 0;
3106
+ // Async edge case fix requires storing an event listener's attach timestamp.
3107
+ var getNow = Date.now;
3108
+ // Determine what event timestamp the browser is using. Annoyingly, the
3109
+ // timestamp can either be hi-res (relative to page load) or low-res
3110
+ // (relative to UNIX epoch), so in order to compare time we have to use the
3111
+ // same timestamp type when saving the flush timestamp.
3112
+ // All IE versions use low-res event timestamps, and have problematic clock
3113
+ // implementations (#9632)
3114
+ if (inBrowser && !isIE) {
3115
+ var performance_1 = window.performance;
3116
+ if (performance_1 &&
3117
+ typeof performance_1.now === 'function' &&
3118
+ getNow() > document.createEvent('Event').timeStamp) {
3119
+ // if the event timestamp, although evaluated AFTER the Date.now(), is
3120
+ // smaller than it, it means the event is using a hi-res timestamp,
3121
+ // and we need to use the hi-res version for event listener timestamps as
3122
+ // well.
3123
+ getNow = function () { return performance_1.now(); };
3124
+ }
3125
+ }
3126
+ var sortCompareFn = function (a, b) {
3127
+ if (a.post) {
3128
+ if (!b.post)
3129
+ return 1;
3130
+ }
3131
+ else if (b.post) {
3132
+ return -1;
3133
+ }
3134
+ return a.id - b.id;
3135
+ };
3136
+ /**
3137
+ * Flush both queues and run the watchers.
3138
+ */
3139
+ function flushSchedulerQueue() {
3140
+ currentFlushTimestamp = getNow();
3141
+ flushing = true;
3142
+ var watcher, id;
3143
+ // Sort queue before flush.
3144
+ // This ensures that:
3145
+ // 1. Components are updated from parent to child. (because parent is always
3146
+ // created before the child)
3147
+ // 2. A component's user watchers are run before its render watcher (because
3148
+ // user watchers are created before the render watcher)
3149
+ // 3. If a component is destroyed during a parent component's watcher run,
3150
+ // its watchers can be skipped.
3151
+ queue.sort(sortCompareFn);
3152
+ // do not cache length because more watchers might be pushed
3153
+ // as we run existing watchers
3154
+ for (index$1 = 0; index$1 < queue.length; index$1++) {
3155
+ watcher = queue[index$1];
3156
+ if (watcher.before) {
3157
+ watcher.before();
3158
+ }
3159
+ id = watcher.id;
3160
+ has[id] = null;
3161
+ watcher.run();
3162
+ // in dev build, check and stop circular updates.
3163
+ if (has[id] != null) {
3164
+ circular[id] = (circular[id] || 0) + 1;
3165
+ if (circular[id] > MAX_UPDATE_COUNT) {
3166
+ warn$2('You may have an infinite update loop ' +
3167
+ (watcher.user
3168
+ ? "in watcher with expression \"".concat(watcher.expression, "\"")
3169
+ : "in a component render function."), watcher.vm);
3170
+ break;
3171
+ }
3172
+ }
3173
+ }
3174
+ // keep copies of post queues before resetting state
3175
+ var activatedQueue = activatedChildren.slice();
3176
+ var updatedQueue = queue.slice();
3177
+ resetSchedulerState();
3178
+ // call component updated and activated hooks
3179
+ callActivatedHooks(activatedQueue);
3180
+ callUpdatedHooks(updatedQueue);
3181
+ // devtool hook
3182
+ /* istanbul ignore if */
3183
+ if (devtools && config.devtools) {
3184
+ devtools.emit('flush');
3185
+ }
3186
+ }
3187
+ function callUpdatedHooks(queue) {
3188
+ var i = queue.length;
3189
+ while (i--) {
3190
+ var watcher = queue[i];
3191
+ var vm = watcher.vm;
3192
+ if (vm && vm._watcher === watcher && vm._isMounted && !vm._isDestroyed) {
3193
+ callHook$1(vm, 'updated');
3194
+ }
3195
+ }
3196
+ }
3197
+ /**
3198
+ * Queue a kept-alive component that was activated during patch.
3199
+ * The queue will be processed after the entire tree has been patched.
3200
+ */
3201
+ function queueActivatedComponent(vm) {
3202
+ // setting _inactive to false here so that a render function can
3203
+ // rely on checking whether it's in an inactive tree (e.g. router-view)
3204
+ vm._inactive = false;
3205
+ activatedChildren.push(vm);
3206
+ }
3207
+ function callActivatedHooks(queue) {
3208
+ for (var i = 0; i < queue.length; i++) {
3209
+ queue[i]._inactive = true;
3210
+ activateChildComponent(queue[i], true /* true */);
3211
+ }
3212
+ }
3213
+ /**
3214
+ * Push a watcher into the watcher queue.
3215
+ * Jobs with duplicate IDs will be skipped unless it's
3216
+ * pushed when the queue is being flushed.
3217
+ */
3218
+ function queueWatcher(watcher) {
3219
+ var id = watcher.id;
3220
+ if (has[id] != null) {
3221
+ return;
3222
+ }
3223
+ if (watcher === Dep.target && watcher.noRecurse) {
3224
+ return;
3225
+ }
3226
+ has[id] = true;
3227
+ if (!flushing) {
3228
+ queue.push(watcher);
3229
+ }
3230
+ else {
3231
+ // if already flushing, splice the watcher based on its id
3232
+ // if already past its id, it will be run next immediately.
3233
+ var i = queue.length - 1;
3234
+ while (i > index$1 && queue[i].id > watcher.id) {
3235
+ i--;
3236
+ }
3237
+ queue.splice(i + 1, 0, watcher);
3238
+ }
3239
+ // queue the flush
3240
+ if (!waiting) {
3241
+ waiting = true;
3242
+ if (!config.async) {
3243
+ flushSchedulerQueue();
3244
+ return;
3245
+ }
3246
+ nextTick(flushSchedulerQueue);
3247
+ }
3248
+ }
3249
+
3250
+ var WATCHER = "watcher";
3251
+ var WATCHER_CB = "".concat(WATCHER, " callback");
3252
+ var WATCHER_GETTER = "".concat(WATCHER, " getter");
3253
+ var WATCHER_CLEANUP = "".concat(WATCHER, " cleanup");
3254
+ // Simple effect.
3255
+ function watchEffect(effect, options) {
3256
+ return doWatch(effect, null, options);
3257
+ }
3258
+ function watchPostEffect(effect, options) {
3259
+ return doWatch(effect, null, (__assign(__assign({}, options), { flush: 'post' }) ));
3260
+ }
3261
+ function watchSyncEffect(effect, options) {
3262
+ return doWatch(effect, null, (__assign(__assign({}, options), { flush: 'sync' }) ));
3263
+ }
3264
+ // initial value for watchers to trigger on undefined initial values
3265
+ var INITIAL_WATCHER_VALUE = {};
3266
+ // implementation
3267
+ function watch(source, cb, options) {
3268
+ if (typeof cb !== 'function') {
3269
+ warn$2("`watch(fn, options?)` signature has been moved to a separate API. " +
3270
+ "Use `watchEffect(fn, options?)` instead. `watch` now only " +
3271
+ "supports `watch(source, cb, options?) signature.");
3272
+ }
3273
+ return doWatch(source, cb, options);
3274
+ }
3275
+ function doWatch(source, cb, _a) {
3276
+ var _b = _a === void 0 ? emptyObject : _a, immediate = _b.immediate, deep = _b.deep, _c = _b.flush, flush = _c === void 0 ? 'pre' : _c, onTrack = _b.onTrack, onTrigger = _b.onTrigger;
3277
+ if (!cb) {
3278
+ if (immediate !== undefined) {
3279
+ warn$2("watch() \"immediate\" option is only respected when using the " +
3280
+ "watch(source, callback, options?) signature.");
3281
+ }
3282
+ if (deep !== undefined) {
3283
+ warn$2("watch() \"deep\" option is only respected when using the " +
3284
+ "watch(source, callback, options?) signature.");
3285
+ }
3286
+ }
3287
+ var warnInvalidSource = function (s) {
3288
+ warn$2("Invalid watch source: ".concat(s, ". A watch source can only be a getter/effect ") +
3289
+ "function, a ref, a reactive object, or an array of these types.");
3290
+ };
3291
+ var instance = currentInstance;
3292
+ var call = function (fn, type, args) {
3293
+ if (args === void 0) { args = null; }
3294
+ return invokeWithErrorHandling(fn, null, args, instance, type);
3295
+ };
3296
+ var getter;
3297
+ var forceTrigger = false;
3298
+ var isMultiSource = false;
3299
+ if (isRef(source)) {
3300
+ getter = function () { return source.value; };
3301
+ forceTrigger = isShallow(source);
3302
+ }
3303
+ else if (isReactive(source)) {
3304
+ getter = function () {
3305
+ source.__ob__.dep.depend();
3306
+ return source;
3307
+ };
3308
+ deep = true;
3309
+ }
3310
+ else if (isArray(source)) {
3311
+ isMultiSource = true;
3312
+ forceTrigger = source.some(function (s) { return isReactive(s) || isShallow(s); });
3313
+ getter = function () {
3314
+ return source.map(function (s) {
3315
+ if (isRef(s)) {
3316
+ return s.value;
3317
+ }
3318
+ else if (isReactive(s)) {
3319
+ return traverse(s);
3320
+ }
3321
+ else if (isFunction(s)) {
3322
+ return call(s, WATCHER_GETTER);
3323
+ }
3324
+ else {
3325
+ warnInvalidSource(s);
3326
+ }
3327
+ });
3328
+ };
3329
+ }
3330
+ else if (isFunction(source)) {
3331
+ if (cb) {
3332
+ // getter with cb
3333
+ getter = function () { return call(source, WATCHER_GETTER); };
3334
+ }
3335
+ else {
3336
+ // no cb -> simple effect
3337
+ getter = function () {
3338
+ if (instance && instance._isDestroyed) {
3339
+ return;
3340
+ }
3341
+ if (cleanup) {
3342
+ cleanup();
3343
+ }
3344
+ return call(source, WATCHER, [onCleanup]);
3345
+ };
3346
+ }
3347
+ }
3348
+ else {
3349
+ getter = noop;
3350
+ warnInvalidSource(source);
3351
+ }
3352
+ if (cb && deep) {
3353
+ var baseGetter_1 = getter;
3354
+ getter = function () { return traverse(baseGetter_1()); };
3355
+ }
3356
+ var cleanup;
3357
+ var onCleanup = function (fn) {
3358
+ cleanup = watcher.onStop = function () {
3359
+ call(fn, WATCHER_CLEANUP);
3360
+ };
3361
+ };
3362
+ // in SSR there is no need to setup an actual effect, and it should be noop
3363
+ // unless it's eager
3364
+ if (isServerRendering()) {
3365
+ // we will also not call the invalidate callback (+ runner is not set up)
3366
+ onCleanup = noop;
3367
+ if (!cb) {
3368
+ getter();
3369
+ }
3370
+ else if (immediate) {
3371
+ call(cb, WATCHER_CB, [
3372
+ getter(),
3373
+ isMultiSource ? [] : undefined,
3374
+ onCleanup
3375
+ ]);
3376
+ }
3377
+ return noop;
3378
+ }
3379
+ var watcher = new Watcher(currentInstance, getter, noop, {
3380
+ lazy: true
3381
+ });
3382
+ watcher.noRecurse = !cb;
3383
+ var oldValue = isMultiSource ? [] : INITIAL_WATCHER_VALUE;
3384
+ // overwrite default run
3385
+ watcher.run = function () {
3386
+ if (!watcher.active &&
3387
+ !(flush === 'pre' && instance && instance._isBeingDestroyed)) {
3388
+ return;
3389
+ }
3390
+ if (cb) {
3391
+ // watch(source, cb)
3392
+ var newValue = watcher.get();
3393
+ if (deep ||
3394
+ forceTrigger ||
3395
+ (isMultiSource
3396
+ ? newValue.some(function (v, i) {
3397
+ return hasChanged(v, oldValue[i]);
3398
+ })
3399
+ : hasChanged(newValue, oldValue))) {
3400
+ // cleanup before running cb again
3401
+ if (cleanup) {
3402
+ cleanup();
3403
+ }
3404
+ call(cb, WATCHER_CB, [
3405
+ newValue,
3406
+ // pass undefined as the old value when it's changed for the first time
3407
+ oldValue === INITIAL_WATCHER_VALUE ? undefined : oldValue,
3408
+ onCleanup
3409
+ ]);
3410
+ oldValue = newValue;
3411
+ }
3412
+ }
3413
+ else {
3414
+ // watchEffect
3415
+ watcher.get();
3416
+ }
3417
+ };
3418
+ if (flush === 'sync') {
3419
+ watcher.update = watcher.run;
3420
+ }
3421
+ else if (flush === 'post') {
3422
+ watcher.post = true;
3423
+ watcher.update = function () { return queueWatcher(watcher); };
3424
+ }
3425
+ else {
3426
+ // pre
3427
+ watcher.update = function () {
3428
+ if (instance && instance === currentInstance && !instance._isMounted) {
3429
+ // pre-watcher triggered before
3430
+ var buffer = instance._preWatchers || (instance._preWatchers = []);
3431
+ if (buffer.indexOf(watcher) < 0)
3432
+ buffer.push(watcher);
3433
+ }
3434
+ else {
3435
+ queueWatcher(watcher);
3436
+ }
3437
+ };
3438
+ }
3439
+ {
3440
+ watcher.onTrack = onTrack;
3441
+ watcher.onTrigger = onTrigger;
3442
+ }
3443
+ // initial run
3444
+ if (cb) {
3445
+ if (immediate) {
3446
+ watcher.run();
3447
+ }
3448
+ else {
3449
+ oldValue = watcher.get();
3450
+ }
3451
+ }
3452
+ else if (flush === 'post' && instance) {
3453
+ instance.$once('hook:mounted', function () { return watcher.get(); });
3454
+ }
3455
+ else {
3456
+ watcher.get();
3457
+ }
3458
+ return function () {
3459
+ watcher.teardown();
3460
+ };
3461
+ }
3462
+
3463
+ var activeEffectScope;
3464
+ var EffectScope = /** @class */ (function () {
3465
+ function EffectScope(detached) {
3466
+ if (detached === void 0) { detached = false; }
3467
+ /**
3468
+ * @internal
3469
+ */
3470
+ this.active = true;
3471
+ /**
3472
+ * @internal
3473
+ */
3474
+ this.effects = [];
3475
+ /**
3476
+ * @internal
3477
+ */
3478
+ this.cleanups = [];
3479
+ if (!detached && activeEffectScope) {
3480
+ this.parent = activeEffectScope;
3481
+ this.index =
3482
+ (activeEffectScope.scopes || (activeEffectScope.scopes = [])).push(this) - 1;
3483
+ }
3484
+ }
3485
+ EffectScope.prototype.run = function (fn) {
3486
+ if (this.active) {
3487
+ var currentEffectScope = activeEffectScope;
3488
+ try {
3489
+ activeEffectScope = this;
3490
+ return fn();
3491
+ }
3492
+ finally {
3493
+ activeEffectScope = currentEffectScope;
3494
+ }
3495
+ }
3496
+ else {
3497
+ warn$2("cannot run an inactive effect scope.");
3498
+ }
3499
+ };
3500
+ /**
3501
+ * This should only be called on non-detached scopes
3502
+ * @internal
3503
+ */
3504
+ EffectScope.prototype.on = function () {
3505
+ activeEffectScope = this;
3506
+ };
3507
+ /**
3508
+ * This should only be called on non-detached scopes
3509
+ * @internal
3510
+ */
3511
+ EffectScope.prototype.off = function () {
3512
+ activeEffectScope = this.parent;
3513
+ };
3514
+ EffectScope.prototype.stop = function (fromParent) {
3515
+ if (this.active) {
3516
+ var i = void 0, l = void 0;
3517
+ for (i = 0, l = this.effects.length; i < l; i++) {
3518
+ this.effects[i].teardown();
3519
+ }
3520
+ for (i = 0, l = this.cleanups.length; i < l; i++) {
3521
+ this.cleanups[i]();
3522
+ }
3523
+ if (this.scopes) {
3524
+ for (i = 0, l = this.scopes.length; i < l; i++) {
3525
+ this.scopes[i].stop(true);
3526
+ }
3527
+ }
3528
+ // nested scope, dereference from parent to avoid memory leaks
3529
+ if (this.parent && !fromParent) {
3530
+ // optimized O(1) removal
3531
+ var last = this.parent.scopes.pop();
3532
+ if (last && last !== this) {
3533
+ this.parent.scopes[this.index] = last;
3534
+ last.index = this.index;
3535
+ }
3536
+ }
3537
+ this.active = false;
3538
+ }
3539
+ };
3540
+ return EffectScope;
3541
+ }());
3542
+ function effectScope(detached) {
3543
+ return new EffectScope(detached);
3544
+ }
3545
+ /**
3546
+ * @internal
3547
+ */
3548
+ function recordEffectScope(effect, scope) {
3549
+ if (scope === void 0) { scope = activeEffectScope; }
3550
+ if (scope && scope.active) {
3551
+ scope.effects.push(effect);
3552
+ }
3553
+ }
3554
+ function getCurrentScope() {
3555
+ return activeEffectScope;
3556
+ }
3557
+ function onScopeDispose(fn) {
3558
+ if (activeEffectScope) {
3559
+ activeEffectScope.cleanups.push(fn);
3560
+ }
3561
+ else {
3562
+ warn$2("onScopeDispose() is called when there is no active effect scope" +
3563
+ " to be associated with.");
3564
+ }
3565
+ }
3566
+
3567
+ function provide(key, value) {
3568
+ if (!currentInstance) {
3569
+ {
3570
+ warn$2("provide() can only be used inside setup().");
3571
+ }
3572
+ }
3573
+ else {
3574
+ // TS doesn't allow symbol as index type
3575
+ resolveProvided(currentInstance)[key] = value;
3576
+ }
3577
+ }
3578
+ function resolveProvided(vm) {
3579
+ // by default an instance inherits its parent's provides object
3580
+ // but when it needs to provide values of its own, it creates its
3581
+ // own provides object using parent provides object as prototype.
3582
+ // this way in `inject` we can simply look up injections from direct
3583
+ // parent and let the prototype chain do the work.
3584
+ var existing = vm._provided;
3585
+ var parentProvides = vm.$parent && vm.$parent._provided;
3586
+ if (parentProvides === existing) {
3587
+ return (vm._provided = Object.create(parentProvides));
3588
+ }
3589
+ else {
3590
+ return existing;
3591
+ }
3592
+ }
3593
+ function inject(key, defaultValue, treatDefaultAsFactory) {
3594
+ if (treatDefaultAsFactory === void 0) { treatDefaultAsFactory = false; }
3595
+ // fallback to `currentRenderingInstance` so that this can be called in
3596
+ // a functional component
3597
+ var instance = currentInstance;
3598
+ if (instance) {
3599
+ // #2400
3600
+ // to support `app.use` plugins,
3601
+ // fallback to appContext's `provides` if the instance is at root
3602
+ var provides = instance.$parent && instance.$parent._provided;
3603
+ if (provides && key in provides) {
3604
+ // TS doesn't allow symbol as index type
3605
+ return provides[key];
3606
+ }
3607
+ else if (arguments.length > 1) {
3608
+ return treatDefaultAsFactory && isFunction(defaultValue)
3609
+ ? defaultValue.call(instance)
3610
+ : defaultValue;
3611
+ }
3612
+ else {
3613
+ warn$2("injection \"".concat(String(key), "\" not found."));
3614
+ }
3615
+ }
3616
+ else {
3617
+ warn$2("inject() can only be used inside setup() or functional components.");
3618
+ }
3619
+ }
3620
+
3621
+ /**
3622
+ * @internal this function needs manual public type declaration because it relies
3623
+ * on previously manually authored types from Vue 2
3624
+ */
3625
+ function h(type, props, children) {
3626
+ if (!currentInstance) {
3627
+ warn$2("globally imported h() can only be invoked when there is an active " +
3628
+ "component instance, e.g. synchronously in a component's render or setup function.");
3629
+ }
3630
+ return createElement$1(currentInstance, type, props, children, 2, true);
3631
+ }
3632
+
3633
+ function handleError(err, vm, info) {
3634
+ // Deactivate deps tracking while processing error handler to avoid possible infinite rendering.
3635
+ // See: https://github.com/vuejs/vuex/issues/1505
3636
+ pushTarget();
3637
+ try {
3638
+ if (vm) {
3639
+ var cur = vm;
3640
+ while ((cur = cur.$parent)) {
3641
+ var hooks = cur.$options.errorCaptured;
3642
+ if (hooks) {
3643
+ for (var i = 0; i < hooks.length; i++) {
3644
+ try {
3645
+ var capture = hooks[i].call(cur, err, vm, info) === false;
3646
+ if (capture)
3647
+ return;
3648
+ }
3649
+ catch (e) {
3650
+ globalHandleError(e, cur, 'errorCaptured hook');
3651
+ }
3652
+ }
3653
+ }
3654
+ }
3655
+ }
3656
+ globalHandleError(err, vm, info);
3657
+ }
3658
+ finally {
3659
+ popTarget();
3660
+ }
3661
+ }
3662
+ function invokeWithErrorHandling(handler, context, args, vm, info) {
3663
+ var res;
3664
+ try {
3665
+ res = args ? handler.apply(context, args) : handler.call(context);
3666
+ if (res && !res._isVue && isPromise(res) && !res._handled) {
3667
+ res.catch(function (e) { return handleError(e, vm, info + " (Promise/async)"); });
3668
+ res._handled = true;
3669
+ }
3670
+ }
3671
+ catch (e) {
3672
+ handleError(e, vm, info);
3673
+ }
3674
+ return res;
3675
+ }
3676
+ function globalHandleError(err, vm, info) {
3677
+ if (config.errorHandler) {
3678
+ try {
3679
+ return config.errorHandler.call(null, err, vm, info);
3680
+ }
3681
+ catch (e) {
3682
+ // if the user intentionally throws the original error in the handler,
3683
+ // do not log it twice
3684
+ if (e !== err) {
3685
+ logError(e, null, 'config.errorHandler');
3686
+ }
3687
+ }
3688
+ }
3689
+ logError(err, vm, info);
3690
+ }
3691
+ function logError(err, vm, info) {
3692
+ {
3693
+ warn$2("Error in ".concat(info, ": \"").concat(err.toString(), "\""), vm);
3694
+ }
3695
+ /* istanbul ignore else */
3696
+ if (inBrowser && typeof console !== 'undefined') {
3697
+ console.error(err);
3698
+ }
3699
+ else {
3700
+ throw err;
3701
+ }
3702
+ }
3703
+
3704
+ /* globals MutationObserver */
3705
+ var isUsingMicroTask = false;
3706
+ var callbacks = [];
3707
+ var pending = false;
3708
+ function flushCallbacks() {
3709
+ pending = false;
3710
+ var copies = callbacks.slice(0);
3711
+ callbacks.length = 0;
3712
+ for (var i = 0; i < copies.length; i++) {
3713
+ copies[i]();
3714
+ }
3715
+ }
3716
+ // Here we have async deferring wrappers using microtasks.
3717
+ // In 2.5 we used (macro) tasks (in combination with microtasks).
3718
+ // However, it has subtle problems when state is changed right before repaint
3719
+ // (e.g. #6813, out-in transitions).
3720
+ // Also, using (macro) tasks in event handler would cause some weird behaviors
3721
+ // that cannot be circumvented (e.g. #7109, #7153, #7546, #7834, #8109).
3722
+ // So we now use microtasks everywhere, again.
3723
+ // A major drawback of this tradeoff is that there are some scenarios
3724
+ // where microtasks have too high a priority and fire in between supposedly
3725
+ // sequential events (e.g. #4521, #6690, which have workarounds)
3726
+ // or even between bubbling of the same event (#6566).
3727
+ var timerFunc;
3728
+ // The nextTick behavior leverages the microtask queue, which can be accessed
3729
+ // via either native Promise.then or MutationObserver.
3730
+ // MutationObserver has wider support, however it is seriously bugged in
3731
+ // UIWebView in iOS >= 9.3.3 when triggered in touch event handlers. It
3732
+ // completely stops working after triggering a few times... so, if native
3733
+ // Promise is available, we will use it:
3734
+ /* istanbul ignore next, $flow-disable-line */
3735
+ if (typeof Promise !== 'undefined' && isNative(Promise)) {
3736
+ var p_1 = Promise.resolve();
3737
+ timerFunc = function () {
3738
+ p_1.then(flushCallbacks);
3739
+ // In problematic UIWebViews, Promise.then doesn't completely break, but
3740
+ // it can get stuck in a weird state where callbacks are pushed into the
3741
+ // microtask queue but the queue isn't being flushed, until the browser
3742
+ // needs to do some other work, e.g. handle a timer. Therefore we can
3743
+ // "force" the microtask queue to be flushed by adding an empty timer.
3744
+ if (isIOS)
3745
+ setTimeout(noop);
3746
+ };
3747
+ isUsingMicroTask = true;
3748
+ }
3749
+ else if (!isIE &&
3750
+ typeof MutationObserver !== 'undefined' &&
3751
+ (isNative(MutationObserver) ||
3752
+ // PhantomJS and iOS 7.x
3753
+ MutationObserver.toString() === '[object MutationObserverConstructor]')) {
3754
+ // Use MutationObserver where native Promise is not available,
3755
+ // e.g. PhantomJS, iOS7, Android 4.4
3756
+ // (#6466 MutationObserver is unreliable in IE11)
3757
+ var counter_1 = 1;
3758
+ var observer = new MutationObserver(flushCallbacks);
3759
+ var textNode_1 = document.createTextNode(String(counter_1));
3760
+ observer.observe(textNode_1, {
3761
+ characterData: true
3762
+ });
3763
+ timerFunc = function () {
3764
+ counter_1 = (counter_1 + 1) % 2;
3765
+ textNode_1.data = String(counter_1);
3766
+ };
3767
+ isUsingMicroTask = true;
3768
+ }
3769
+ else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {
3770
+ // Fallback to setImmediate.
3771
+ // Technically it leverages the (macro) task queue,
3772
+ // but it is still a better choice than setTimeout.
3773
+ timerFunc = function () {
3774
+ setImmediate(flushCallbacks);
3775
+ };
3776
+ }
3777
+ else {
3778
+ // Fallback to setTimeout.
3779
+ timerFunc = function () {
3780
+ setTimeout(flushCallbacks, 0);
3781
+ };
3782
+ }
3783
+ /**
3784
+ * @internal
3785
+ */
3786
+ function nextTick(cb, ctx) {
3787
+ var _resolve;
3788
+ callbacks.push(function () {
3789
+ if (cb) {
3790
+ try {
3791
+ cb.call(ctx);
3792
+ }
3793
+ catch (e) {
3794
+ handleError(e, ctx, 'nextTick');
3795
+ }
3796
+ }
3797
+ else if (_resolve) {
3798
+ _resolve(ctx);
3799
+ }
3800
+ });
3801
+ if (!pending) {
3802
+ pending = true;
3803
+ timerFunc();
3804
+ }
3805
+ // $flow-disable-line
3806
+ if (!cb && typeof Promise !== 'undefined') {
3807
+ return new Promise(function (resolve) {
3808
+ _resolve = resolve;
3809
+ });
3810
+ }
3811
+ }
3812
+
3813
+ function useCssModule(name) {
3814
+ /* istanbul ignore else */
3815
+ {
3816
+ {
3817
+ warn$2("useCssModule() is not supported in the global build.");
3818
+ }
3819
+ return emptyObject;
3820
+ }
3821
+ }
3822
+
3823
+ /**
3824
+ * Runtime helper for SFC's CSS variable injection feature.
3825
+ * @private
3826
+ */
3827
+ function useCssVars(getter) {
3828
+ if (!inBrowser && !false)
3829
+ return;
3830
+ var instance = currentInstance;
3831
+ if (!instance) {
3832
+ warn$2("useCssVars is called without current active component instance.");
3833
+ return;
3834
+ }
3835
+ watchPostEffect(function () {
3836
+ var el = instance.$el;
3837
+ var vars = getter(instance, instance._setupProxy);
3838
+ if (el && el.nodeType === 1) {
3839
+ var style = el.style;
3840
+ for (var key in vars) {
3841
+ style.setProperty("--".concat(key), vars[key]);
3842
+ }
3843
+ }
3844
+ });
3845
+ }
3846
+
3847
+ /**
3848
+ * v3-compatible async component API.
3849
+ * @internal the type is manually declared in <root>/types/v3-define-async-component.d.ts
3850
+ * because it relies on existing manual types
3851
+ */
3852
+ function defineAsyncComponent(source) {
3853
+ if (isFunction(source)) {
3854
+ source = { loader: source };
3855
+ }
3856
+ var loader = source.loader, loadingComponent = source.loadingComponent, errorComponent = source.errorComponent, _a = source.delay, delay = _a === void 0 ? 200 : _a, timeout = source.timeout, // undefined = never times out
3857
+ _b = source.suspensible, // undefined = never times out
3858
+ suspensible = _b === void 0 ? false : _b, // in Vue 3 default is true
3859
+ userOnError = source.onError;
3860
+ if (suspensible) {
3861
+ warn$2("The suspensiblbe option for async components is not supported in Vue2. It is ignored.");
3862
+ }
3863
+ var pendingRequest = null;
3864
+ var retries = 0;
3865
+ var retry = function () {
3866
+ retries++;
3867
+ pendingRequest = null;
3868
+ return load();
3869
+ };
3870
+ var load = function () {
3871
+ var thisRequest;
3872
+ return (pendingRequest ||
3873
+ (thisRequest = pendingRequest =
3874
+ loader()
3875
+ .catch(function (err) {
3876
+ err = err instanceof Error ? err : new Error(String(err));
3877
+ if (userOnError) {
3878
+ return new Promise(function (resolve, reject) {
3879
+ var userRetry = function () { return resolve(retry()); };
3880
+ var userFail = function () { return reject(err); };
3881
+ userOnError(err, userRetry, userFail, retries + 1);
3882
+ });
3883
+ }
3884
+ else {
3885
+ throw err;
3886
+ }
3887
+ })
3888
+ .then(function (comp) {
3889
+ if (thisRequest !== pendingRequest && pendingRequest) {
3890
+ return pendingRequest;
3891
+ }
3892
+ if (!comp) {
3893
+ warn$2("Async component loader resolved to undefined. " +
3894
+ "If you are using retry(), make sure to return its return value.");
3895
+ }
3896
+ // interop module default
3897
+ if (comp &&
3898
+ (comp.__esModule || comp[Symbol.toStringTag] === 'Module')) {
3899
+ comp = comp.default;
3900
+ }
3901
+ if (comp && !isObject(comp) && !isFunction(comp)) {
3902
+ throw new Error("Invalid async component load result: ".concat(comp));
3903
+ }
3904
+ return comp;
3905
+ })));
3906
+ };
3907
+ return function () {
3908
+ var component = load();
3909
+ return {
3910
+ component: component,
3911
+ delay: delay,
3912
+ timeout: timeout,
3913
+ error: errorComponent,
3914
+ loading: loadingComponent
3915
+ };
3916
+ };
3917
+ }
3918
+
3919
+ function createLifeCycle(hookName) {
3920
+ return function (fn, target) {
3921
+ if (target === void 0) { target = currentInstance; }
3922
+ if (!target) {
3923
+ warn$2("".concat(formatName(hookName), " is called when there is no active component instance to be ") +
3924
+ "associated with. " +
3925
+ "Lifecycle injection APIs can only be used during execution of setup().");
3926
+ return;
3927
+ }
3928
+ return injectHook(target, hookName, fn);
3929
+ };
3930
+ }
3931
+ function formatName(name) {
3932
+ if (name === 'beforeDestroy') {
3933
+ name = 'beforeUnmount';
3934
+ }
3935
+ else if (name === 'destroyed') {
3936
+ name = 'unmounted';
3937
+ }
3938
+ return "on".concat(name[0].toUpperCase() + name.slice(1));
3939
+ }
3940
+ function injectHook(instance, hookName, fn) {
3941
+ var options = instance.$options;
3942
+ options[hookName] = mergeLifecycleHook(options[hookName], fn);
3943
+ }
3944
+ var onBeforeMount = createLifeCycle('beforeMount');
3945
+ var onMounted = createLifeCycle('mounted');
3946
+ var onBeforeUpdate = createLifeCycle('beforeUpdate');
3947
+ var onUpdated = createLifeCycle('updated');
3948
+ var onBeforeUnmount = createLifeCycle('beforeDestroy');
3949
+ var onUnmounted = createLifeCycle('destroyed');
3950
+ var onErrorCaptured = createLifeCycle('errorCaptured');
3951
+ var onActivated = createLifeCycle('activated');
3952
+ var onDeactivated = createLifeCycle('deactivated');
3953
+ var onServerPrefetch = createLifeCycle('serverPrefetch');
3954
+ var onRenderTracked = createLifeCycle('renderTracked');
3955
+ var onRenderTriggered = createLifeCycle('renderTriggered');
3956
+
3957
+ /**
3958
+ * Note: also update dist/vue.runtime.mjs when adding new exports to this file.
3959
+ */
3960
+ var version = '2.7.8';
3961
+ /**
3962
+ * @internal type is manually declared in <root>/types/v3-define-component.d.ts
3963
+ */
3964
+ function defineComponent(options) {
3965
+ return options;
3966
+ }
3967
+
3968
+ var vca = /*#__PURE__*/Object.freeze({
3969
+ __proto__: null,
3970
+ version: version,
3971
+ defineComponent: defineComponent,
3972
+ ref: ref$1,
3973
+ shallowRef: shallowRef,
3974
+ isRef: isRef,
3975
+ toRef: toRef,
3976
+ toRefs: toRefs,
3977
+ unref: unref,
3978
+ proxyRefs: proxyRefs,
3979
+ customRef: customRef,
3980
+ triggerRef: triggerRef,
3981
+ reactive: reactive,
3982
+ isReactive: isReactive,
3983
+ isReadonly: isReadonly,
3984
+ isShallow: isShallow,
3985
+ isProxy: isProxy,
3986
+ shallowReactive: shallowReactive,
3987
+ markRaw: markRaw,
3988
+ toRaw: toRaw,
3989
+ readonly: readonly,
3990
+ shallowReadonly: shallowReadonly,
3991
+ computed: computed,
3992
+ watch: watch,
3993
+ watchEffect: watchEffect,
3994
+ watchPostEffect: watchPostEffect,
3995
+ watchSyncEffect: watchSyncEffect,
3996
+ EffectScope: EffectScope,
3997
+ effectScope: effectScope,
3998
+ onScopeDispose: onScopeDispose,
3999
+ getCurrentScope: getCurrentScope,
4000
+ provide: provide,
4001
+ inject: inject,
4002
+ h: h,
4003
+ getCurrentInstance: getCurrentInstance,
4004
+ useSlots: useSlots,
4005
+ useAttrs: useAttrs,
4006
+ useListeners: useListeners,
4007
+ mergeDefaults: mergeDefaults,
4008
+ nextTick: nextTick,
4009
+ set: set,
4010
+ del: del,
4011
+ useCssModule: useCssModule,
4012
+ useCssVars: useCssVars,
4013
+ defineAsyncComponent: defineAsyncComponent,
4014
+ onBeforeMount: onBeforeMount,
4015
+ onMounted: onMounted,
4016
+ onBeforeUpdate: onBeforeUpdate,
4017
+ onUpdated: onUpdated,
4018
+ onBeforeUnmount: onBeforeUnmount,
4019
+ onUnmounted: onUnmounted,
4020
+ onErrorCaptured: onErrorCaptured,
4021
+ onActivated: onActivated,
4022
+ onDeactivated: onDeactivated,
4023
+ onServerPrefetch: onServerPrefetch,
4024
+ onRenderTracked: onRenderTracked,
4025
+ onRenderTriggered: onRenderTriggered
4026
+ });
4027
+
4028
+ var seenObjects = new _Set();
4029
+ /**
4030
+ * Recursively traverse an object to evoke all converted
4031
+ * getters, so that every nested property inside the object
4032
+ * is collected as a "deep" dependency.
4033
+ */
4034
+ function traverse(val) {
4035
+ _traverse(val, seenObjects);
4036
+ seenObjects.clear();
4037
+ return val;
4038
+ }
4039
+ function _traverse(val, seen) {
4040
+ var i, keys;
4041
+ var isA = isArray(val);
4042
+ if ((!isA && !isObject(val)) ||
4043
+ Object.isFrozen(val) ||
4044
+ val instanceof VNode) {
4045
+ return;
4046
+ }
4047
+ if (val.__ob__) {
4048
+ var depId = val.__ob__.dep.id;
4049
+ if (seen.has(depId)) {
4050
+ return;
4051
+ }
4052
+ seen.add(depId);
4053
+ }
4054
+ if (isA) {
4055
+ i = val.length;
4056
+ while (i--)
4057
+ _traverse(val[i], seen);
4058
+ }
4059
+ else if (isRef(val)) {
4060
+ _traverse(val.value, seen);
4061
+ }
4062
+ else {
4063
+ keys = Object.keys(val);
4064
+ i = keys.length;
4065
+ while (i--)
4066
+ _traverse(val[keys[i]], seen);
4067
+ }
4068
+ }
4069
+
4070
+ var uid$1 = 0;
4071
+ /**
4072
+ * A watcher parses an expression, collects dependencies,
4073
+ * and fires callback when the expression value changes.
4074
+ * This is used for both the $watch() api and directives.
4075
+ * @internal
4076
+ */
4077
+ var Watcher = /** @class */ (function () {
4078
+ function Watcher(vm, expOrFn, cb, options, isRenderWatcher) {
4079
+ recordEffectScope(this, activeEffectScope || (vm ? vm._scope : undefined));
4080
+ if ((this.vm = vm)) {
4081
+ if (isRenderWatcher) {
4082
+ vm._watcher = this;
4083
+ }
4084
+