diff --git a/notemyprogress/ajax.php b/notemyprogress/ajax.php
index 1bd5ed4b377c9e9d30eb521c0dd39c70ad71774a..a2fb52b92b808a54f6ad7d8ab3c516d0fcb4dd41 100644
--- a/notemyprogress/ajax.php
+++ b/notemyprogress/ajax.php
@@ -73,6 +73,7 @@ $settings= optional_param('settings', false ,PARAM_TEXT);
 $url= optional_param('url', false ,PARAM_TEXT);
 //$courseid = optional_param('modulename', false ,PARAM_TEXT);
 $enable = optional_param('enable', false ,PARAM_BOOL);
+$section = optional_param('section',false,PARAM_TEXT);
 
 /*                                               */ 
 
@@ -193,17 +194,35 @@ if($action == 'saveconfigweek') {//Exemple: if the action passed is saveconfigwe
     array_push($params, $levels);
     array_push($params, $settings);
     array_push($params, $url);
-    array_push($params, $enable);
+    array_push($params, $section);
     if($courseid && $userid && $rules && $levels && $settings && $url) {
         $func = "local_notemyprogress_save_gamification_config";
     }
 }elseif($action =='rankable'){
     array_push($params, $courseid);
     array_push($params, $userid);
+    array_push($params, $url);
     if($courseid && $userid) {
         $func = "local_notemyprogress_set_rankable_player";
     }
-}
+}elseif($action =='saveEnable'){
+    array_push($params, $courseid);
+    array_push($params, $userid);
+    array_push($params,$enable);
+    array_push($params,$url);
+    if($courseid && $userid) {
+        $func = "local_notemyprogress_save_enable";
+    }
+}elseif($action =='studentGamificationViewed'){
+    array_push($params, $courseid);
+    array_push($params, $userid);
+    array_push($params,$url);
+    if($courseid && $userid) {
+        $func = "local_notemyprogress_viewed_student_lvl";
+    }
+}        
+
+
 
 if(isset($params) && isset($func)){
     call_user_func_array($func, $params);
@@ -337,7 +356,6 @@ function local_notemyprogress_get_student_sessions($weekcode, $courseid, $userid
 
 function local_notemyprogress_downloadMoodleLogs($beginDate, $lastDate, $courseid, $userid, $currentUrl) {
     $logs = new \local_notemyprogress\logs($courseid, $userid);
-
     $logs->addLogsNMP("downloaded", "logfile", "LOGFILES", "moodle", $currentUrl, "File that contains all the activities performed on the Note My Progress plugin in a time interval");
     $jsonData = $logs->searchLogsMoodle($beginDate, $lastDate);
     local_notemyprogress_ajax_response(array("jsonData"=>$jsonData));
@@ -348,31 +366,42 @@ function local_notemyprogress_addLogs($sectionname, $actiontype, $courseid, $use
     $logs->addLogsNMP($actiontype, $objectType, $sectionname, $objectName, $currentUrl, $objectDescription);
     local_notemyprogress_ajax_response(array("ok"=>"ok"));
 }
-function local_notemyprogress_save_gamification_config($courseid, $userid, $rules, $levels, $settings, $url,$enable){
-    // \local_notemyprogress\logs::create(
-    //     "setgamification",
-    //     "configweeks",
-    //     "saved",
-    //     "weeks_settings",
-    //     $url,
-    //     4,
-    //     $userid,
-    //     $courseid
-    // );
- 
+function local_notemyprogress_save_gamification_config($courseid, $userid, $rules, $levels, $settings, $url,$section){
+    $logs = new \local_notemyprogress\logs($courseid, $userid);
+    $logs->addLogsNMP("Saved", $section, "CONFIGURATION_GAMIFICATION", "configuration_gamification", $url, "GamificationSaved");
+
      $configLevels = new \local_notemyprogress\configgamification($courseid, $userid);
      $configLevels->save_levels($levels, $settings, $rules);
-     $configLevels->save_enable($enable);
+     //$configLevels->save_enable($enable);
      $message = get_string('fml_api_save_successful', 'local_notemyprogress');
      local_notemyprogress_ajax_response($message);
  }
 
-function local_notemyprogress_set_rankable_player($courseid, $userid){
+function local_notemyprogress_set_rankable_player($courseid, $userid,$url){
+    $logs = new \local_notemyprogress\logs($courseid, $userid);
+    $logs->addLogsNMP("Saved", "section", "STUDENT_GAMIFICATION", "student_gamification", $url, "GamificationSaved");
     GLobal $DB;
-    // $sql = "update {notemyprogress_xp} set rankable = ? where courseid = ? and userid = ?";
-    // $DB->execute($sql, array(1,$courseid, $userid));
-    $sql = "UPDATE {notemyprogress_xp} SET rankable = 1 WHERE courseid = 2 AND userid = 3";
-    $DB->execute($sql);
+    $sql = "update {notemyprogress_xp} set rankable = ? where courseid = ? and userid = ?";
+    $DB->execute($sql, array(1,$courseid, $userid));
+    // $sql = "UPDATE {notemyprogress_xp} SET rankable = 1 WHERE courseid = 2 AND userid = 3";
+    // $DB->execute($sql);
     $message = get_string('fml_api_save_successful', 'local_notemyprogress');
     local_notemyprogress_ajax_response($message);
-}
\ No newline at end of file
+}
+
+function local_notemyprogress_save_enable($courseid, $userid, $enable,$url){
+    $logs = new \local_notemyprogress\logs($courseid, $userid);
+    $logs->addLogsNMP("Saved", "section", "CONFIGURATION_GAMIFICATION", "configuration_gamification", $url, "GamificationSaved");
+     $configLevels = new \local_notemyprogress\configgamification($courseid, $userid);
+     $configLevels->save_enable($enable);
+     $message = get_string('fml_api_save_successful', 'local_notemyprogress');
+     local_notemyprogress_ajax_response($message);
+ }
+ function local_notemyprogress_viewed_student_lvl($courseid, $userid,$url){
+    $logs = new \local_notemyprogress\logs($courseid, $userid);
+    $logs->addLogsNMP("Viewed", "section", "STUDENT_GAMIFICATION", "student_gamification", $url, "GamificationSaved");;
+    //  $configLevels = new \local_notemyprogress\configgamification($courseid, $userid);
+    //  $configLevels->save_enable($enable);
+    //  $message = get_string('fml_api_save_successful', 'local_notemyprogress');
+    //  local_notemyprogress_ajax_response($message);
+ }
\ No newline at end of file
diff --git a/notemyprogress/amd/build/gamification.js b/notemyprogress/amd/build/gamification.js
index e83c2b5d5dcc9c72007e142993c3987a557cc6d6..5ba1ae7061ea5405269a932cd210be99e41a35be 100644
--- a/notemyprogress/amd/build/gamification.js
+++ b/notemyprogress/amd/build/gamification.js
@@ -4,13 +4,15 @@ define([
   "local_notemyprogress/axios",
   "local_notemyprogress/alertify",
   "local_notemyprogress/pageheader",
-], function (Vue, Vuetify, Axios, Alertify, PageHeader) {
+  "local_notemyprogress/chartdynamic",
+], function (Vue, Vuetify, Axios, Alertify, PageHeader, ChartDynamic) {
   "use strict";
 
   function init(content) {
-    //console.log(content);
+    console.log(content);
     Vue.use(Vuetify);
     Vue.component("pageheader", PageHeader);
+    Vue.component("chart", ChartDynamic);
     const app = new Vue({
       delimiters: ["[[", "]]"],
       el: "#gamification",
@@ -33,7 +35,13 @@ define([
         setPointsOption: "calculated",
         pointsBase: 0,
         pointsBaseOri: 0,
-        swDisableEnable: "",
+        swDisableEnable: content.strings.swValue,
+        spreadData: [],
+        week_resources_categories: [],
+        week_resources_data: [],
+        week_resources_colors: "#FA4641",
+        indicators: content.indicators,
+        chartdata: content.chart_data,
       },
 
       beforeMount() {},
@@ -113,10 +121,11 @@ define([
           }
           return parseInt(x);
         },
-        save_changes() {
+        save_changes(logParam) {
           this.notifications = ["Do you want to save the changes"];
           Alertify.confirm(this.strings.save_warning_content, () => {
-            this.saveGamificationConfig();
+            this.saveGamificationConfig(logParam);
+            console.log(logParam);
           }) // ON CONFIRM
             .set({ title: this.strings.save_warning_title })
             .set({
@@ -126,7 +135,7 @@ define([
               },
             });
         },
-        saveGamificationConfig() {
+        saveGamificationConfig(logParam) {
           this.loading = true;
           let settings = {
             tit: this.settings.tit,
@@ -142,10 +151,10 @@ define([
             rules: JSON.stringify(this.rulesData),
             token: this.token,
             enable: this.enable,
+            section: logParam,
           };
           let url = { url: window.location.href };
           Axios({
-            ///! try resolve that with a listener
             method: "post",
             url:
               M.cfg.wwwroot +
@@ -162,8 +171,10 @@ define([
               "&url=" +
               url.url +
               "&enable=" +
-              data.enable,
-            data: data,
+              data.enable +
+              "&section=" +
+              data.section,
+            params: data,
           })
             .then((response) => {
               // console.log(response);
@@ -213,7 +224,204 @@ define([
         disableEnable(swDisableEnable) {
           //traitement
           this.enable = swDisableEnable;
+          let data = {
+            courseid: this.courseid,
+            userid: this.userid,
+            action: "saveEnable",
+            enable: this.enable,
+          };
+          Axios({
+            method: "get",
+            url: M.cfg.wwwroot + "/local/notemyprogress/ajax.php",
+            params: data,
+          })
+            .then((response) => {
+              if (response.status == 200 && response.data.ok) {
+                this.showNotifications(response.data.data, "success");
+              } else {
+                let message =
+                  response.data.error || this.strings.api_error_network;
+                this.showNotifications(message, "error"); //in this line "error" define the kind of message send
+              }
+            })
+            .catch((e) => {
+              let message = e.response.data || this.strings.api_error_network;
+              this.showNotifications(message, "error");
+            })
+            .finally(() => {
+              this.loading = false;
+            });
+        },
+        //? ////////////////////////////////////////////////////////////////////// ?//
+        //? //////////////////////////// ChartPart /////////////////////////////// ?//
+        //? ////////////////////////////////////////////////////////////////////// ?//
+        chart_spread() {
+          let chart = new Object();
+          chart.chart = {
+            type: "column",
+            backgroundColor: null,
+          };
+          chart.title = {
+            text: this.strings.chartTitle,
+          };
+          chart.colors = ["#118AB2"];
+          (chart.xAxis = {
+            type: "category",
+            labels: {
+              rotation: -45,
+              style: {
+                fontSize: "13px",
+                fontFamily: "Verdana, sans-serif",
+              },
+            },
+          }),
+            (chart.yAxis = {
+              min: 0,
+              title: {
+                text: this.strings.chartYaxis,
+              },
+            });
+          chart.legend = {
+            enabled: false,
+          };
+          (chart.series = [
+            {
+              name: null,
+              data: this.chartdata, //[["level : 1", 1]],
+              dataLabels: {
+                enabled: true,
+                rotation: -90,
+                color: "#FFFFFF",
+                align: "right",
+                format: "{point.y:.1f}", // one decimal
+                y: 10, // 10 pixels down from the top
+                style: {
+                  fontSize: "13px",
+                  fontFamily: "Verdana, sans-serif",
+                },
+              },
+            },
+          ]),
+            console.log("series: ");
+          console.log(chart.series);
+          return chart;
         },
+        /*
+        build_inverted_time_chart() {
+          console.log("enter build_inverted_time_chart ");
+          //console.log(this.students_planification);
+          //console.log("this.data_report_meta_hours = ");
+          //console.log(this.data_report_meta_hours);
+          let chart = new Object();
+          let meta = new Object();
+          meta = this.chartdata_hours_week_dedication();
+          console.log("meta = ");
+          console.log(meta);
+          let invest = [
+            {
+              name: meta.labels[0],
+              y: meta.datasets[0].data[0],
+            },
+            {
+              name: meta.labels[1],
+              y: meta.datasets[0].data[1],
+            },
+            {
+              name: meta.labels[2],
+              y: meta.datasets[0].data[2],
+            },
+          ];
+          console.log("invest = ");
+          console.log(invest);
+          chart.chart = {
+            type: "bar",
+            backgroundColor: null,
+            style: { fontFamily: "poppins" },
+          };
+          chart.title = { text: null };
+          chart.colors = this.inverted_time_colors;
+          chart.xAxis = {
+            type: "category",
+            crosshair: true,
+          };
+          chart.yAxis = {
+            title: {
+              text: "Framboise",
+            },
+          };
+          chart.tooltip = {
+            shared: true,
+            useHTML: true,
+            formatter: function () {
+              let category_name = this.points[0].key;
+              let time = vue.convert_time(this.y);
+              return `<b>${category_name}: </b>${time}`;
+            },
+          };
+          chart.legend = {
+            enabled: false,
+          };
+          chart.series = [
+            {
+              colorByPoint: true,
+              data: invest,
+            },
+          ];
+          //console.log("this.inverted_time.data = ");
+          //console.log(this.inverted_time.data);
+
+          // console.log("invest = ");
+          // console.log(invest);
+          return chart;
+        },
+        chartdata_hours_week_dedication() {
+          var data = new Object();
+          data.datasets = [];
+
+          let inverted =
+            this.render_has == "teacher"
+              ? this.strings.inverted_time
+              : `${this.strings.myself} ${this.strings.inverted_time}`;
+          let planified =
+            this.render_has == "teacher"
+              ? this.strings.planified_time
+              : `${this.strings.myself} ${this.strings.planified_time}`;
+          data.labels = [inverted, planified];
+          var dataset = new Object();
+          dataset.label = "Horas";
+          //console.log("data_report_meta_hours in chartdata_hours_week_dedication  = ");
+          //console.log(this.data_report_meta_hours);
+          dataset.data = [
+            parseFloat(this.data_report_meta_hours.horas_trabajadas),
+            parseInt(this.data_report_meta_hours.horas_planificadas),
+          ];
+          dataset.backgroundColor = ["#ffa700", "#a0c2fa"];
+          dataset.borderWidth = 0;
+          data.datasets.push(dataset);
+
+          //if (this.render_has == "student" && this.compare_with_course) {
+          data.labels.splice(1, 0, this.strings.inverted_time_course);
+          //data.labels.splice(3, 0, this.strings.planified_time_course);
+          dataset.data.splice(
+            1,
+            0,
+            parseFloat(this.course_report_hours.horas_trabajadas)
+          );
+          // dataset.data.splice(
+          //   3,
+          //   0,
+          //   parseFloat(this.course_report_hours.horas_planificadas)
+          // );
+          dataset.backgroundColor.splice(1, 0, "#ffa700");
+          //dataset.backgroundColor.splice(3, 0, "#a0c2fa");
+          //}
+          //console.log("data_report_meta_hours = ");
+          //console.log(this.data_report_meta_hours);
+
+          //console.log("data = ");
+          //console.log(data);
+          return data;
+        },*/
       },
     });
   }
diff --git a/notemyprogress/amd/build/listener.min.js b/notemyprogress/amd/build/listener.min.js
index f7412851521e015dd04ea00d52bd076ea76c2e2e..577b33cb6aedc1b3b10838f0ef40f60696806187 100644
--- a/notemyprogress/amd/build/listener.min.js
+++ b/notemyprogress/amd/build/listener.min.js
@@ -1 +1,11 @@
-define([],function(){return{init:function(){document.querySelector("#downloadButton").addEventListener("click",function(){console.log("clicked !")})}}});
\ No newline at end of file
+define([], function () {
+  return {
+    init: function () {
+      document
+        .querySelector("#downloadButton")
+        .addEventListener("click", function () {
+          console.log("clicked !");
+        });
+    },
+  };
+});
diff --git a/notemyprogress/amd/build/student_gamification.js b/notemyprogress/amd/build/student_gamification.js
index a77d864883406dae90330837bdfab7cd94e991d2..d7fb47847300386cc9b36ae99c5382f37b04e6d9 100644
--- a/notemyprogress/amd/build/student_gamification.js
+++ b/notemyprogress/amd/build/student_gamification.js
@@ -31,7 +31,18 @@ define([
         error_messages: [],
         save_successful: false,
       },
-      beforeMount() {},
+      beforeMount() {
+        let data = {
+          courseid: this.courseid,
+          userid: this.userid,
+          action: "studentGamificationViewed",
+        };
+        Axios({
+          method: "get",
+          url: M.cfg.wwwroot + "/local/notemyprogress/ajax.php",
+          params: data,
+        });
+      },
       computed: {},
       methods: {
         get_help_content() {
diff --git a/notemyprogress/amd/build/teacher.js b/notemyprogress/amd/build/teacher.js
new file mode 100644
index 0000000000000000000000000000000000000000..59e8e40d2f52b57d58a94dc6da977a237f792f03
--- /dev/null
+++ b/notemyprogress/amd/build/teacher.js
@@ -0,0 +1,305 @@
+define([
+  "local_notemyprogress/vue",
+  "local_notemyprogress/vuetify",
+  "local_notemyprogress/axios",
+  "local_notemyprogress/pagination",
+  "local_notemyprogress/chartstatic",
+  "local_notemyprogress/pageheader",
+  "local_notemyprogress/helpdialog",
+], function (
+  Vue,
+  Vuetify,
+  Axios,
+  Pagination,
+  ChartStatic,
+  PageHeader,
+  HelpDialog
+) {
+  "use strict";
+
+  function init(content) {
+    // console.log(content);
+    Vue.use(Vuetify);
+    Vue.component("pagination", Pagination);
+    Vue.component("chart", ChartStatic);
+    Vue.component("pageheader", PageHeader);
+    Vue.component("helpdialog", HelpDialog);
+    let vue = new Vue({
+      delimiters: ["[[", "]]"],
+      el: "#teacher",
+      vuetify: new Vuetify(),
+      data() {
+        return {
+          strings: content.strings,
+          groups: content.groups,
+          userid: content.userid,
+          courseid: content.courseid,
+          timezone: content.timezone,
+          render_has: content.profile_render,
+
+          indicators: content.indicators,
+          week_resources_colors: content.week_resources_colors,
+          search: null,
+          week_resources_categories: [],
+          week_resources_data: [],
+
+          help_dialog: false,
+          help_contents: [],
+        };
+      },
+      beforeMount() {
+        this.calculate_week_resources();
+      },
+      mounted() {
+        document.querySelector("#sessions-loader").style.display = "none";
+        document.querySelector("#teacher").style.display = "block";
+      },
+      methods: {
+        get_help_content() {
+          let contents = [];
+          contents.push({
+            title: this.strings.section_help_title,
+            description: this.strings.section_help_description,
+          });
+          return contents;
+        },
+
+        get_course_grade() {
+          let grade = Number(this.indicators.course.grademax);
+          return this.isInt(grade) ? grade : grade.toFixed(2);
+        },
+
+        calculate_week_resources() {
+          let categories = [],
+            data = [];
+          let week_name;
+          this.indicators.weeks.forEach((week) => {
+            week_name = `${week.name} ${week.position + 1}`;
+            categories.push(week_name);
+            data.push(week.cms);
+          });
+          let name = this.capitalizeFirstLetter(
+            this.strings.teacher_indicators_modules
+          );
+          this.week_resources_categories = categories;
+          this.week_resources_data = [{ name, data }];
+        },
+
+        build_week_resources_chart() {
+          let chart = new Object();
+          chart.chart = {
+            type: "bar",
+            backgroundColor: null,
+            style: { fontFamily: "poppins" },
+          };
+          chart.title = {
+            text: null,
+          };
+          chart.colors = this.week_resources_colors;
+          chart.xAxis = {
+            categories: this.week_resources_categories,
+          };
+          chart.yAxis = {
+            min: 0,
+            title: {
+              text: this.strings.teacher_indicators_week_resources_yaxis_title,
+            },
+          };
+          chart.legend = {
+            enabled: false,
+          };
+          chart.series = this.week_resources_data;
+          console.log(chart.series);
+          return chart;
+        },
+
+        build_weeks_sessions_chart() {
+          let chart = new Object();
+          chart.chart = {
+            type: "heatmap",
+            backgroundColor: null,
+            style: { fontFamily: "poppins" },
+          };
+          chart.title = {
+            text: null,
+          };
+          chart.xAxis = {
+            categories: this.strings.weeks,
+          };
+          chart.yAxis = {
+            categories: this.indicators.sessions.categories,
+            title: null,
+            reversed: true,
+          };
+          chart.colorAxis = {
+            min: 0,
+            minColor: "#E0E0E0",
+            maxColor: "#118AB2",
+          };
+          chart.legend = {
+            layout: "horizontal",
+            verticalAlign: "bottom",
+          };
+          chart.tooltip = {
+            formatter: function () {
+              let days =
+                vue.indicators.sessions.weeks[this.point.y][this.point.x] || "";
+              let xCategoryName = vue.get_point_category_name(this.point, "x");
+              let yCategoryName = vue.get_point_category_name(this.point, "y");
+              let label = vue.strings.teacher_indicators_sessions;
+              if (this.point.value == 1) {
+                label = vue.strings.teacher_indicators_session;
+              }
+              return (
+                "<b>" +
+                yCategoryName +
+                " " +
+                xCategoryName +
+                "</b>: " +
+                this.point.value +
+                " " +
+                label +
+                "<br/>" +
+                days
+              );
+            },
+          };
+          chart.series = [
+            {
+              borderWidth: 2,
+              borderColor: "#FAFAFA",
+              data: this.indicators.sessions.data,
+            },
+          ];
+          return chart;
+        },
+
+        table_headers() {
+          let headers = [
+            { text: "", value: "id", align: "center", sortable: false },
+            { text: this.strings.thead_name, value: "firstname" },
+            { text: this.strings.thead_lastname, value: "lastname" },
+            { text: this.strings.thead_email, value: "email" },
+            {
+              text: this.strings.thead_progress,
+              value: "progress_percentage",
+              align: "center",
+            },
+            {
+              text: this.strings.thead_sessions,
+              value: "sessions_number",
+              align: "center",
+            },
+            {
+              text: this.strings.thead_time,
+              value: "inverted_time",
+              align: "center",
+            },
+          ];
+          return headers;
+        },
+
+        get_picture_url(userid) {
+          let url = `${M.cfg.wwwroot}/user/pix.php?file=/${userid}/f1.jpg`;
+          return url;
+        },
+
+        get_percentage_progress(value) {
+          return `${value} %`;
+        },
+
+        get_progress_tooltip(item) {
+          let module_label = this.strings.teacher_indicators_modules;
+          let finished_label = this.strings.teacher_indicators_finished;
+          if (item.cms.complete == 1) {
+            module_label = this.strings.teacher_indicators_module;
+            finished_label = this.strings.teacher_indicators_finalized;
+          }
+          return `${item.cms.complete} ${module_label} ${finished_label} ${this.strings.of_conector} ${item.cms.total}`;
+        },
+
+        get_point_category_name(point, dimension) {
+          let series = point.series,
+            isY = dimension === "y",
+            axis = series[isY ? "yAxis" : "xAxis"];
+          return axis.categories[point[isY ? "y" : "x"]];
+        },
+
+        capitalizeFirstLetter(string) {
+          return string.charAt(0).toUpperCase() + string.slice(1);
+        },
+
+        isInt(n) {
+          return n % 1 === 0;
+        },
+
+        open_chart_help(chart) {
+          let contents = [];
+          if (chart == "week_resources") {
+            contents.push({
+              title: this.strings.week_resources_help_title,
+              description: this.strings.week_resources_help_description_p1,
+            });
+            contents.push({
+              description: this.strings.week_resources_help_description_p2,
+            });
+          } else if (chart == "weeks_sessions") {
+            contents.push({
+              title: this.strings.weeks_sessions_help_title,
+              description: this.strings.week_sessions_help_description_p1,
+            });
+            contents.push({
+              description: this.strings.week_sessions_help_description_p2,
+            });
+          } else if (chart == "progress_table") {
+            contents.push({
+              title: this.strings.progress_table_help_title,
+              description: this.strings.progress_table_help_description,
+            });
+          }
+          this.help_contents = contents;
+          if (this.help_contents.length) {
+            this.help_dialog = true;
+          }
+        },
+
+        update_help_dialog(value) {
+          this.help_dialog = value;
+        },
+
+        get_timezone() {
+          let information = `${this.strings.ss_change_timezone} ${this.timezone}`;
+          return information;
+        },
+
+        addLogsIntoDB(action, objectName, objectType, objectDescription) {
+          let data = {
+            courseid: content.courseid,
+            userid: content.userid,
+            action: "addLogs",
+            sectionname: "TEACHER_GENERAL_INDICATORS",
+            actiontype: action,
+            objectType: objectType,
+            objectName: objectName,
+            currentUrl: document.location.href,
+            objectDescription: objectDescription,
+          };
+          Axios({
+            method: "get",
+            url: M.cfg.wwwroot + "/local/notemyprogress/ajax.php",
+            params: data,
+          })
+            .then((response) => {
+              if (response.status == 200 && response.data.ok) {
+              }
+            })
+            .catch((e) => {});
+        },
+      },
+    });
+  }
+
+  return {
+    init: init,
+  };
+});
diff --git a/notemyprogress/amd/build/teacher.min.js b/notemyprogress/amd/build/teacher.min.js
deleted file mode 100644
index 7b49e25001efbe51976e1ee2eb2274b2f88de329..0000000000000000000000000000000000000000
--- a/notemyprogress/amd/build/teacher.min.js
+++ /dev/null
@@ -1,2 +0,0 @@
-define(["local_notemyprogress/vue","local_notemyprogress/vuetify","local_notemyprogress/axios","local_notemyprogress/pagination","local_notemyprogress/chartstatic","local_notemyprogress/pageheader","local_notemyprogress/helpdialog"],function(e,t,s,i,r,o,n){"use strict";return{init:function(a){e.use(t),e.component("pagination",i),e.component("chart",r),e.component("pageheader",o),e.component("helpdialog",n);let l=new e({delimiters:["[[","]]"],el:"#teacher",vuetify:new t,data:()=>({strings:a.strings,groups:a.groups,userid:a.userid,courseid:a.courseid,timezone:a.timezone,render_has:a.profile_render,indicators:a.indicators,week_resources_colors:a.week_resources_colors,search:null,week_resources_categories:[],week_resources_data:[],help_dialog:!1,help_contents:[]}),beforeMount(){this.calculate_week_resources()},mounted(){document.querySelector("#sessions-loader").style.display="none",document.querySelector("#teacher").style.display="block"},methods:{get_help_content(){let e=[];return e.push({title:this.strings.section_help_title,description:this.strings.section_help_description}),e},get_course_grade(){let e=Number(this.indicators.course.grademax);return this.isInt(e)?e:e.toFixed(2)},calculate_week_resources(){let e,t=[],s=[];this.indicators.weeks.forEach(i=>{e=`${i.name} ${i.position+1}`,t.push(e),s.push(i.cms)});let i=this.capitalizeFirstLetter(this.strings.teacher_indicators_modules);this.week_resources_categories=t,this.week_resources_data=[{name:i,data:s}]},build_week_resources_chart(){let e=new Object;return e.chart={type:"bar",backgroundColor:null,style:{fontFamily:"poppins"}},e.title={text:null},e.colors=this.week_resources_colors,e.xAxis={categories:this.week_resources_categories},e.yAxis={min:0,title:{text:this.strings.teacher_indicators_week_resources_yaxis_title}},e.legend={enabled:!1},e.series=this.week_resources_data,e},build_weeks_sessions_chart(){let e=new Object;return e.chart={type:"heatmap",backgroundColor:null,style:{fontFamily:"poppins"}},e.title={text:null},e.xAxis={categories:this.strings.weeks},e.yAxis={categories:this.indicators.sessions.categories,title:null,reversed:!0},e.colorAxis={min:0,minColor:"#E0E0E0",maxColor:"#118AB2"},e.legend={layout:"horizontal",verticalAlign:"bottom"},e.tooltip={formatter:function(){let e=l.indicators.sessions.weeks[this.point.y][this.point.x]||"",t=l.get_point_category_name(this.point,"x"),s=l.get_point_category_name(this.point,"y"),i=l.strings.teacher_indicators_sessions;return 1==this.point.value&&(i=l.strings.teacher_indicators_session),"<b>"+s+" "+t+"</b>: "+this.point.value+" "+i+"<br/>"+e}},e.series=[{borderWidth:2,borderColor:"#FAFAFA",data:this.indicators.sessions.data}],e},table_headers(){return[{text:"",value:"id",align:"center",sortable:!1},{text:this.strings.thead_name,value:"firstname"},{text:this.strings.thead_lastname,value:"lastname"},{text:this.strings.thead_email,value:"email"},{text:this.strings.thead_progress,value:"progress_percentage",align:"center"},{text:this.strings.thead_sessions,value:"sessions_number",align:"center"},{text:this.strings.thead_time,value:"inverted_time",align:"center"}]},get_picture_url:e=>`${M.cfg.wwwroot}/user/pix.php?file=/${e}/f1.jpg`,get_percentage_progress:e=>`${e} %`,get_progress_tooltip(e){let t=this.strings.teacher_indicators_modules,s=this.strings.teacher_indicators_finished;return 1==e.cms.complete&&(t=this.strings.teacher_indicators_module,s=this.strings.teacher_indicators_finalized),`${e.cms.complete} ${t} ${s} ${this.strings.of_conector} ${e.cms.total}`},get_point_category_name(e,t){let s="y"===t;return e.series[s?"yAxis":"xAxis"].categories[e[s?"y":"x"]]},capitalizeFirstLetter:e=>e.charAt(0).toUpperCase()+e.slice(1),isInt:e=>e%1==0,open_chart_help(e){let t=[];"week_resources"==e?(t.push({title:this.strings.week_resources_help_title,description:this.strings.week_resources_help_description_p1}),t.push({description:this.strings.week_resources_help_description_p2})):"weeks_sessions"==e?(t.push({title:this.strings.weeks_sessions_help_title,description:this.strings.week_sessions_help_description_p1}),t.push({description:this.strings.week_sessions_help_description_p2})):"progress_table"==e&&t.push({title:this.strings.progress_table_help_title,description:this.strings.progress_table_help_description}),this.help_contents=t,this.help_contents.length&&(this.help_dialog=!0)},update_help_dialog(e){this.help_dialog=e},get_timezone(){return`${this.strings.ss_change_timezone} ${this.timezone}`},addLogsIntoDB(e,t,i,r){let o={courseid:a.courseid,userid:a.userid,action:"addLogs",sectionname:"TEACHER_GENERAL_INDICATORS",actiontype:e,objectType:i,objectName:t,currentUrl:document.location.href,objectDescription:r};s({method:"get",url:M.cfg.wwwroot+"/local/notemyprogress/ajax.php",params:o}).then(e=>{200==e.status&&e.data.ok}).catch(e=>{})}}})}}});
-//# sourceMappingURL=teacher.min.js.map
diff --git a/notemyprogress/amd/build/teacher.min.js.map b/notemyprogress/amd/build/teacher.min.js.map
deleted file mode 100644
index 6579b63acd185dff389ab267b839dbee24635552..0000000000000000000000000000000000000000
--- a/notemyprogress/amd/build/teacher.min.js.map
+++ /dev/null
@@ -1 +0,0 @@
-{"version":3,"sources":["../src/teacher.js"],"names":["define","Vue","Vuetify","Axios","Pagination","ChartStatic","PageHeader","HelpDialog","init","content","use","component","vue","delimiters","el","vuetify","data","strings","groups","userid","courseid","timezone","render_has","profile_render","indicators","week_resources_colors","search","week_resources_categories","week_resources_data","help_dialog","help_contents","beforeMount","calculate_week_resources","mounted","document","querySelector","style","display","methods","get_help_content","contents","title","section_help_title","description","section_help_description","get_course_grade","grade","course","grademax","isInt","toFixed","categories","week_name","weeks","forEach","week","name","position","push","cms","capitalizeFirstLetter","teacher_indicators_modules","build_week_resources_chart","chart","type","backgroundColor","fontFamily","text","colors","xAxis","yAxis","min","teacher_indicators_week_resources_yaxis_title","legend","enabled","series","build_weeks_sessions_chart","sessions","reversed","colorAxis","minColor","maxColor","layout","verticalAlign","tooltip","formatter","days","point","y","x","xCategoryName","get_point_category_name","yCategoryName","label","teacher_indicators_sessions","value","teacher_indicators_session","borderWidth","borderColor","table_headers","headers","align","sortable","thead_name","thead_lastname","thead_email","thead_progress","thead_sessions","thead_time","get_picture_url","url","M","cfg","wwwroot","get_percentage_progress","get_progress_tooltip","item","module_label","finished_label","teacher_indicators_finished","complete","teacher_indicators_module","teacher_indicators_finalized","of_conector","total","dimension","isY","axis","string","charAt","toUpperCase","slice","n","open_chart_help","week_resources_help_title","week_resources_help_description_p1","week_resources_help_description_p2","weeks_sessions_help_title","week_sessions_help_description_p1","week_sessions_help_description_p2","progress_table_help_title","progress_table_help_description","length","update_help_dialog","get_timezone","information","ss_change_timezone"],"mappings":"AAAAA,OAAM,8BAAC,CAAC,wBAAD,CACC,4BADD,CAEC,0BAFD,CAGC,+BAHD,CAIC,gCAJD,CAKC,+BALD,CAMC,+BAND,CAAD,CAQF,SAASC,CAAT,CAAcC,CAAd,CAAuBC,CAAvB,CAA8BC,CAA9B,CAA0CC,CAA1C,CAAuDC,CAAvD,CAAmEC,CAAnE,CAA+E,CAC3E,aAwOA,MAAO,CACHC,IAAI,CAvOR,SAAcC,CAAd,CAAuB,CAEnBR,CAAG,CAACS,GAAJ,CAAQR,CAAR,EACAD,CAAG,CAACU,SAAJ,CAAc,YAAd,CAA4BP,CAA5B,EACAH,CAAG,CAACU,SAAJ,CAAc,OAAd,CAAuBN,CAAvB,EACAJ,CAAG,CAACU,SAAJ,CAAc,YAAd,CAA4BL,CAA5B,EACAL,CAAG,CAACU,SAAJ,CAAc,YAAd,CAA4BJ,CAA5B,EACA,GAAIK,CAAAA,CAAG,CAAG,GAAIX,CAAAA,CAAJ,CAAQ,CACdY,UAAU,CAAE,CAAC,IAAD,CAAO,IAAP,CADE,CAEdC,EAAE,CAAE,UAFU,CAGdC,OAAO,CAAE,GAAIb,CAAAA,CAHC,CAIdc,IAJc,gBAIP,CACH,MAAO,CACHC,OAAO,CAAGR,CAAO,CAACQ,OADf,CAEHC,MAAM,CAAGT,CAAO,CAACS,MAFd,CAGHC,MAAM,CAAGV,CAAO,CAACU,MAHd,CAIHC,QAAQ,CAAGX,CAAO,CAACW,QAJhB,CAKHC,QAAQ,CAAGZ,CAAO,CAACY,QALhB,CAMHC,UAAU,CAAGb,CAAO,CAACc,cANlB,CAQHC,UAAU,CAAEf,CAAO,CAACe,UARjB,CASHC,qBAAqB,CAAEhB,CAAO,CAACgB,qBAT5B,CAUHC,MAAM,CAAE,IAVL,CAWHC,yBAAyB,CAAE,EAXxB,CAYHC,mBAAmB,CAAE,EAZlB,CAcHC,WAAW,GAdR,CAeHC,aAAa,CAAE,EAfZ,CAiBV,CAtBa,CAuBdC,WAvBc,uBAuBD,CACT,KAAKC,wBAAL,EACH,CAzBa,CA0BdC,OA1Bc,mBA0BL,CACLC,QAAQ,CAACC,aAAT,CAAuB,kBAAvB,EAA2CC,KAA3C,CAAiDC,OAAjD,CAA2D,MAA3D,CACAH,QAAQ,CAACC,aAAT,CAAuB,UAAvB,EAAmCC,KAAnC,CAAyCC,OAAzC,CAAmD,OACtD,CA7Ba,CA8BdC,OAAO,CAAG,CACNC,gBADM,4BACY,CACd,GAAIC,CAAAA,CAAQ,CAAG,CACD,CACVC,KAAK,CAAE,KAAKxB,OAAL,CAAayB,kBADV,CAEVC,WAAW,CAAE,KAAK1B,OAAL,CAAa2B,wBAFhB,CADC,CAAf,CAKA,MAAOJ,CAAAA,CACV,CARK,CAUNK,gBAVM,4BAUY,CACd,GAAIC,CAAAA,CAAK,EAAU,KAAKtB,UAAL,CAAgBuB,MAAhB,CAAuBC,QAA1C,CACA,MAAQ,MAAKC,KAAL,CAAWH,CAAX,CAAD,CAAsBA,CAAtB,CAA8BA,CAAK,CAACI,OAAN,CAAc,CAAd,CACxC,CAbK,CAeNlB,wBAfM,oCAeqB,IACnBmB,CAAAA,CAAU,CAAG,EADM,CACFnC,CAAI,CAAG,EADL,CAEnBoC,CAFmB,CAGvB,KAAK5B,UAAL,CAAgB6B,KAAhB,CAAsBC,OAAtB,CAA8B,SAAAC,CAAI,CAAI,CAClCH,CAAS,WAAMG,CAAI,CAACC,IAAX,aAAoBD,CAAI,CAACE,QAAL,CAAc,CAAlC,CAAT,CACAN,CAAU,CAACO,IAAX,CAAgBN,CAAhB,EACApC,CAAI,CAAC0C,IAAL,CAAUH,CAAI,CAACI,GAAf,CACH,CAJD,EAKA,GAAIH,CAAAA,CAAI,CAAG,KAAKI,qBAAL,CAA2B,KAAK3C,OAAL,CAAa4C,0BAAxC,CAAX,CACA,KAAKlC,yBAAL,CAAiCwB,CAAjC,CACA,KAAKvB,mBAAL,CAA2B,CAAC,CAAE4B,IAAI,CAAJA,CAAF,CAAQxC,IAAI,CAAJA,CAAR,CAAD,CAC9B,CA1BK,CA4BN8C,0BA5BM,sCA4BuB,CACzB,GAAIC,CAAAA,CAAK,GAAT,CACAA,CAAK,CAACA,KAAN,CAAc,CACVC,IAAI,CAAE,KADI,CAEVC,eAAe,CAAE,IAFP,CAGV7B,KAAK,CAAE,CAAC8B,UAAU,CAAE,SAAb,CAHG,CAAd,CAKAH,CAAK,CAACtB,KAAN,CAAc,CACV0B,IAAI,CAAE,IADI,CAAd,CAGAJ,CAAK,CAACK,MAAN,CAAe,KAAK3C,qBAApB,CACAsC,CAAK,CAACM,KAAN,CAAc,CACVlB,UAAU,CAAE,KAAKxB,yBADP,CAAd,CAGAoC,CAAK,CAACO,KAAN,CAAc,CACVC,GAAG,CAAE,CADK,CAEN9B,KAAK,CAAE,CACP0B,IAAI,CAAE,KAAKlD,OAAL,CAAauD,6CADZ,CAFD,CAAd,CAMAT,CAAK,CAACU,MAAN,CAAe,CACXC,OAAO,GADI,CAAf,CAGAX,CAAK,CAACY,MAAN,CAAe,KAAK/C,mBAApB,CACA,MAAOmC,CAAAA,CACV,CArDK,CAuDNa,0BAvDM,sCAuDuB,CACzB,GAAIb,CAAAA,CAAK,GAAT,CACAA,CAAK,CAACA,KAAN,CAAc,CACVC,IAAI,CAAE,SADI,CAEVC,eAAe,CAAE,IAFP,CAGV7B,KAAK,CAAE,CAAC8B,UAAU,CAAE,SAAb,CAHG,CAAd,CAKAH,CAAK,CAACtB,KAAN,CAAc,CACV0B,IAAI,CAAE,IADI,CAAd,CAGAJ,CAAK,CAACM,KAAN,CAAc,CACVlB,UAAU,CAAE,KAAKlC,OAAL,CAAaoC,KADf,CAAd,CAGAU,CAAK,CAACO,KAAN,CAAc,CACVnB,UAAU,CAAE,KAAK3B,UAAL,CAAgBqD,QAAhB,CAAyB1B,UAD3B,CAEVV,KAAK,CAAE,IAFG,CAGVqC,QAAQ,GAHE,CAAd,CAKAf,CAAK,CAACgB,SAAN,CAAkB,CACdR,GAAG,CAAE,CADS,CAEdS,QAAQ,CAAE,SAFI,CAGdC,QAAQ,CAAE,SAHI,CAAlB,CAKAlB,CAAK,CAACU,MAAN,CAAe,CACXS,MAAM,CAAE,YADG,CAEXC,aAAa,CAAE,QAFJ,CAAf,CAIApB,CAAK,CAACqB,OAAN,CAAgB,CACZC,SAAS,CAAE,oBAAY,IACfC,CAAAA,CAAI,CAAG1E,CAAG,CAACY,UAAJ,CAAeqD,QAAf,CAAwBxB,KAAxB,CAA8B,KAAKkC,KAAL,CAAWC,CAAzC,EAA4C,KAAKD,KAAL,CAAWE,CAAvD,GAA6D,EADrD,CAEfC,CAAa,CAAG9E,CAAG,CAAC+E,uBAAJ,CAA4B,KAAKJ,KAAjC,CAAwC,GAAxC,CAFD,CAGfK,CAAa,CAAGhF,CAAG,CAAC+E,uBAAJ,CAA4B,KAAKJ,KAAjC,CAAwC,GAAxC,CAHD,CAIfM,CAAK,CAAGjF,CAAG,CAACK,OAAJ,CAAY6E,2BAJL,CAKnB,GAAwB,CAApB,OAAKP,KAAL,CAAWQ,KAAf,CAA2B,CACvBF,CAAK,CAAGjF,CAAG,CAACK,OAAJ,CAAY+E,0BACvB,CACD,MAAO,MAAQJ,CAAR,CAAwB,GAAxB,CAA8BF,CAA9B,CAA8C,QAA9C,CACD,KAAKH,KAAL,CAAWQ,KADV,CACiB,GADjB,CACuBF,CADvB,CAC+B,OAD/B,CACyCP,CACnD,CAXW,CAAhB,CAaAvB,CAAK,CAACY,MAAN,CAAe,CAAC,CACZsB,WAAW,CAAE,CADD,CAEZC,WAAW,CAAE,SAFD,CAGZlF,IAAI,CAAE,KAAKQ,UAAL,CAAgBqD,QAAhB,CAAyB7D,IAHnB,CAAD,CAAf,CAKA,MAAO+C,CAAAA,CACV,CArGK,CAuGNoC,aAvGM,yBAuGS,CACX,GAAIC,CAAAA,CAAO,CAAG,CACV,CAAEjC,IAAI,CAAE,EAAR,CAAY4B,KAAK,CAAG,IAApB,CAA0BM,KAAK,CAAG,QAAlC,CAA4CC,QAAQ,GAApD,CADU,CAEV,CAAEnC,IAAI,CAAE,KAAKlD,OAAL,CAAasF,UAArB,CAAkCR,KAAK,CAAG,WAA1C,CAFU,CAGV,CAAE5B,IAAI,CAAE,KAAKlD,OAAL,CAAauF,cAArB,CAAsCT,KAAK,CAAG,UAA9C,CAHU,CAIV,CAAE5B,IAAI,CAAE,KAAKlD,OAAL,CAAawF,WAArB,CAAmCV,KAAK,CAAG,OAA3C,CAJU,CAKV,CAAE5B,IAAI,CAAE,KAAKlD,OAAL,CAAayF,cAArB,CAAsCX,KAAK,CAAG,qBAA9C,CAAsEM,KAAK,CAAG,QAA9E,CALU,CAMV,CAAElC,IAAI,CAAE,KAAKlD,OAAL,CAAa0F,cAArB,CAAsCZ,KAAK,CAAG,iBAA9C,CAAkEM,KAAK,CAAG,QAA1E,CANU,CAOV,CAAElC,IAAI,CAAE,KAAKlD,OAAL,CAAa2F,UAArB,CAAkCb,KAAK,CAAG,eAA1C,CAA2DM,KAAK,CAAG,QAAnE,CAPU,CAAd,CASA,MAAOD,CAAAA,CACV,CAlHK,CAoHNS,eApHM,0BAoHU1F,CApHV,CAoHiB,CACnB,GAAI2F,CAAAA,CAAG,WAAMC,CAAC,CAACC,GAAF,CAAMC,OAAZ,gCAA0C9F,CAA1C,WAAP,CACA,MAAO2F,CAAAA,CACV,CAvHK,CAyHNI,uBAzHM,kCAyHkBnB,CAzHlB,CAyHwB,CAC1B,gBAAUA,CAAV,MACH,CA3HK,CA6HNoB,oBA7HM,+BA6HeC,CA7Hf,CA6HoB,IAClBC,CAAAA,CAAY,CAAG,KAAKpG,OAAL,CAAa4C,0BADV,CAElByD,CAAc,CAAG,KAAKrG,OAAL,CAAasG,2BAFZ,CAGtB,GAAyB,CAArB,EAAAH,CAAI,CAACzD,GAAL,CAAS6D,QAAb,CAA4B,CACxBH,CAAY,CAAG,KAAKpG,OAAL,CAAawG,yBAA5B,CACAH,CAAc,CAAG,KAAKrG,OAAL,CAAayG,4BACjC,CACD,gBAAUN,CAAI,CAACzD,GAAL,CAAS6D,QAAnB,aAA+BH,CAA/B,aAA+CC,CAA/C,aAAiE,KAAKrG,OAAL,CAAa0G,WAA9E,aAA6FP,CAAI,CAACzD,GAAL,CAASiE,KAAtG,CACH,CArIK,CAuINjC,uBAvIM,kCAuIkBJ,CAvIlB,CAuIyBsC,CAvIzB,CAuIoC,CACtC,GAAIlD,CAAAA,CAAM,CAAGY,CAAK,CAACZ,MAAnB,CACImD,CAAG,CAAiB,GAAd,GAAAD,CADV,CAEIE,CAAI,CAAGpD,CAAM,CAACmD,CAAG,CAAG,OAAH,CAAa,OAAjB,CAFjB,CAGA,MAAOC,CAAAA,CAAI,CAAC5E,UAAL,CAAgBoC,CAAK,CAACuC,CAAG,CAAG,GAAH,CAAS,GAAb,CAArB,CACV,CA5IK,CA8INlE,qBA9IM,gCA8IgBoE,CA9IhB,CA8IwB,CAC1B,MAAOA,CAAAA,CAAM,CAACC,MAAP,CAAc,CAAd,EAAiBC,WAAjB,GAAiCF,CAAM,CAACG,KAAP,CAAa,CAAb,CAC3C,CAhJK,CAkJNlF,KAlJM,gBAkJAmF,CAlJA,CAkJG,CACL,MAAiB,EAAV,EAAAA,CAAC,CAAG,CACd,CApJK,CAsJNC,eAtJM,0BAsJUtE,CAtJV,CAsJiB,CACnB,GAAIvB,CAAAA,CAAQ,CAAG,EAAf,CACA,GAAa,gBAAT,EAAAuB,CAAJ,CAA+B,CAC3BvB,CAAQ,CAACkB,IAAT,CAAc,CACVjB,KAAK,CAAE,KAAKxB,OAAL,CAAaqH,yBADV,CAEV3F,WAAW,CAAE,KAAK1B,OAAL,CAAasH,kCAFhB,CAAd,EAIA/F,CAAQ,CAACkB,IAAT,CAAc,CACVf,WAAW,CAAE,KAAK1B,OAAL,CAAauH,kCADhB,CAAd,CAGH,CARD,IAQO,IAAa,gBAAT,EAAAzE,CAAJ,CAA+B,CAClCvB,CAAQ,CAACkB,IAAT,CAAc,CACVjB,KAAK,CAAE,KAAKxB,OAAL,CAAawH,yBADV,CAEV9F,WAAW,CAAE,KAAK1B,OAAL,CAAayH,iCAFhB,CAAd,EAIAlG,CAAQ,CAACkB,IAAT,CAAc,CACVf,WAAW,CAAE,KAAK1B,OAAL,CAAa0H,iCADhB,CAAd,CAGH,CARM,IAQA,IAAa,gBAAT,EAAA5E,CAAJ,CAA+B,CAClCvB,CAAQ,CAACkB,IAAT,CAAc,CACVjB,KAAK,CAAE,KAAKxB,OAAL,CAAa2H,yBADV,CAEVjG,WAAW,CAAE,KAAK1B,OAAL,CAAa4H,+BAFhB,CAAd,CAIH,CACD,KAAK/G,aAAL,CAAqBU,CAArB,CACA,GAAI,KAAKV,aAAL,CAAmBgH,MAAvB,CAA+B,CAC3B,KAAKjH,WAAL,GACH,CACJ,CAlLK,CAoLNkH,kBApLM,6BAoLchD,CApLd,CAoLqB,CACvB,KAAKlE,WAAL,CAAmBkE,CACtB,CAtLK,CAwLNiD,YAxLM,wBAwLQ,CACV,GAAIC,CAAAA,CAAW,WAAM,KAAKhI,OAAL,CAAaiI,kBAAnB,aAAyC,KAAK7H,QAA9C,CAAf,CACA,MAAO4H,CAAAA,CACV,CA3LK,CA9BI,CAAR,CA6Nb,CAEM,CAGV,CApPC,CAAN","sourcesContent":["define([\"local_notemyprogress/vue\",\r\n        \"local_notemyprogress/vuetify\",\r\n        \"local_notemyprogress/axios\",\r\n        \"local_notemyprogress/pagination\",\r\n        \"local_notemyprogress/chartstatic\",\r\n        \"local_notemyprogress/pageheader\",\r\n        \"local_notemyprogress/helpdialog\",\r\n    ],\r\n    function(Vue, Vuetify, Axios, Pagination, ChartStatic, PageHeader, HelpDialog) {\r\n        \"use strict\";\r\n\r\n        function init(content) {\r\n            // console.log(content);\r\n            Vue.use(Vuetify);\r\n            Vue.component('pagination', Pagination);\r\n            Vue.component('chart', ChartStatic);\r\n            Vue.component('pageheader', PageHeader);\r\n            Vue.component('helpdialog', HelpDialog);\r\n            let vue = new Vue({\r\n                delimiters: [\"[[\", \"]]\"],\r\n                el: \"#teacher\",\r\n                vuetify: new Vuetify(),\r\n                data() {\r\n                    return {\r\n                        strings : content.strings,\r\n                        groups : content.groups,\r\n                        userid : content.userid,\r\n                        courseid : content.courseid,\r\n                        timezone : content.timezone,\r\n                        render_has : content.profile_render,\r\n\r\n                        indicators: content.indicators,\r\n                        week_resources_colors: content.week_resources_colors,\r\n                        search: null,\r\n                        week_resources_categories: [],\r\n                        week_resources_data: [],\r\n\r\n                        help_dialog: false,\r\n                        help_contents: [],\r\n                    }\r\n                },\r\n                beforeMount(){\r\n                    this.calculate_week_resources();\r\n                },\r\n                mounted(){\r\n                    document.querySelector(\"#sessions-loader\").style.display = \"none\";\r\n                    document.querySelector(\"#teacher\").style.display = \"block\";\r\n                },\r\n                methods : {\r\n                    get_help_content(){\r\n                        let contents = [];\r\n                        contents.push({\r\n                            title: this.strings.section_help_title,\r\n                            description: this.strings.section_help_description,\r\n                        });\r\n                        return contents;\r\n                    },\r\n\r\n                    get_course_grade(){\r\n                        let grade = Number(this.indicators.course.grademax);\r\n                        return (this.isInt(grade)) ? grade : grade.toFixed(2);\r\n                    },\r\n\r\n                    calculate_week_resources() {\r\n                        let categories = [], data = [];\r\n                        let week_name;\r\n                        this.indicators.weeks.forEach(week => {\r\n                            week_name = `${week.name} ${(week.position+1)}`;\r\n                            categories.push(week_name);\r\n                            data.push(week.cms);\r\n                        });\r\n                        let name = this.capitalizeFirstLetter(this.strings.teacher_indicators_modules);\r\n                        this.week_resources_categories = categories;\r\n                        this.week_resources_data = [{ name, data}];\r\n                    },\r\n\r\n                    build_week_resources_chart() {\r\n                        let chart = new Object();\r\n                        chart.chart = {\r\n                            type: 'bar',\r\n                            backgroundColor: null,\r\n                            style: {fontFamily: 'poppins'},\r\n                        };\r\n                        chart.title = {\r\n                            text: null,\r\n                        };\r\n                        chart.colors = this.week_resources_colors;\r\n                        chart.xAxis = {\r\n                            categories: this.week_resources_categories\r\n                        };\r\n                        chart.yAxis = {\r\n                            min: 0,\r\n                                title: {\r\n                                text: this.strings.teacher_indicators_week_resources_yaxis_title\r\n                            }\r\n                        };\r\n                        chart.legend = {\r\n                            enabled: false\r\n                        };\r\n                        chart.series = this.week_resources_data;\r\n                        return chart;\r\n                    },\r\n\r\n                    build_weeks_sessions_chart() {\r\n                        let chart = new Object();\r\n                        chart.chart = {\r\n                            type: 'heatmap',\r\n                            backgroundColor: null,\r\n                            style: {fontFamily: 'poppins'},\r\n                        };\r\n                        chart.title = {\r\n                            text: null,\r\n                        };\r\n                        chart.xAxis = {\r\n                            categories: this.strings.weeks,\r\n                        };\r\n                        chart.yAxis = {\r\n                            categories: this.indicators.sessions.categories,\r\n                            title: null,\r\n                            reversed: true,\r\n                        };\r\n                        chart.colorAxis = {\r\n                            min: 0,\r\n                            minColor: '#E0E0E0',\r\n                            maxColor: '#118AB2'\r\n                        };\r\n                        chart.legend = {\r\n                            layout: 'horizontal',\r\n                            verticalAlign: 'bottom',\r\n                        };\r\n                        chart.tooltip = {\r\n                            formatter: function () {\r\n                                let days = vue.indicators.sessions.weeks[this.point.y][this.point.x] || '';\r\n                                let xCategoryName = vue.get_point_category_name(this.point, 'x');\r\n                                let yCategoryName = vue.get_point_category_name(this.point, 'y');\r\n                                let label = vue.strings.teacher_indicators_sessions;\r\n                                if (this.point.value == 1) {\r\n                                    label = vue.strings.teacher_indicators_session;\r\n                                }\r\n                                return '<b>' + yCategoryName + ' ' + xCategoryName + '</b>: '\r\n                                    + this.point.value +' ' + label + '<br/>' + days;\r\n                            }\r\n                        };\r\n                        chart.series = [{\r\n                            borderWidth: 2,\r\n                            borderColor: '#FAFAFA',\r\n                            data: this.indicators.sessions.data,\r\n                        }];\r\n                        return chart;\r\n                    },\r\n\r\n                    table_headers(){\r\n                        let headers = [\r\n                            { text: '', value : 'id', align : 'center', sortable : false},\r\n                            { text: this.strings.thead_name , value : 'firstname'},\r\n                            { text: this.strings.thead_lastname , value : 'lastname'},\r\n                            { text: this.strings.thead_email , value : 'email'},\r\n                            { text: this.strings.thead_progress , value : 'progress_percentage',  align : 'center'},\r\n                            { text: this.strings.thead_sessions , value : 'sessions_number',  align : 'center'},\r\n                            { text: this.strings.thead_time , value : 'inverted_time', align : 'center'},\r\n                        ];\r\n                        return headers;\r\n                    },\r\n\r\n                    get_picture_url(userid){\r\n                        let url = `${M.cfg.wwwroot}/user/pix.php?file=/${userid}/f1.jpg`;\r\n                        return url;\r\n                    },\r\n\r\n                    get_percentage_progress(value){\r\n                        return `${value} %`;\r\n                    },\r\n\r\n                    get_progress_tooltip(item){\r\n                        let module_label = this.strings.teacher_indicators_modules;\r\n                        let finished_label = this.strings.teacher_indicators_finished;\r\n                        if (item.cms.complete == 1) {\r\n                            module_label = this.strings.teacher_indicators_module;\r\n                            finished_label = this.strings.teacher_indicators_finalized;\r\n                        }\r\n                        return `${item.cms.complete} ${module_label} ${finished_label} ${this.strings.of_conector} ${item.cms.total}`;\r\n                    },\r\n\r\n                    get_point_category_name(point, dimension) {\r\n                        let series = point.series,\r\n                            isY = dimension === 'y',\r\n                            axis = series[isY ? 'yAxis' : 'xAxis'];\r\n                        return axis.categories[point[isY ? 'y' : 'x']];\r\n                    },\r\n\r\n                    capitalizeFirstLetter(string) {\r\n                        return string.charAt(0).toUpperCase() + string.slice(1);\r\n                    },\r\n\r\n                    isInt(n) {\r\n                        return n % 1 === 0;\r\n                    },\r\n\r\n                    open_chart_help(chart) {\r\n                        let contents = [];\r\n                        if (chart == \"week_resources\") {\r\n                            contents.push({\r\n                                title: this.strings.week_resources_help_title,\r\n                                description: this.strings.week_resources_help_description_p1,\r\n                            });\r\n                            contents.push({\r\n                                description: this.strings.week_resources_help_description_p2,\r\n                            });\r\n                        } else if (chart == \"weeks_sessions\") {\r\n                            contents.push({\r\n                                title: this.strings.weeks_sessions_help_title,\r\n                                description: this.strings.week_sessions_help_description_p1,\r\n                            });\r\n                            contents.push({\r\n                                description: this.strings.week_sessions_help_description_p2,\r\n                            });\r\n                        } else if (chart == \"progress_table\") {\r\n                            contents.push({\r\n                                title: this.strings.progress_table_help_title,\r\n                                description: this.strings.progress_table_help_description,\r\n                            });\r\n                        }\r\n                        this.help_contents = contents;\r\n                        if (this.help_contents.length) {\r\n                            this.help_dialog = true;\r\n                        }\r\n                    },\r\n\r\n                    update_help_dialog (value) {\r\n                        this.help_dialog = value;\r\n                    },\r\n\r\n                    get_timezone(){\r\n                        let information = `${this.strings.ss_change_timezone} ${this.timezone}`\r\n                        return information;\r\n                    },\r\n\r\n                }\r\n            })\r\n        }\r\n\r\n        return {\r\n            init : init\r\n        };\r\n    });"],"file":"teacher.min.js"}
\ No newline at end of file
diff --git a/notemyprogress/amd/src/logs.js b/notemyprogress/amd/src/logs.js
index 11f3883b60293bf7ae8fb7f7e14bb168c131588f..edc81115e83e526f5c3d83be4a402cbbe5afa8ca 100644
--- a/notemyprogress/amd/src/logs.js
+++ b/notemyprogress/amd/src/logs.js
@@ -2,305 +2,379 @@
 @author 2021 Éric Bart <bart.eric@hotmail.com>
  */
 
-define(["local_notemyprogress/vue",
-    "local_notemyprogress/vuetify",
-    "local_notemyprogress/axios",
-    "local_notemyprogress/moment",
-    "local_notemyprogress/pagination",
-    "local_notemyprogress/pageheader",
-    "local_notemyprogress/helpdialog",
-    "local_notemyprogress/alertify",
-
-],
-    function (Vue, Vuetify, Axios, Moment, Pagination, Pageheader, HelpDialog, Alertify) {
-        "use strict";
-
-        function init(content) {
-            const timeout = 60 * 120 * 1000
-            Axios.defaults.timeout = timeout
-            Vue.use(Vuetify);
-            Vue.component('pagination', Pagination);
-            Vue.component('pageheader', Pageheader);
-            Vue.component('helpdialog', HelpDialog);
-            let vue = new Vue({
-                delimiters: ["[[", "]]"],
-                el: "#logs",
-                vuetify: new Vuetify(),
-                data() {
-                    return {
-                        calendarData: {},
-                        strings: content.strings,
-                        groups: content.groups,
-                        userid: content.userid,
-                        courseid: content.courseid,
-                        timezone: content.timezone,
-                        render_has: content.profile_render,
-                        courseRole: content.courseRole,
-                        loading: false,
-                        errors: [],
-                        pages: content.pages,
-                        help_dialog: false,
-                        help_contents: [],
-                        dateRules: [
-                            v => !!v || this.strings.logs_invalid_date
-                        ]
+define([
+  "local_notemyprogress/vue",
+  "local_notemyprogress/vuetify",
+  "local_notemyprogress/axios",
+  "local_notemyprogress/moment",
+  "local_notemyprogress/pagination",
+  "local_notemyprogress/pageheader",
+  "local_notemyprogress/helpdialog",
+  "local_notemyprogress/alertify",
+], function (
+  Vue,
+  Vuetify,
+  Axios,
+  Moment,
+  Pagination,
+  Pageheader,
+  HelpDialog,
+  Alertify
+) {
+  "use strict";
 
+  function init(content) {
+    const timeout = 60 * 120 * 1000;
+    Axios.defaults.timeout = timeout;
+    Vue.use(Vuetify);
+    Vue.component("pagination", Pagination);
+    Vue.component("pageheader", Pageheader);
+    Vue.component("helpdialog", HelpDialog);
+    let vue = new Vue({
+      delimiters: ["[[", "]]"],
+      el: "#logs",
+      vuetify: new Vuetify(),
+      data() {
+        return {
+          calendarData: {},
+          strings: content.strings,
+          groups: content.groups,
+          userid: content.userid,
+          courseid: content.courseid,
+          timezone: content.timezone,
+          render_has: content.profile_render,
+          courseRole: content.courseRole,
+          loading: false,
+          errors: [],
+          pages: content.pages,
+          help_dialog: false,
+          help_contents: [],
+          dateRules: [(v) => !!v || this.strings.logs_invalid_date],
+        };
+      },
+      beforeMount() {
+        document.querySelector("#downloadButtonMoodle").style.display = "none";
+        document.querySelector("#downloadButtonNMP").style.display = "none";
+      },
+      mounted() {
+        document.querySelector(".v-application--wrap").style.minHeight = "60vh";
+        document.querySelector("#sessions-loader").style.display = "none";
+        document.querySelector("#helpMoodle").style.display = "block";
+        document.querySelector("#helpNMP").style.display = "block";
+        document.querySelector("#downloadButtonMoodle").style.display = "block";
+        document.querySelector("#downloadButtonNMP").style.display = "block";
+      },
+      methods: {
+        get_Moodlefile() {
+          let lastDate = document.querySelector("#lastDateMoodle");
+          let beginDate = document.querySelector("#beginDateMoodle");
+          let timestampBeginDate = 0;
+          let timestampLastDate = 0;
+          let parsedBeginDate = [];
+          let parsedLastDate = [];
+          this.url = false;
+          this.loading = true;
+          var data = {
+            action: "downloadMOODLElogs",
+            courseid: this.courseid,
+            userid: this.userid,
+            beginDate: beginDate.value,
+            lastDate: lastDate.value,
+            currentUrl: window.location.href,
+          };
+          if (beginDate.value != "" && lastDate.value != "") {
+            parsedBeginDate = beginDate.value.split("-");
+            timestampBeginDate = new Date(
+              parsedBeginDate[0],
+              parsedBeginDate[1] - 1,
+              parsedBeginDate[2]
+            );
+            parsedLastDate = lastDate.value.split("-");
+            timestampLastDate = new Date(
+              parsedLastDate[0],
+              parsedLastDate[1] - 1,
+              parsedLastDate[2]
+            );
+            if (timestampBeginDate.getTime() <= timestampLastDate.getTime()) {
+              if (timestampBeginDate.getTime() <= Date.now()) {
+                document.querySelector("#downloadButtonMoodle").innerHTML =
+                  this.strings.logs_download_btn;
+                document.getElementById("downloadButtonMoodle").disabled = true;
+                Axios({
+                  method: "get",
+                  url: M.cfg.wwwroot + "/local/notemyprogress/ajax.php",
+                  timeout: timeout,
+                  params: data,
+                })
+                  .then((response) => {
+                    this.loading = false;
+                    if (response.status == 200 && response.data.ok) {
+                      let jsonData = response.data.data.jsonData;
+                      jsonData = jsonData.map((row) => ({
+                        Role: row.user.role,
+                        Email: row.user.email,
+                        Fullname: row.user.firstname + " " + row.user.lastname,
+                        Date: row.time.date,
+                        Hour: row.time.hour,
+                        ACTION_VERB: row.action.actionverb,
+                        CourseID: row.course.courseid,
+                        CourseName: row.course.coursename,
+                        OBJECT_ID: row.action.objectid,
+                        OBJECT_NAME: row.action.objectname,
+                        OBJECT_TYPE: row.action.objecttype,
+                      }));
+                      let csvData = vue.objectToCSV(jsonData);
+                      vue.downloadCSV(csvData, "Activity_Moodle");
+                      document.querySelector(
+                        "#downloadButtonMoodle"
+                      ).innerHTML = this.strings.logs_valid_Moodlebtn;
+                      document.getElementById(
+                        "downloadButtonMoodle"
+                      ).disabled = false;
+                      Alertify.success(
+                        this.strings.logs_success_file_downloaded
+                      );
+                    } else {
+                      Alertify.error(
+                        this.strings.logs_error_problem_encountered
+                      );
+                      document.querySelector(
+                        "#downloadButtonMoodle"
+                      ).innerHTML = this.strings.logs_valid_Moodlebtn;
+                      document.getElementById(
+                        "downloadButtonMoodle"
+                      ).disabled = false;
                     }
-                },
-                beforeMount() {
-                    document.querySelector("#downloadButtonMoodle").style.display = "none";
-                    document.querySelector("#downloadButtonNMP").style.display = "none";
-                },
-                mounted() {
-                    document.querySelector(".v-application--wrap").style.minHeight = "60vh";
-                    document.querySelector("#sessions-loader").style.display = "none";
-                    document.querySelector("#helpMoodle").style.display = "block";
-                    document.querySelector("#helpNMP").style.display = "block";
-                    document.querySelector("#downloadButtonMoodle").style.display = "block";
-                    document.querySelector("#downloadButtonNMP").style.display = "block";
-                },
-                methods: {
-                    get_Moodlefile() {
-                        let lastDate = document.querySelector("#lastDateMoodle");
-                        let beginDate = document.querySelector("#beginDateMoodle");
-                        let timestampBeginDate = 0;
-                        let timestampLastDate = 0;
-                        let parsedBeginDate = [];
-                        let parsedLastDate = [];
-                        this.url = false;
-                        this.loading = true;
-                        var data = {
-                            action: "downloadMOODLElogs",
-                            courseid: this.courseid,
-                            userid: this.userid,
-                            beginDate: beginDate.value,
-                            lastDate: lastDate.value,
-                            currentUrl: window.location.href,
-                        }
-                        if (beginDate.value != "" && lastDate.value != "") {
-                            parsedBeginDate = beginDate.value.split("-");
-                            timestampBeginDate = new Date(parsedBeginDate[0], parsedBeginDate[1] - 1, parsedBeginDate[2]);
-                            parsedLastDate = lastDate.value.split("-");
-                            timestampLastDate = new Date(parsedLastDate[0], parsedLastDate[1] - 1, parsedLastDate[2]);
-                            if (timestampBeginDate.getTime() <= timestampLastDate.getTime()) {
-                                if (timestampBeginDate.getTime() <= Date.now()) {
-                                    document.querySelector('#downloadButtonMoodle').innerHTML = this.strings.logs_download_btn;
-                                    document.getElementById('downloadButtonMoodle').disabled = true;
-                                    Axios({
-                                        method: 'get',
-                                        url: M.cfg.wwwroot + "/local/notemyprogress/ajax.php",
-                                        timeout: timeout,
-                                        params: data,
-                                    }).then((response) => {
-                                        this.loading = false
-                                        if (response.status == 200 && response.data.ok) {
-                                            let jsonData = response.data.data.jsonData;
-                                            jsonData = jsonData.map(row => ({
-                                                Role: row.user.role,
-                                                Email: row.user.email,
-                                                Fullname: row.user.firstname + ' ' + row.user.lastname,
-                                                Date: row.time.date,
-                                                Hour: row.time.hour,
-                                                ACTION_VERB: row.action.actionverb,
-                                                CourseID: row.course.courseid,
-                                                CourseName: row.course.coursename,
-                                                OBJECT_ID: row.action.objectid,
-                                                OBJECT_NAME: row.action.objectname,
-                                                OBJECT_TYPE: row.action.objecttype
-                                            }));
-                                            let csvData = vue.objectToCSV(jsonData);
-                                            vue.downloadCSV(csvData, "Activity_Moodle");
-                                            document.querySelector('#downloadButtonMoodle').innerHTML = this.strings.logs_valid_Moodlebtn;
-                                            document.getElementById('downloadButtonMoodle').disabled = false;
-                                            Alertify.success(this.strings.logs_success_file_downloaded);
-                                        } else {
-                                            Alertify.error(this.strings.logs_error_problem_encountered);
-                                            document.querySelector('#downloadButtonMoodle').innerHTML = this.strings.logs_valid_Moodlebtn;
-                                            document.getElementById('downloadButtonMoodle').disabled = false;
-                                        }
-                                    }).catch((e) => {
-                                        Alertify.error(this.strings.logs_error_problem_encountered);
-                                        this.loading = false;
-                                        document.querySelector('#downloadButtonMoodle').innerHTML = this.strings.logs_valid_Moodlebtn;
-                                        document.getElementById('downloadButtonMoodle').disabled = false;
-                                    }).finally(() => {
-                                        this.loading = false;
-                                        document.querySelector('#downloadButtonMoodle').innerHTML = this.strings.logs_valid_Moodlebtn;
-                                        document.getElementById('downloadButtonMoodle').disabled = false;
-                                    });
-                                } else {
-                                    Alertify.error(this.strings.logs_error_begin_date_superior);
-                                }
-                            } else {
-                                Alertify.error(this.strings.logs_error_begin_date_inferior);
-                            }
-                        } else {
-                            Alertify.error(this.strings.logs_error_empty_dates);
-                        }
-                    },
-
-                    objectToCSV(jsonData) {
-                        let csvRows = [];
+                  })
+                  .catch((e) => {
+                    Alertify.error(this.strings.logs_error_problem_encountered);
+                    this.loading = false;
+                    document.querySelector("#downloadButtonMoodle").innerHTML =
+                      this.strings.logs_valid_Moodlebtn;
+                    document.getElementById(
+                      "downloadButtonMoodle"
+                    ).disabled = false;
+                  })
+                  .finally(() => {
+                    this.loading = false;
+                    document.querySelector("#downloadButtonMoodle").innerHTML =
+                      this.strings.logs_valid_Moodlebtn;
+                    document.getElementById(
+                      "downloadButtonMoodle"
+                    ).disabled = false;
+                  });
+              } else {
+                Alertify.error(this.strings.logs_error_begin_date_superior);
+              }
+            } else {
+              Alertify.error(this.strings.logs_error_begin_date_inferior);
+            }
+          } else {
+            Alertify.error(this.strings.logs_error_empty_dates);
+          }
+        },
 
-                        let headers = Object.keys(jsonData[0]);
-                        csvRows.push(headers.join(';'));
+        objectToCSV(jsonData) {
+          let csvRows = [];
 
-                        for (const row of jsonData) {
-                            const values = headers.map(header => {
-                                const escaped = ('' + row[header]).replace(/"/g, '\\"');
-                                return `"${escaped}"`;
-                            })
-                            csvRows.push(values.join(';'));
-                        }
+          let headers = Object.keys(jsonData[0]);
+          csvRows.push(headers.join(";"));
 
-                        return csvRows.join('\n');
-                    },
+          for (const row of jsonData) {
+            const values = headers.map((header) => {
+              const escaped = ("" + row[header]).replace(/"/g, '\\"');
+              return `"${escaped}"`;
+            });
+            csvRows.push(values.join(";"));
+          }
 
-                    downloadCSV(data, documentName) {
-                        let blob = new Blob([data], { type: 'text/csv' });
-                        let url = window.URL.createObjectURL(blob);
-                        const a = document.createElement('a');
-                        a.setAttribute('hidden', '');
-                        a.setAttribute('href', url);
-                        a.setAttribute('download', documentName + '.csv');
-                        document.body.appendChild(a);
-                        a.click();
-                        document.body.removeChild(a);
-                    },
+          return csvRows.join("\n");
+        },
 
-                    getRapport() {
-                        Alertify.confirm(this.strings.logs_download_details_description,
-                            () => {
-                                let path = M.cfg.wwwroot + "/local/notemyprogress/downloads/Details_Informations_LogsNMP.pdf";
-                                var link = document.createElement('a');
-                                link.href = path;
-                                link.download = "Details_Informations_LogsNMP.pdf";
-                                link.click();
-                                Alertify.success(this.strings.logs_download_details_validation);
-                            }).set({ title: this.strings.logs_download_details_title })
-                            .set({ labels: { cancel: this.strings.logs_download_details_cancel, ok: this.strings.logs_download_details_ok } });
-                    },
+        downloadCSV(data, documentName) {
+          let blob = new Blob([data], { type: "text/csv" });
+          let url = window.URL.createObjectURL(blob);
+          const a = document.createElement("a");
+          a.setAttribute("hidden", "");
+          a.setAttribute("href", url);
+          a.setAttribute("download", documentName + ".csv");
+          document.body.appendChild(a);
+          a.click();
+          document.body.removeChild(a);
+        },
 
-                    get_NMPfile() {
-                        let lastDate = document.querySelector("#lastDateNMP");
-                        let beginDate = document.querySelector("#beginDateNMP");
-                        let timestampBeginDate = 0;
-                        let timestampLastDate = 0;
-                        let parsedBeginDate = [];
-                        let parsedLastDate = [];
-                        this.url = false;
-                        this.loading = true;
-                        var data = {
-                            action: "downloadNMPlogs",
-                            courseid: this.courseid,
-                            userid: this.userid,
-                            beginDate: beginDate.value,
-                            lastDate: lastDate.value,
-                            currentUrl: window.location.href,
-                        }
-                        if (beginDate.value != "" && lastDate.value != "") {
-                            parsedBeginDate = beginDate.value.split("-");
-                            timestampBeginDate = new Date(parsedBeginDate[0], parsedBeginDate[1] - 1, parsedBeginDate[2]);
-                            parsedLastDate = lastDate.value.split("-");
-                            timestampLastDate = new Date(parsedLastDate[0], parsedLastDate[1] - 1, parsedLastDate[2]);
-                            if (timestampBeginDate.getTime() <= timestampLastDate.getTime()) {
-                                if (timestampBeginDate.getTime() <= Date.now()) {
-                                    document.querySelector('#downloadButtonNMP').innerHTML = this.strings.logs_download_btn;
-                                    document.getElementById('downloadButtonNMP').disabled = true;
-                                    Axios({
-                                        method: 'get',
-                                        url: M.cfg.wwwroot + "/local/notemyprogress/ajax.php",
-                                        timeout: timeout,
-                                        params: data,
-                                    }).then((response) => {
-                                        this.loading = false
-                                        if (response.status == 200 && response.data.ok) {
-                                            if (beginDate.value != "" || lastDate.value != "") {
-                                                let jsonData = response.data.data.jsonData;
-                                                jsonData = jsonData.map(row => ({
-                                                    Role: row.user.role,
-                                                    Email: row.user.email,
-                                                    Username: row.user.username,
-                                                    Fullname: row.user.fullname,
-                                                    Date: row.time.date,
-                                                    Hour: row.time.hour,
-                                                    CourseID: row.course.courseid,
-                                                    SECTION_NAME: row.action.sectionname,
-                                                    ACTION_TYPE: row.action.actiontype
-                                                }));
-                                                let csvData = vue.objectToCSV(jsonData);
-                                                vue.downloadCSV(csvData, "Activity_NoteMyProgress");
-                                                document.querySelector('#downloadButtonNMP').innerHTML = this.strings.logs_valid_NMPbtn;
-                                                document.getElementById('downloadButtonNMP').disabled = false;
-                                                Alertify.success(this.strings.logs_success_file_downloaded);
-                                            }
-                                        } else {
-                                            Alertify.error(this.strings.logs_error_problem_encountered);
-                                            document.querySelector('#downloadButtonNMP').innerHTML = this.strings.logs_valid_NMPbtn;
-                                            document.getElementById('downloadButtonNMP').disabled = false;
-                                        }
-                                    }).catch((e) => {
-                                        Alertify.error(this.strings.logs_error_problem_encountered);
-                                        this.loading = false;
-                                        document.querySelector('#downloadButtonNMP').innerHTML = this.strings.logs_valid_NMPbtn;
-                                        document.getElementById('downloadButtonNMP').disabled = false;
-                                    }).finally(() => {
-                                        this.loading = false;
-                                        document.querySelector('#downloadButtonNMP').innerHTML = this.strings.logs_valid_NMPbtn;
-                                        document.getElementById('downloadButtonNMP').disabled = false;
-                                    });
-                                } else { //Si la date de début est supérieure à la date de fin
-                                    Alertify.error(this.strings.logs_error_begin_date_superior);
-                                }
-                            } else { //Si la date de début est inférieure à la date du jour
-                                Alertify.error(this.strings.logs_error_begin_date_inferior);
-                            }
-                        } else { //Si les dates ne sont pas remplies
-                            Alertify.error(this.strings.logs_error_empty_dates);
-                        }
-                    },
+        getRapport() {
+          Alertify.confirm(
+            this.strings.logs_download_details_description,
+            () => {
+              let path =
+                M.cfg.wwwroot +
+                "/local/notemyprogress/downloads/Details_Informations_LogsNMP.pdf";
+              var link = document.createElement("a");
+              link.href = path;
+              link.download = "Details_Informations_LogsNMP.pdf";
+              link.click();
+              Alertify.success(this.strings.logs_download_details_validation);
+            }
+          )
+            .set({ title: this.strings.logs_download_details_title })
+            .set({
+              labels: {
+                cancel: this.strings.logs_download_details_cancel,
+                ok: this.strings.logs_download_details_ok,
+              },
+            });
+        },
 
-                    get_help_content() {
-                        var help_contents = [];
-                        var help = new Object();
-                        help.title = this.strings.title;
-                        help.description = this.strings.description;
-                        help_contents.push(help);
-                        return help_contents;
-                    },
-
-                    open_chart_help(chart) {
-                        let contents = [];
-                        if (chart == 'download_moodle') {
-                            contents.push({
-                                title: this.strings.logs_download_moodle_help_title,
-                                description: this.strings.logs_download_moodle_help_description,
-                            });
-                        } else if (chart == "download_nmp") {
-                            contents.push({
-                                title: this.strings.logs_download_nmp_help_title,
-                                description: this.strings.logs_download_nmp_help_description,
-                            });
-                        }
-                        this.help_contents = contents;
-                        if (this.help_contents.length) {
-                            this.help_dialog = true;
-                        }
-                    },
+        get_NMPfile() {
+          let lastDate = document.querySelector("#lastDateNMP");
+          let beginDate = document.querySelector("#beginDateNMP");
+          let timestampBeginDate = 0;
+          let timestampLastDate = 0;
+          let parsedBeginDate = [];
+          let parsedLastDate = [];
+          this.url = false;
+          this.loading = true;
+          var data = {
+            action: "downloadNMPlogs",
+            courseid: this.courseid,
+            userid: this.userid,
+            beginDate: beginDate.value,
+            lastDate: lastDate.value,
+            currentUrl: window.location.href,
+          };
+          if (beginDate.value != "" && lastDate.value != "") {
+            parsedBeginDate = beginDate.value.split("-");
+            timestampBeginDate = new Date(
+              parsedBeginDate[0],
+              parsedBeginDate[1] - 1,
+              parsedBeginDate[2]
+            );
+            parsedLastDate = lastDate.value.split("-");
+            timestampLastDate = new Date(
+              parsedLastDate[0],
+              parsedLastDate[1] - 1,
+              parsedLastDate[2]
+            );
+            if (timestampBeginDate.getTime() <= timestampLastDate.getTime()) {
+              if (timestampBeginDate.getTime() <= Date.now()) {
+                document.querySelector("#downloadButtonNMP").innerHTML =
+                  this.strings.logs_download_btn;
+                document.getElementById("downloadButtonNMP").disabled = true;
+                Axios({
+                  method: "get",
+                  url: M.cfg.wwwroot + "/local/notemyprogress/ajax.php",
+                  timeout: timeout,
+                  params: data,
+                })
+                  .then((response) => {
+                    this.loading = false;
+                    if (response.status == 200 && response.data.ok) {
+                      if (beginDate.value != "" || lastDate.value != "") {
+                        let jsonData = response.data.data.jsonData;
+                        jsonData = jsonData.map((row) => ({
+                          Role: row.user.role,
+                          Email: row.user.email,
+                          Username: row.user.username,
+                          Fullname: row.user.fullname,
+                          Date: row.time.date,
+                          Hour: row.time.hour,
+                          CourseID: row.course.courseid,
+                          SECTION_NAME: row.action.sectionname,
+                          ACTION_TYPE: row.action.actiontype,
+                        }));
+                        let csvData = vue.objectToCSV(jsonData);
+                        vue.downloadCSV(csvData, "Activity_NoteMyProgress");
+                        document.querySelector("#downloadButtonNMP").innerHTML =
+                          this.strings.logs_valid_NMPbtn;
+                        document.getElementById(
+                          "downloadButtonNMP"
+                        ).disabled = false;
+                        Alertify.success(
+                          this.strings.logs_success_file_downloaded
+                        );
+                      }
+                    } else {
+                      Alertify.error(
+                        this.strings.logs_error_problem_encountered
+                      );
+                      document.querySelector("#downloadButtonNMP").innerHTML =
+                        this.strings.logs_valid_NMPbtn;
+                      document.getElementById(
+                        "downloadButtonNMP"
+                      ).disabled = false;
+                    }
+                  })
+                  .catch((e) => {
+                    Alertify.error(this.strings.logs_error_problem_encountered);
+                    this.loading = false;
+                    document.querySelector("#downloadButtonNMP").innerHTML =
+                      this.strings.logs_valid_NMPbtn;
+                    document.getElementById(
+                      "downloadButtonNMP"
+                    ).disabled = false;
+                  })
+                  .finally(() => {
+                    this.loading = false;
+                    document.querySelector("#downloadButtonNMP").innerHTML =
+                      this.strings.logs_valid_NMPbtn;
+                    document.getElementById(
+                      "downloadButtonNMP"
+                    ).disabled = false;
+                  });
+              } else {
+                //Si la date de début est supérieure à la date de fin
+                Alertify.error(this.strings.logs_error_begin_date_superior);
+              }
+            } else {
+              //Si la date de début est inférieure à la date du jour
+              Alertify.error(this.strings.logs_error_begin_date_inferior);
+            }
+          } else {
+            //Si les dates ne sont pas remplies
+            Alertify.error(this.strings.logs_error_empty_dates);
+          }
+        },
 
-                    update_help_dialog(value) {
-                        this.help_dialog = value;
-                    },
+        get_help_content() {
+          var help_contents = [];
+          var help = new Object();
+          help.title = this.strings.title;
+          help.description = this.strings.description;
+          help_contents.push(help);
+          return help_contents;
+        },
 
-                    get_timezone() {
-                        let information = `${this.strings.ss_change_timezone} ${this.timezone}`
-                        return information;
-                    },
-                }
-            })
-        }
+        open_chart_help(chart) {
+          let contents = [];
+          if (chart == "download_moodle") {
+            contents.push({
+              title: this.strings.logs_download_moodle_help_title,
+              description: this.strings.logs_download_moodle_help_description,
+            });
+          } else if (chart == "download_nmp") {
+            contents.push({
+              title: this.strings.logs_download_nmp_help_title,
+              description: this.strings.logs_download_nmp_help_description,
+            });
+          }
+          this.help_contents = contents;
+          if (this.help_contents.length) {
+            this.help_dialog = true;
+          }
+        },
 
-        return {
-            init: init
-        };
-    });
\ No newline at end of file
+        update_help_dialog(value) {
+          this.help_dialog = value;
+        },
+        get_timezone() {
+          let information = `${this.strings.ss_change_timezone} ${this.timezone}`;
+          return information;
+        },
+      },
+    });
+  }
+  return {
+    init: init,
+  };
+});
diff --git a/notemyprogress/amd/src/sessions.js b/notemyprogress/amd/src/sessions.js
index 14d0d7990d3de6af94f026f4cfbbcb9dda6c3931..8d9df751b9905c8312ec27ab41c406ebc347749a 100644
--- a/notemyprogress/amd/src/sessions.js
+++ b/notemyprogress/amd/src/sessions.js
@@ -1,388 +1,438 @@
-define(["local_notemyprogress/vue",
-        "local_notemyprogress/vuetify",
-        "local_notemyprogress/axios",
-        "local_notemyprogress/moment",
-        "local_notemyprogress/pagination",
-        "local_notemyprogress/chartstatic",
-        "local_notemyprogress/pageheader",
-        "local_notemyprogress/helpdialog",
-    ],
-    function(Vue, Vuetify, Axios, Moment, Pagination, ChartStatic, PageHeader, HelpDialog) {
-        "use strict";
+define([
+  "local_notemyprogress/vue",
+  "local_notemyprogress/vuetify",
+  "local_notemyprogress/axios",
+  "local_notemyprogress/moment",
+  "local_notemyprogress/pagination",
+  "local_notemyprogress/chartstatic",
+  "local_notemyprogress/pageheader",
+  "local_notemyprogress/helpdialog",
+], function (
+  Vue,
+  Vuetify,
+  Axios,
+  Moment,
+  Pagination,
+  ChartStatic,
+  PageHeader,
+  HelpDialog
+) {
+  "use strict";
 
-        function init(content) {
-            // console.log(content);
-            Vue.use(Vuetify);
-            Vue.component('pagination', Pagination);
-            Vue.component('chart', ChartStatic);
-            Vue.component('pageheader', PageHeader);
-            Vue.component('helpdialog', HelpDialog);
-            let vue = new Vue({
-                delimiters: ["[[", "]]"],
-                el: "#work_sessions",
-                vuetify: new Vuetify(),
-                data() {
-                    return {
-                        strings : content.strings,
-                        groups : content.groups,
-                        userid : content.userid,
-                        courseid : content.courseid,
-                        timezone : content.timezone,
-                        render_has : content.profile_render,
-                        loading : false,
-                        errors : [],
+  function init(content) {
+    // console.log(content);
+    Vue.use(Vuetify);
+    Vue.component("pagination", Pagination);
+    Vue.component("chart", ChartStatic);
+    Vue.component("pageheader", PageHeader);
+    Vue.component("helpdialog", HelpDialog);
+    let vue = new Vue({
+      delimiters: ["[[", "]]"],
+      el: "#work_sessions",
+      vuetify: new Vuetify(),
+      data() {
+        return {
+          strings: content.strings,
+          groups: content.groups,
+          userid: content.userid,
+          courseid: content.courseid,
+          timezone: content.timezone,
+          render_has: content.profile_render,
+          loading: false,
+          errors: [],
 
-                        pages : content.pages,
-                        hours_sessions: content.indicators.sessions,
-                        session_count: content.indicators.count,
-                        inverted_time: content.indicators.time,
-                        inverted_time_colors: content.inverted_time_colors,
-                        sessions_count_colors: content.sessions_count_colors,
+          pages: content.pages,
+          hours_sessions: content.indicators.sessions,
+          session_count: content.indicators.count,
+          inverted_time: content.indicators.time,
+          inverted_time_colors: content.inverted_time_colors,
+          sessions_count_colors: content.sessions_count_colors,
 
-                        search: null,
+          search: null,
 
-                        help_dialog: false,
-                        help_contents: [],
-                    }
-                },
-                mounted(){
-                    document.querySelector("#sessions-loader").style.display = "none";
-                    document.querySelector("#work_sessions").style.display = "block";
-                    setTimeout(function() {
-                        vue.setGraphicsEventListeners();
-                    }, 500);
-                },
-                methods : {
-                    get_help_content(){
-                        let contents = [];
-                        contents.push({
-                            title: this.strings.section_help_title,
-                            description: this.strings.section_help_description,
-                        });
-                        return contents;
-                    },
+          help_dialog: false,
+          help_contents: [],
+        };
+      },
+      mounted() {
+        document.querySelector("#sessions-loader").style.display = "none";
+        document.querySelector("#work_sessions").style.display = "block";
+        setTimeout(function () {
+          vue.setGraphicsEventListeners();
+        }, 500);
+      },
+      methods: {
+        get_help_content() {
+          let contents = [];
+          contents.push({
+            title: this.strings.section_help_title,
+            description: this.strings.section_help_description,
+          });
+          return contents;
+        },
 
-                    update_interactions(week){
-                        this.loading = true;
-                        this.errors = [];
-                        let data = {
-                            action : "worksessions",
-                            userid : this.userid,
-                            courseid : this.courseid,
-                            weekcode : week.weekcode,
-                            profile : this.render_has,
-                        }
-                        Axios({
-                            method:'get',
-                            url: M.cfg.wwwroot + "/local/notemyprogress/ajax.php",
-                            params : data,
-                        }).then((response) => {
-                            if (response.status == 200 && response.data.ok) {
-                                this.hours_sessions = response.data.data.indicators.sessions;
-                                this.session_count = response.data.data.indicators.count;
-                                this.inverted_time = response.data.data.indicators.time;
-                            } else {
-                                this.error_messages.push(this.strings.error_network);
-                            }
-                        }).catch((e) => {
-                            this.errors.push(this.strings.api_error_network);
-                        }).finally(() => {
-                            this.loading = false;
-                            //Ici, la page a fini de charger
-                            vue.addLogsIntoDB("viewed", "week_"+week.weekcode, "week_section", "Week section that allows you to obtain information on a specific week");
-                            vue.setGraphicsEventListeners();
-                        });
-                        return this.data;
-                    },
+        update_interactions(week) {
+          this.loading = true;
+          this.errors = [];
+          let data = {
+            action: "worksessions",
+            userid: this.userid,
+            courseid: this.courseid,
+            weekcode: week.weekcode,
+            profile: this.render_has,
+          };
+          Axios({
+            method: "get",
+            url: M.cfg.wwwroot + "/local/notemyprogress/ajax.php",
+            params: data,
+          })
+            .then((response) => {
+              if (response.status == 200 && response.data.ok) {
+                this.hours_sessions = response.data.data.indicators.sessions;
+                this.session_count = response.data.data.indicators.count;
+                this.inverted_time = response.data.data.indicators.time;
+              } else {
+                this.error_messages.push(this.strings.error_network);
+              }
+            })
+            .catch((e) => {
+              this.errors.push(this.strings.api_error_network);
+            })
+            .finally(() => {
+              this.loading = false;
+              //Ici, la page a fini de charger
+              vue.addLogsIntoDB(
+                "viewed",
+                "week_" + week.weekcode,
+                "week_section",
+                "Week section that allows you to obtain information on a specific week"
+              );
+              vue.setGraphicsEventListeners();
+            });
+          return this.data;
+        },
 
-                    get_point_category_name(point, dimension) {
-                        let series = point.series,
-                            isY = dimension === 'y',
-                            axis = series[isY ? 'yAxis' : 'xAxis'];
-                        return axis.categories[point[isY ? 'y' : 'x']];
-                    },
+        get_point_category_name(point, dimension) {
+          let series = point.series,
+            isY = dimension === "y",
+            axis = series[isY ? "yAxis" : "xAxis"];
+          return axis.categories[point[isY ? "y" : "x"]];
+        },
 
-                    build_hours_sessions_chart() {
-                        let chart = new Object();
-                        chart.title = {
-                            text: null,
-                        };
-                        chart.chart = {
-                            type: 'heatmap',
-                            backgroundColor: null,
-                            style: {fontFamily: 'poppins'},
-                        };
-                        chart.xAxis = {
-                            categories: this.strings.days,
-                        };
-                        chart.yAxis = {
-                            categories: this.strings.hours,
-                            title: null,
-                            reversed: true,
-                        };
-                        chart.colorAxis = {
-                            min: 0,
-                            minColor: '#E0E0E0',
-                            maxColor: '#118AB2'
-                        };
-                        chart.legend = {
-                            layout: 'horizontal',
-                            verticalAlign: 'bottom',
-                        };
-                        chart.tooltip = {
-                            formatter: function () {
-                                let xCategoryName = vue.get_point_category_name(this.point, 'x');
-                                let yCategoryName = vue.get_point_category_name(this.point, 'y');
-                                let label = vue.strings.sessions_text;
-                                if (this.point.value == 1) {
-                                    label = vue.strings.session_text;
-                                }
-                                return '<b>' + xCategoryName + ' ' + yCategoryName + '</b>: '
-                                    + this.point.value +' ' + label;
-                            }
-                        };
-                        chart.series = [{
-                            borderWidth: 2,
-                            borderColor: '#FAFAFA',
-                            data: this.hours_sessions,
-                        }];
-                        return chart;
-                    },
+        build_hours_sessions_chart() {
+          let chart = new Object();
+          chart.title = {
+            text: null,
+          };
+          chart.chart = {
+            type: "heatmap",
+            backgroundColor: null,
+            style: { fontFamily: "poppins" },
+          };
+          chart.xAxis = {
+            categories: this.strings.days,
+          };
+          chart.yAxis = {
+            categories: this.strings.hours,
+            title: null,
+            reversed: true,
+          };
+          chart.colorAxis = {
+            min: 0,
+            minColor: "#E0E0E0",
+            maxColor: "#118AB2",
+          };
+          chart.legend = {
+            layout: "horizontal",
+            verticalAlign: "bottom",
+          };
+          chart.tooltip = {
+            formatter: function () {
+              let xCategoryName = vue.get_point_category_name(this.point, "x");
+              let yCategoryName = vue.get_point_category_name(this.point, "y");
+              let label = vue.strings.sessions_text;
+              if (this.point.value == 1) {
+                label = vue.strings.session_text;
+              }
+              return (
+                "<b>" +
+                xCategoryName +
+                " " +
+                yCategoryName +
+                "</b>: " +
+                this.point.value +
+                " " +
+                label
+              );
+            },
+          };
+          chart.series = [
+            {
+              borderWidth: 2,
+              borderColor: "#FAFAFA",
+              data: this.hours_sessions,
+            },
+          ];
+          return chart;
+        },
 
-                    build_inverted_time_chart() {
-                        let chart = new Object();
-                        chart.chart = {
-                            type: 'bar',
-                            backgroundColor: null,
-                            style: {fontFamily: 'poppins'},
-                        };
-                        chart.title = {
-                            text: null,
-                        };
-                        chart.colors = this.inverted_time_colors;
-                        chart.xAxis = {
-                            type: 'category',
-                            crosshair: true,
-                        };
-                        chart.yAxis = {
-                            title: {
-                                text: this.strings.time_inverted_x_axis,
-                            }
-                        };
-                        chart.tooltip = {
-                            shared:true,
-                            useHTML:true,
-                            formatter: function () {
-                                let category_name = this.points[0].key;
-                                let time = vue.convert_time(this.y);
-                                return `<b>${category_name}: </b>${time}`;
-                            }
-                        };
-                        chart.legend = {
-                            enabled: false
-                        };
-                        chart.series = [{
-                            colorByPoint: true,
-                            data: this.inverted_time.data
-                        }];
-                        return chart;
-                    },
+        build_inverted_time_chart() {
+          let chart = new Object();
+          chart.chart = {
+            type: "bar",
+            backgroundColor: null,
+            style: { fontFamily: "poppins" },
+          };
+          chart.title = {
+            text: null,
+          };
+          chart.colors = this.inverted_time_colors;
+          chart.xAxis = {
+            type: "category",
+            crosshair: true,
+          };
+          chart.yAxis = {
+            title: {
+              text: this.strings.time_inverted_x_axis,
+            },
+          };
+          chart.tooltip = {
+            shared: true,
+            useHTML: true,
+            formatter: function () {
+              let category_name = this.points[0].key;
+              let time = vue.convert_time(this.y);
+              return `<b>${category_name}: </b>${time}`;
+            },
+          };
+          chart.legend = {
+            enabled: false,
+          };
+          chart.series = [
+            {
+              colorByPoint: true,
+              data: this.inverted_time.data,
+            },
+          ];
+          return chart;
+        },
 
-                    build_sessions_count_chart() {
-                        let chart = new Object();
-                        chart.chart = {
-                            backgroundColor: null,
-                            style: {fontFamily: 'poppins'},
-                        };
-                        chart.title = {
-                            text: null,
-                        };
-                        chart.colors = this.sessions_count_colors;
-                        chart.yAxis = {
-                            title: {
-                                text: this.strings.session_count_yaxis_title,
-                            },
-                            allowDecimals: false
-                        };
-                        chart.xAxis = {
-                            categories: this.session_count.categories,
-                        };
-                        chart.tooltip = {
-                            valueSuffix: this.strings.session_count_tooltip_suffix,
-                        };
-                        chart.legend = {
-                            layout: 'horizontal',
-                            verticalAlign: 'bottom',
-                        };
-                        chart.series = this.session_count.data
-                        return chart;
-                    },
+        build_sessions_count_chart() {
+          let chart = new Object();
+          chart.chart = {
+            backgroundColor: null,
+            style: { fontFamily: "poppins" },
+          };
+          chart.title = {
+            text: null,
+          };
+          chart.colors = this.sessions_count_colors;
+          chart.yAxis = {
+            title: {
+              text: this.strings.session_count_yaxis_title,
+            },
+            allowDecimals: false,
+          };
+          chart.xAxis = {
+            categories: this.session_count.categories,
+          };
+          chart.tooltip = {
+            valueSuffix: this.strings.session_count_tooltip_suffix,
+          };
+          chart.legend = {
+            layout: "horizontal",
+            verticalAlign: "bottom",
+          };
+          chart.series = this.session_count.data;
+          return chart;
+        },
 
-                    convert_time(time) {
-                        time *= 3600; // pasar las horas a segundos
-                        let h = this.strings.hours_short;
-                        let m = this.strings.minutes_short;
-                        let s = this.strings.seconds_short;
-                        let hours = Math.floor(time / 3600);
-                        let minutes = Math.floor((time % 3600) / 60);
-                        let seconds = Math.floor(time % 60);
-                        let text;
-                        if (hours >= 1) {
-                            if (minutes >= 1) {
-                                text = `${hours}${h} ${minutes}${m}`;
-                            } else {
-                                text = `${hours}${h}`;
-                            }
-                        } else if ((minutes >= 1)) {
-                            if (seconds >= 1) {
-                                text = `${minutes}${m} ${seconds}${s}`;
-                            } else {
-                                text = `${minutes}${m}`;
-                            }
-                        } else {
-                            text = `${seconds}${s}`;
-                        }
-                        return text;
-                    },
+        convert_time(time) {
+          time *= 3600; // pasar las horas a segundos
+          let h = this.strings.hours_short;
+          let m = this.strings.minutes_short;
+          let s = this.strings.seconds_short;
+          let hours = Math.floor(time / 3600);
+          let minutes = Math.floor((time % 3600) / 60);
+          let seconds = Math.floor(time % 60);
+          let text;
+          if (hours >= 1) {
+            if (minutes >= 1) {
+              text = `${hours}${h} ${minutes}${m}`;
+            } else {
+              text = `${hours}${h}`;
+            }
+          } else if (minutes >= 1) {
+            if (seconds >= 1) {
+              text = `${minutes}${m} ${seconds}${s}`;
+            } else {
+              text = `${minutes}${m}`;
+            }
+          } else {
+            text = `${seconds}${s}`;
+          }
+          return text;
+        },
 
-                    open_chart_help(chart) {
-                        let contents = [];
-                        var action = "";
-                        var objectName = "";
-                        var objectType = "";
-                        var objectDescription = "";
-                        if (chart == "inverted_time") {
-                            contents.push({
-                                title: this.strings.inverted_time_help_title,
-                                description: this.strings.inverted_time_help_description_p1,
-                            });
-                            contents.push({
-                                description: this.strings.inverted_time_help_description_p2,
-                            });
-                            action = "viewed";
-                            objectType = "help";
-                            objectName = "invested_time";
-                            objectDescription = "Help section that provides information about the sessions per week chart";
-                            vue.addLogsIntoDB(action, objectName, objectType, objectDescription);
-                        } else if (chart == "hours_sessions") {
-                            contents.push({
-                                title: this.strings.hours_sessions_help_title,
-                                description: this.strings.hours_sessions_help_description_p1,
-                            });
-                            contents.push({
-                                description: this.strings.hours_sessions_help_description_p2,
-                            });
-                            action = "viewed";
-                            objectType = "help";
-                            objectName = "hours_sessions";
-                            objectDescription = "Help section that provides information about the sessions per hour chart";
-                            vue.addLogsIntoDB(action, objectName, objectType, objectDescription);
-                        } else if (chart == "sessions_count") {
-                            contents.push({
-                                title: this.strings.sessions_count_help_title,
-                                description: this.strings.sessions_count_help_description_p1,
-                            });
-                            contents.push({
-                                description: this.strings.sessions_count_help_description_p2,
-                            });
-                            action = "viewed";
-                            objectType = "help";
-                            objectName = "sessions_count";
-                            objectDescription = "Help section that provides information about the invested time chart";
-                            vue.addLogsIntoDB(action, objectName, objectType, objectDescription);
-                        }
-                        this.help_contents = contents;
-                        if (this.help_contents.length) {
-                            this.help_dialog = true;
-                        }
-                    },
+        open_chart_help(chart) {
+          let contents = [];
+          var action = "";
+          var objectName = "";
+          var objectType = "";
+          var objectDescription = "";
+          if (chart == "inverted_time") {
+            contents.push({
+              title: this.strings.inverted_time_help_title,
+              description: this.strings.inverted_time_help_description_p1,
+            });
+            contents.push({
+              description: this.strings.inverted_time_help_description_p2,
+            });
+            action = "viewed";
+            objectType = "help";
+            objectName = "invested_time";
+            objectDescription =
+              "Help section that provides information about the sessions per week chart";
+            vue.addLogsIntoDB(
+              action,
+              objectName,
+              objectType,
+              objectDescription
+            );
+          } else if (chart == "hours_sessions") {
+            contents.push({
+              title: this.strings.hours_sessions_help_title,
+              description: this.strings.hours_sessions_help_description_p1,
+            });
+            contents.push({
+              description: this.strings.hours_sessions_help_description_p2,
+            });
+            action = "viewed";
+            objectType = "help";
+            objectName = "hours_sessions";
+            objectDescription =
+              "Help section that provides information about the sessions per hour chart";
+            vue.addLogsIntoDB(
+              action,
+              objectName,
+              objectType,
+              objectDescription
+            );
+          } else if (chart == "sessions_count") {
+            contents.push({
+              title: this.strings.sessions_count_help_title,
+              description: this.strings.sessions_count_help_description_p1,
+            });
+            contents.push({
+              description: this.strings.sessions_count_help_description_p2,
+            });
+            action = "viewed";
+            objectType = "help";
+            objectName = "sessions_count";
+            objectDescription =
+              "Help section that provides information about the invested time chart";
+            vue.addLogsIntoDB(
+              action,
+              objectName,
+              objectType,
+              objectDescription
+            );
+          }
+          this.help_contents = contents;
+          if (this.help_contents.length) {
+            this.help_dialog = true;
+          }
+        },
 
-                    update_help_dialog (value) {
-                        this.help_dialog = value;
-                    },
+        update_help_dialog(value) {
+          this.help_dialog = value;
+        },
 
-                    get_timezone(){
-                        let information = `${this.strings.ss_change_timezone} ${this.timezone}`
-                        return information;
-                    },
+        get_timezone() {
+          let information = `${this.strings.ss_change_timezone} ${this.timezone}`;
+          return information;
+        },
 
-                    setGraphicsEventListeners() {
-                        let graphics = document.querySelectorAll('.highcharts-container');
-                        if(graphics.length<1) {
-                            setTimeout(vue.setGraphicsEventListeners,500);
-                        } else {
-                            graphics[0].id="investedTime";
-                            graphics[1].id="sessionsPerHour";
-                            graphics[2].id="sessionsPerWeek";
-                            graphics.forEach((graph) => {
-                                graph.addEventListener('mouseenter', vue.addLogsViewGraphic);
-                            })
-                        }
-                    },
+        setGraphicsEventListeners() {
+          let graphics = document.querySelectorAll(".highcharts-container");
+          if (graphics.length < 1) {
+            setTimeout(vue.setGraphicsEventListeners, 500);
+          } else {
+            graphics[0].id = "investedTime";
+            graphics[1].id = "sessionsPerHour";
+            graphics[2].id = "sessionsPerWeek";
+            graphics.forEach((graph) => {
+              graph.addEventListener("mouseenter", vue.addLogsViewGraphic);
+            });
+          }
+        },
 
-                    addLogsViewGraphic(e) {
-                        event.stopPropagation();
-                        var action = "";
-                        var objectName = "";
-                        var objectType = "";
-                        var objectDescription = "";
-                        switch(e.target.id) {
-                            case "investedTime":
-                                action = "viewed";
-                                objectName = "invested_time";
-                                objectType = "chart";
-                                objectDescription = "Bar chart that shows the average time invested by students as a function of the expected invested time";
-                                break;
-                            case "sessionsPerHour":
-                                action = "viewed";
-                                objectName = "hours_sessions";
-                                objectType = "chart";
-                                objectDescription = "Chart showing the number of sessions performed according to the time of day";
-                                break;
-                            case "sessionsPerWeek":
-                                action = "viewed";
-                                objectName = "sessions_count";
-                                objectType = "chart";
-                                objectDescription = "Chart showing the number of sessions performed per week";
-                                break;
-                            default:
-                                action = "viewed";
-                                objectName = "";
-                                objectType = "chart";
-                                objectDescription = "A chart";
-                                break;
-                        }
-                        vue.addLogsIntoDB(action, objectName, objectType, objectDescription);
-                    },
+        addLogsViewGraphic(e) {
+          event.stopPropagation();
+          var action = "";
+          var objectName = "";
+          var objectType = "";
+          var objectDescription = "";
+          switch (e.target.id) {
+            case "investedTime":
+              action = "viewed";
+              objectName = "invested_time";
+              objectType = "chart";
+              objectDescription =
+                "Bar chart that shows the average time invested by students as a function of the expected invested time";
+              break;
+            case "sessionsPerHour":
+              action = "viewed";
+              objectName = "hours_sessions";
+              objectType = "chart";
+              objectDescription =
+                "Chart showing the number of sessions performed according to the time of day";
+              break;
+            case "sessionsPerWeek":
+              action = "viewed";
+              objectName = "sessions_count";
+              objectType = "chart";
+              objectDescription =
+                "Chart showing the number of sessions performed per week";
+              break;
+            default:
+              action = "viewed";
+              objectName = "";
+              objectType = "chart";
+              objectDescription = "A chart";
+              break;
+          }
+          vue.addLogsIntoDB(action, objectName, objectType, objectDescription);
+        },
 
-                    addLogsIntoDB(action, objectName, objectType, objectDescription) {
-                        let data = {
-                            courseid: content.courseid,
-                            userid: content.userid,
-                            action: "addLogs",
-                            sectionname: "TEACHER_STUDY_SESSIONS",
-                            actiontype: action,
-                            objectType: objectType,
-                            objectName: objectName,
-                            currentUrl: document.location.href,
-                            objectDescription: objectDescription,
-                        };
-                        Axios({
-                            method:'get',
-                            url: M.cfg.wwwroot + "/local/notemyprogress/ajax.php",
-                            params : data,
-                        }).then((response) => {
-                            if (response.status == 200 && response.data.ok) {
-                            }
-                        }).catch((e) => {
-                        });
-                    },
-                }
+        addLogsIntoDB(action, objectName, objectType, objectDescription) {
+          let data = {
+            courseid: content.courseid,
+            userid: content.userid,
+            action: "addLogs",
+            sectionname: "TEACHER_STUDY_SESSIONS",
+            actiontype: action,
+            objectType: objectType,
+            objectName: objectName,
+            currentUrl: document.location.href,
+            objectDescription: objectDescription,
+          };
+          Axios({
+            method: "get",
+            url: M.cfg.wwwroot + "/local/notemyprogress/ajax.php",
+            params: data,
+          })
+            .then((response) => {
+              if (response.status == 200 && response.data.ok) {
+              }
             })
+            .catch((e) => {});
+        },
+      },
+    });
+  }
 
-        }
-
-        return {
-            init : init
-        };
-    });
\ No newline at end of file
+  return {
+    init: init,
+  };
+});
diff --git a/notemyprogress/amd/src/teacher.js b/notemyprogress/amd/src/teacher.js
deleted file mode 100644
index 516f045979325e9d354104572559ed77df141938..0000000000000000000000000000000000000000
--- a/notemyprogress/amd/src/teacher.js
+++ /dev/null
@@ -1,268 +0,0 @@
-define(["local_notemyprogress/vue",
-        "local_notemyprogress/vuetify",
-        "local_notemyprogress/axios",
-        "local_notemyprogress/pagination",
-        "local_notemyprogress/chartstatic",
-        "local_notemyprogress/pageheader",
-        "local_notemyprogress/helpdialog",
-    ],
-    function(Vue, Vuetify, Axios, Pagination, ChartStatic, PageHeader, HelpDialog) {
-        "use strict";
-
-        function init(content) {
-            // console.log(content);
-            Vue.use(Vuetify);
-            Vue.component('pagination', Pagination);
-            Vue.component('chart', ChartStatic);
-            Vue.component('pageheader', PageHeader);
-            Vue.component('helpdialog', HelpDialog);
-            let vue = new Vue({
-                delimiters: ["[[", "]]"],
-                el: "#teacher",
-                vuetify: new Vuetify(),
-                data() {
-                    return {
-                        strings : content.strings,
-                        groups : content.groups,
-                        userid : content.userid,
-                        courseid : content.courseid,
-                        timezone : content.timezone,
-                        render_has : content.profile_render,
-
-                        indicators: content.indicators,
-                        week_resources_colors: content.week_resources_colors,
-                        search: null,
-                        week_resources_categories: [],
-                        week_resources_data: [],
-
-                        help_dialog: false,
-                        help_contents: [],
-                    }
-                },
-                beforeMount(){
-                    this.calculate_week_resources();
-                },
-                mounted(){
-                    document.querySelector("#sessions-loader").style.display = "none";
-                    document.querySelector("#teacher").style.display = "block";
-                },
-                methods : {
-                    get_help_content(){
-                        let contents = [];
-                        contents.push({
-                            title: this.strings.section_help_title,
-                            description: this.strings.section_help_description,
-                        });
-                        return contents;
-                    },
-
-                    get_course_grade(){
-                        let grade = Number(this.indicators.course.grademax);
-                        return (this.isInt(grade)) ? grade : grade.toFixed(2);
-                    },
-
-                    calculate_week_resources() {
-                        let categories = [], data = [];
-                        let week_name;
-                        this.indicators.weeks.forEach(week => {
-                            week_name = `${week.name} ${(week.position+1)}`;
-                            categories.push(week_name);
-                            data.push(week.cms);
-                        });
-                        let name = this.capitalizeFirstLetter(this.strings.teacher_indicators_modules);
-                        this.week_resources_categories = categories;
-                        this.week_resources_data = [{ name, data}];
-                    },
-
-                    build_week_resources_chart() {
-                        let chart = new Object();
-                        chart.chart = {
-                            type: 'bar',
-                            backgroundColor: null,
-                            style: {fontFamily: 'poppins'},
-                        };
-                        chart.title = {
-                            text: null,
-                        };
-                        chart.colors = this.week_resources_colors;
-                        chart.xAxis = {
-                            categories: this.week_resources_categories
-                        };
-                        chart.yAxis = {
-                            min: 0,
-                                title: {
-                                text: this.strings.teacher_indicators_week_resources_yaxis_title
-                            }
-                        };
-                        chart.legend = {
-                            enabled: false
-                        };
-                        chart.series = this.week_resources_data;
-                        return chart;
-                    },
-
-                    build_weeks_sessions_chart() {
-                        let chart = new Object();
-                        chart.chart = {
-                            type: 'heatmap',
-                            backgroundColor: null,
-                            style: {fontFamily: 'poppins'},
-                        };
-                        chart.title = {
-                            text: null,
-                        };
-                        chart.xAxis = {
-                            categories: this.strings.weeks,
-                        };
-                        chart.yAxis = {
-                            categories: this.indicators.sessions.categories,
-                            title: null,
-                            reversed: true,
-                        };
-                        chart.colorAxis = {
-                            min: 0,
-                            minColor: '#E0E0E0',
-                            maxColor: '#118AB2'
-                        };
-                        chart.legend = {
-                            layout: 'horizontal',
-                            verticalAlign: 'bottom',
-                        };
-                        chart.tooltip = {
-                            formatter: function () {
-                                let days = vue.indicators.sessions.weeks[this.point.y][this.point.x] || '';
-                                let xCategoryName = vue.get_point_category_name(this.point, 'x');
-                                let yCategoryName = vue.get_point_category_name(this.point, 'y');
-                                let label = vue.strings.teacher_indicators_sessions;
-                                if (this.point.value == 1) {
-                                    label = vue.strings.teacher_indicators_session;
-                                }
-                                return '<b>' + yCategoryName + ' ' + xCategoryName + '</b>: '
-                                    + this.point.value +' ' + label + '<br/>' + days;
-                            }
-                        };
-                        chart.series = [{
-                            borderWidth: 2,
-                            borderColor: '#FAFAFA',
-                            data: this.indicators.sessions.data,
-                        }];
-                        return chart;
-                    },
-
-                    table_headers(){
-                        let headers = [
-                            { text: '', value : 'id', align : 'center', sortable : false},
-                            { text: this.strings.thead_name , value : 'firstname'},
-                            { text: this.strings.thead_lastname , value : 'lastname'},
-                            { text: this.strings.thead_email , value : 'email'},
-                            { text: this.strings.thead_progress , value : 'progress_percentage',  align : 'center'},
-                            { text: this.strings.thead_sessions , value : 'sessions_number',  align : 'center'},
-                            { text: this.strings.thead_time , value : 'inverted_time', align : 'center'},
-                        ];
-                        return headers;
-                    },
-
-                    get_picture_url(userid){
-                        let url = `${M.cfg.wwwroot}/user/pix.php?file=/${userid}/f1.jpg`;
-                        return url;
-                    },
-
-                    get_percentage_progress(value){
-                        return `${value} %`;
-                    },
-
-                    get_progress_tooltip(item){
-                        let module_label = this.strings.teacher_indicators_modules;
-                        let finished_label = this.strings.teacher_indicators_finished;
-                        if (item.cms.complete == 1) {
-                            module_label = this.strings.teacher_indicators_module;
-                            finished_label = this.strings.teacher_indicators_finalized;
-                        }
-                        return `${item.cms.complete} ${module_label} ${finished_label} ${this.strings.of_conector} ${item.cms.total}`;
-                    },
-
-                    get_point_category_name(point, dimension) {
-                        let series = point.series,
-                            isY = dimension === 'y',
-                            axis = series[isY ? 'yAxis' : 'xAxis'];
-                        return axis.categories[point[isY ? 'y' : 'x']];
-                    },
-
-                    capitalizeFirstLetter(string) {
-                        return string.charAt(0).toUpperCase() + string.slice(1);
-                    },
-
-                    isInt(n) {
-                        return n % 1 === 0;
-                    },
-
-                    open_chart_help(chart) {
-                        let contents = [];
-                        if (chart == "week_resources") {
-                            contents.push({
-                                title: this.strings.week_resources_help_title,
-                                description: this.strings.week_resources_help_description_p1,
-                            });
-                            contents.push({
-                                description: this.strings.week_resources_help_description_p2,
-                            });
-                        } else if (chart == "weeks_sessions") {
-                            contents.push({
-                                title: this.strings.weeks_sessions_help_title,
-                                description: this.strings.week_sessions_help_description_p1,
-                            });
-                            contents.push({
-                                description: this.strings.week_sessions_help_description_p2,
-                            });
-                        } else if (chart == "progress_table") {
-                            contents.push({
-                                title: this.strings.progress_table_help_title,
-                                description: this.strings.progress_table_help_description,
-                            });
-                        }
-                        this.help_contents = contents;
-                        if (this.help_contents.length) {
-                            this.help_dialog = true;
-                        }
-                    },
-
-                    update_help_dialog (value) {
-                        this.help_dialog = value;
-                    },
-
-                    get_timezone(){
-                        let information = `${this.strings.ss_change_timezone} ${this.timezone}`
-                        return information;
-                    },
-
-                    addLogsIntoDB(action, objectName, objectType, objectDescription) {
-                        let data = {
-                            courseid: content.courseid,
-                            userid: content.userid,
-                            action: "addLogs",
-                            sectionname: "TEACHER_GENERAL_INDICATORS",
-                            actiontype: action,
-                            objectType: objectType,
-                            objectName: objectName,
-                            currentUrl: document.location.href,
-                            objectDescription: objectDescription,
-                        };
-                        Axios({
-                            method:'get',
-                            url: M.cfg.wwwroot + "/local/notemyprogress/ajax.php",
-                            params : data,
-                        }).then((response) => {
-                            if (response.status == 200 && response.data.ok) {
-                            }
-                        }).catch((e) => {
-                        });
-                    },
-
-                }
-            })
-        }
-
-        return {
-            init : init
-        };
-    });
\ No newline at end of file
diff --git a/notemyprogress/classes/configgamification.php b/notemyprogress/classes/configgamification.php
index 0a4f947f7ea560db8d1b18b4322ca10f727f5ffc..3fb9d502f2dcd001c6e220e6eddce06380f743c5 100644
--- a/notemyprogress/classes/configgamification.php
+++ b/notemyprogress/classes/configgamification.php
@@ -115,7 +115,12 @@ class configgamification {
             $levelsData->levelsdata = json_decode($levelsData->levelsdata);
             $levelsData->settings = json_decode($levelsData->settings);
             $levelsData->rules = json_decode($levelsData->rules);
-        }
+
+            
+
+            }
+            $sql = "SELECT enablegamification from {notemyprogress_gamification} where courseid=? AND timecreated=? ";
+            $value = $DB->get_record_sql($sql, array("courseid="=>($courseid),"timecreated="=>$timecrated->maximum));
 
         return $levelsData;
     }
@@ -193,19 +198,6 @@ class configgamification {
         $list = [];
 
         $coreevents = $this->get_core_events();
-//!        $list[] = [get_string('coresystem') => array_reduce(array_keys($coreevents), function($carry, $prefix) use ($coreevents) {
-//!            return array_merge($carry, array_reduce($coreevents[$prefix], function($carry, $eventclass) use ($prefix) {
-//!                $infos = self::get_event_infos($eventclass);
-//!                if ($infos) {
-//!                    $carry[$infos['eventname']] = get_string('tg_colon', 'local_notemyprogress', (object) [
-//!                        'a' => $prefix,
-// !                       'b' => $infos['name']
-//  !                  ]);
-//  !              }
-//  !              return $carry;
-//  !          }, []));
-//  !      }, [])];
-
         $coreevents = [get_string('coresystem') => array_reduce(array_keys($coreevents), function($carry, $prefix) use ($coreevents) {
             return array_merge($carry, array_reduce($coreevents[$prefix], function($carry, $eventclass) use ($prefix) {
                 $infos = self::get_event_infos($eventclass);
@@ -393,4 +385,25 @@ class configgamification {
         }
         return $eventclasses;
     }
+    /**
+     * Get the data needed to complete the graph.
+     *
+     * @param int $courseid the course id.
+     * @return array an array containing the apropriate data well formated 
+     */
+    public static function get_spread_chart($courseid){
+        Global $DB;
+        $resultat = [];
+        $levelsData = "SELECT MAX(level) as lvl from {notemyprogress_xp} where courseid=?";
+        $lvl = $DB->get_record_sql($levelsData, array("courseid="=>($courseid)));
+        $i = 1;
+        while($i<=$lvl->lvl){
+            $levelCount = "SELECT COUNT(*) as cpt from {notemyprogress_xp} where courseid=? and level=?";
+            $cpt = $DB->get_record_sql($levelCount, array("courseid="=>($courseid),"level="=>($i)));
+            $string = "level {$i} :";
+            array_push( $resultat,[$string,intval($cpt->cpt)]);
+            $i = $i+1;
+        }
+        return $resultat;
+    }
 }
\ No newline at end of file
diff --git a/notemyprogress/classes/event_strategy.php b/notemyprogress/classes/event_strategy.php
index d7ef122e8bac722b3ad5bce3cc7544881c679880..134b9aee5171eefbb2ab689e68ed484daf01eec2 100644
--- a/notemyprogress/classes/event_strategy.php
+++ b/notemyprogress/classes/event_strategy.php
@@ -358,11 +358,16 @@ class event_strategy {
      *
      * @return users
      */
-    public function get_ranking() {
+    public function get_ranking($int) {
         global $DB;
 
         $users = array();
-        $sql = "SELECT * FROM {{$this->table_xp}} WHERE courseid = {$this->course->id} and rankable = 1 ORDER BY points DESC";
+        if ($int==1){
+            $sql = "SELECT * FROM {{$this->table_xp}} WHERE courseid = {$this->course->id} and rankable = 1 ORDER BY points DESC";
+        }else{
+            $sql = "SELECT * FROM {{$this->table_xp}} WHERE courseid = {$this->course->id} ORDER BY points DESC";
+        }
+        
         $rank = $DB->get_recordset_sql($sql);
         $index = 1;
 
diff --git a/notemyprogress/gamification.php b/notemyprogress/gamification.php
index 4a32d7751800de10ad1b1cceaafc055206835866..392dac98236677db5eaaea684b5bde729fa11283 100644
--- a/notemyprogress/gamification.php
+++ b/notemyprogress/gamification.php
@@ -23,7 +23,7 @@
  * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 require_once('locallib.php');
-global $COURSE, $USER;
+global $COURSE, $USER , $DB;
 
 $courseid = required_param('courseid', PARAM_INT);
 $course = $DB->get_record('course', array('id' => $courseid), '*', MUST_EXIST);
@@ -36,14 +36,27 @@ require_capability('local/notemyprogress:usepluggin', $context);
 require_capability('local/notemyprogress:teacher_gamification', $context);
 require_capability('local/notemyprogress:setweeks', $context);
 
+$maxTimeSql = "SELECT MAX(timecreated) as maximum from {notemyprogress_gamification} where courseid=? ";
+$timecrated = $DB->get_record_sql($maxTimeSql, array("courseid="=>($courseid)));
+
+$sql = "SELECT enablegamification from {notemyprogress_gamification} where courseid=? AND timecreated=? ";
+$value = $DB->get_record_sql($sql, array("courseid="=>($courseid),"timecreated="=>$timecrated->maximum));
+if($value->enablegamification==1){
+    $swValue = true;
+}else{
+    $swValue = false;
+}
+
 $actualLink = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
 
 $logs = new \local_notemyprogress\logs($COURSE->id, $USER->id);
-$logs->addLogsNMP("viewed", "section", "CONFIGURATION_GAMIFICATION", "configuration_gamification", $actualLink, "Section where teacher can configure gamification");
-
+$logs->addLogsNMP("viewed", "section", "CONFIGURATION_GAMIFICATION", "configuration_gamification", $actualLink, "Section where teacher can configure gamification"); 
 
 $configgamification = new \local_notemyprogress\configgamification($COURSE->id, $USER->id);
 $es = new \local_notemyprogress\event_strategy($COURSE, $USER);
+$reports = new \local_notemyprogress\teacher($COURSE->id, $USER->id);
+
+
 
 $content = [
     'strings' =>[
@@ -87,15 +100,26 @@ $content = [
         'add_rule' => get_string("tg_section_settings_add_rule","local_notemyprogress"),
         'earn' => get_string("tg_section_settings_earn","local_notemyprogress"),
         'select_event' => get_string("tg_section_settings_select_event","local_notemyprogress"),
-
+        'enable'=>get_string("EnableGame","local_notemyprogress"),
+        'swValue'=>$swValue,
+        'chart' => $reports->get_chart_langs(),
+        'pointError'=>get_string("game_point_error","local_notemyprogress"),
+        'eventError'=>get_string("game_event_error","local_notemyprogress"),
+        'nameError'=>get_string("game_name_error","local_notemyprogress"),
+        'chartTitle'=>get_string("gm_Chart_Title","local_notemyprogress"),
+        'chartYaxis'=>get_string("gm_Chart_Y","local_notemyprogress"),
     ],
     'token' => local_notemyprogress_generate_token($COURSE->id, $USER->id, "teacher"),
-//    'userid' => $USER->id,
-//    'courseid' => $courseid,
+    'userid' => $USER->id,
+    'courseid' => $courseid,
     'levels_data' => $configgamification->get_levels_data(),
-    'ranking' => $es->get_ranking(),
+    'ranking' => $es->get_ranking(0),
     'events' => $configgamification->events_list(),
-    'image' => $OUTPUT->image_url('badge', 'local_notemyprogress')
+    'image' => $OUTPUT->image_url('badge', 'local_notemyprogress'),
+    'indicators' => $reports->get_general_indicators(),
+    'profile_render' => $reports->render_has(),
+    'timezone' => $reports->timezone,
+    'chart_data' => $configgamification->get_spread_chart($COURSE->id),
 ];
 
 $templatecontext = [
diff --git a/notemyprogress/js/highcharts/highcharts.src.js b/notemyprogress/js/highcharts/highcharts.src.js
index d8256d90570499e39c82e91ad80cb7294ee247c8..eab1ec4f806f46453de3965511828507d970445f 100644
--- a/notemyprogress/js/highcharts/highcharts.src.js
+++ b/notemyprogress/js/highcharts/highcharts.src.js
@@ -5,45166 +5,48241 @@
  *
  * License: www.highcharts.com/license
  */
-'use strict';
+"use strict";
 (function (root, factory) {
-    if (typeof module === 'object' && module.exports) {
-        factory['default'] = factory;
-        module.exports = root.document ?
-            factory(root) :
-            factory;
-    } else if (typeof define === 'function' && define.amd) {
-        define('highcharts/highcharts', function () {
-            return factory(root);
+  if (typeof module === "object" && module.exports) {
+    factory["default"] = factory;
+    module.exports = root.document ? factory(root) : factory;
+  } else if (typeof define === "function" && define.amd) {
+    define("highcharts/highcharts", function () {
+      return factory(root);
+    });
+  } else {
+    if (root.Highcharts) {
+      root.Highcharts.error(16, true);
+    }
+    root.Highcharts = factory(root);
+  }
+})(typeof window !== "undefined" ? window : this, function (win) {
+  var _modules = {};
+  function _registerModule(obj, path, args, fn) {
+    if (!obj.hasOwnProperty(path)) {
+      obj[path] = fn.apply(null, args);
+    }
+  }
+  _registerModule(_modules, "Core/Globals.js", [], function () {
+    /* *
+     *
+     *  (c) 2010-2020 Torstein Honsi
+     *
+     *  License: www.highcharts.com/license
+     *
+     *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+     *
+     * */
+    /* globals Image, window */
+    /**
+     * Reference to the global SVGElement class as a workaround for a name conflict
+     * in the Highcharts namespace.
+     *
+     * @global
+     * @typedef {global.SVGElement} GlobalSVGElement
+     *
+     * @see https://developer.mozilla.org/en-US/docs/Web/API/SVGElement
+     */
+    // glob is a temporary fix to allow our es-modules to work.
+    var glob = // @todo UMD variable named `window`, and glob named `win`
+        typeof win !== "undefined"
+          ? win
+          : typeof window !== "undefined"
+          ? window
+          : {},
+      doc = glob.document,
+      SVG_NS = "http://www.w3.org/2000/svg",
+      userAgent = (glob.navigator && glob.navigator.userAgent) || "",
+      svg =
+        doc &&
+        doc.createElementNS &&
+        !!doc.createElementNS(SVG_NS, "svg").createSVGRect,
+      isMS = /(edge|msie|trident)/i.test(userAgent) && !glob.opera,
+      isFirefox = userAgent.indexOf("Firefox") !== -1,
+      isChrome = userAgent.indexOf("Chrome") !== -1,
+      hasBidiBug =
+        isFirefox && parseInt(userAgent.split("Firefox/")[1], 10) < 4; // issue #38
+    var H = {
+      product: "Highcharts",
+      version: "8.2.2",
+      deg2rad: (Math.PI * 2) / 360,
+      doc: doc,
+      hasBidiBug: hasBidiBug,
+      hasTouch: !!glob.TouchEvent,
+      isMS: isMS,
+      isWebKit: userAgent.indexOf("AppleWebKit") !== -1,
+      isFirefox: isFirefox,
+      isChrome: isChrome,
+      isSafari: !isChrome && userAgent.indexOf("Safari") !== -1,
+      isTouchDevice: /(Mobile|Android|Windows Phone)/.test(userAgent),
+      SVG_NS: SVG_NS,
+      chartCount: 0,
+      seriesTypes: {},
+      symbolSizes: {},
+      svg: svg,
+      win: glob,
+      marginNames: ["plotTop", "marginRight", "marginBottom", "plotLeft"],
+      noop: function () {},
+      /**
+       * Theme options that should get applied to the chart. In module mode it
+       * might not be possible to change this property because of read-only
+       * restrictions, instead use {@link Highcharts.setOptions}.
+       *
+       * @name Highcharts.theme
+       * @type {Highcharts.Options}
+       */
+      /**
+       * An array containing the current chart objects in the page. A chart's
+       * position in the array is preserved throughout the page's lifetime. When
+       * a chart is destroyed, the array item becomes `undefined`.
+       *
+       * @name Highcharts.charts
+       * @type {Array<Highcharts.Chart|undefined>}
+       */
+      charts: [],
+      /**
+       * A hook for defining additional date format specifiers. New
+       * specifiers are defined as key-value pairs by using the
+       * specifier as key, and a function which takes the timestamp as
+       * value. This function returns the formatted portion of the
+       * date.
+       *
+       * @sample highcharts/global/dateformats/
+       *         Adding support for week number
+       *
+       * @name Highcharts.dateFormats
+       * @type {Highcharts.Dictionary<Highcharts.TimeFormatCallbackFunction>}
+       */
+      dateFormats: {},
+    };
+
+    return H;
+  });
+  _registerModule(
+    _modules,
+    "Core/Utilities.js",
+    [_modules["Core/Globals.js"]],
+    function (H) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      /**
+       * An animation configuration. Animation configurations can also be defined as
+       * booleans, where `false` turns off animation and `true` defaults to a duration
+       * of 500ms and defer of 0ms.
+       *
+       * @interface Highcharts.AnimationOptionsObject
+       */ /**
+       * A callback function to exectute when the animation finishes.
+       * @name Highcharts.AnimationOptionsObject#complete
+       * @type {Function|undefined}
+       */ /**
+       * The animation defer in milliseconds.
+       * @name Highcharts.AnimationOptionsObject#defer
+       * @type {number|undefined}
+       */ /**
+       * The animation duration in milliseconds.
+       * @name Highcharts.AnimationOptionsObject#duration
+       * @type {number|undefined}
+       */ /**
+       * The name of an easing function as defined on the `Math` object.
+       * @name Highcharts.AnimationOptionsObject#easing
+       * @type {string|Function|undefined}
+       */ /**
+       * A callback function to execute on each step of each attribute or CSS property
+       * that's being animated. The first argument contains information about the
+       * animation and progress.
+       * @name Highcharts.AnimationOptionsObject#step
+       * @type {Function|undefined}
+       */
+      /**
+       * Creates a frame for the animated SVG element.
+       *
+       * @callback Highcharts.AnimationStepCallbackFunction
+       *
+       * @param {Highcharts.SVGElement} this
+       *        The SVG element to animate.
+       *
+       * @return {void}
+       */
+      /**
+       * Interface description for a class.
+       *
+       * @interface Highcharts.Class<T>
+       * @extends Function
+       */ /**
+       * Class costructor.
+       * @function Highcharts.Class<T>#new
+       * @param {...Array<*>} args
+       *        Constructor arguments.
+       * @return {T}
+       *         Class instance.
+       */
+      /**
+       * A style object with camel case property names to define visual appearance of
+       * a SVG element or HTML element. The properties can be whatever styles are
+       * supported on the given SVG or HTML element.
+       *
+       * @example
+       * {
+       *    fontFamily: 'monospace',
+       *    fontSize: '1.2em'
+       * }
+       *
+       * @interface Highcharts.CSSObject
+       */ /**
+       * @name Highcharts.CSSObject#[key:string]
+       * @type {boolean|number|string|undefined}
+       */ /**
+       * Background style for the element.
+       * @name Highcharts.CSSObject#background
+       * @type {string|undefined}
+       */ /**
+       * Background color of the element.
+       * @name Highcharts.CSSObject#backgroundColor
+       * @type {Highcharts.ColorString|undefined}
+       */ /**
+       * Border style for the element.
+       * @name Highcharts.CSSObject#border
+       * @type {string|undefined}
+       */ /**
+       * Radius of the element border.
+       * @name Highcharts.CSSObject#borderRadius
+       * @type {number|undefined}
+       */ /**
+       * Color used in the element. The 'contrast' option is a Highcharts custom
+       * property that results in black or white, depending on the background of the
+       * element.
+       * @name Highcharts.CSSObject#color
+       * @type {'contrast'|Highcharts.ColorString|undefined}
+       */ /**
+       * Style of the mouse cursor when resting over the element.
+       * @name Highcharts.CSSObject#cursor
+       * @type {Highcharts.CursorValue|undefined}
+       */ /**
+       * Font family of the element text. Multiple values have to be in decreasing
+       * preference order and separated by comma.
+       * @name Highcharts.CSSObject#fontFamily
+       * @type {string|undefined}
+       */ /**
+       * Font size of the element text.
+       * @name Highcharts.CSSObject#fontSize
+       * @type {string|undefined}
+       */ /**
+       * Font weight of the element text.
+       * @name Highcharts.CSSObject#fontWeight
+       * @type {string|undefined}
+       */ /**
+       * Height of the element.
+       * @name Highcharts.CSSObject#height
+       * @type {number|undefined}
+       */ /**
+       * Width of the element border.
+       * @name Highcharts.CSSObject#lineWidth
+       * @type {number|undefined}
+       */ /**
+       * Opacity of the element.
+       * @name Highcharts.CSSObject#opacity
+       * @type {number|undefined}
+       */ /**
+       * Space around the element content.
+       * @name Highcharts.CSSObject#padding
+       * @type {string|undefined}
+       */ /**
+       * Behaviour of the element when the mouse cursor rests over it.
+       * @name Highcharts.CSSObject#pointerEvents
+       * @type {string|undefined}
+       */ /**
+       * Positioning of the element.
+       * @name Highcharts.CSSObject#position
+       * @type {string|undefined}
+       */ /**
+       * Alignment of the element text.
+       * @name Highcharts.CSSObject#textAlign
+       * @type {string|undefined}
+       */ /**
+       * Additional decoration of the element text.
+       * @name Highcharts.CSSObject#textDecoration
+       * @type {string|undefined}
+       */ /**
+       * Outline style of the element text.
+       * @name Highcharts.CSSObject#textOutline
+       * @type {string|undefined}
+       */ /**
+       * Line break style of the element text. Highcharts SVG elements support
+       * `ellipsis` when a `width` is set.
+       * @name Highcharts.CSSObject#textOverflow
+       * @type {string|undefined}
+       */ /**
+       * Top spacing of the element relative to the parent element.
+       * @name Highcharts.CSSObject#top
+       * @type {string|undefined}
+       */ /**
+       * Animated transition of selected element properties.
+       * @name Highcharts.CSSObject#transition
+       * @type {string|undefined}
+       */ /**
+       * Line break style of the element text.
+       * @name Highcharts.CSSObject#whiteSpace
+       * @type {string|undefined}
+       */ /**
+       * Width of the element.
+       * @name Highcharts.CSSObject#width
+       * @type {number|undefined}
+       */
+      /**
+       * All possible cursor styles.
+       *
+       * @typedef {'alias'|'all-scroll'|'auto'|'cell'|'col-resize'|'context-menu'|'copy'|'crosshair'|'default'|'e-resize'|'ew-resize'|'grab'|'grabbing'|'help'|'move'|'n-resize'|'ne-resize'|'nesw-resize'|'no-drop'|'none'|'not-allowed'|'ns-resize'|'nw-resize'|'nwse-resize'|'pointer'|'progress'|'row-resize'|'s-resize'|'se-resize'|'sw-resize'|'text'|'vertical-text'|'w-resize'|'wait'|'zoom-in'|'zoom-out'} Highcharts.CursorValue
+       */
+      /**
+       * All possible dash styles.
+       *
+       * @typedef {'Dash'|'DashDot'|'Dot'|'LongDash'|'LongDashDot'|'LongDashDotDot'|'ShortDash'|'ShortDashDot'|'ShortDashDotDot'|'ShortDot'|'Solid'} Highcharts.DashStyleValue
+       */
+      /**
+       * Generic dictionary in TypeScript notation.
+       * Use the native `Record<string, any>` instead.
+       *
+       * @deprecated
+       * @interface Highcharts.Dictionary<T>
+       */ /**
+       * @name Highcharts.Dictionary<T>#[key:string]
+       * @type {T}
+       */
+      /**
+       * The function callback to execute when the event is fired. The `this` context
+       * contains the instance, that fired the event.
+       *
+       * @callback Highcharts.EventCallbackFunction<T>
+       *
+       * @param {T} this
+       *
+       * @param {Highcharts.Dictionary<*>|Event} [eventArguments]
+       *        Event arguments.
+       *
+       * @return {boolean|void}
+       */
+      /**
+       * The event options for adding function callback.
+       *
+       * @interface Highcharts.EventOptionsObject
+       */ /**
+       * The order the event handler should be called. This opens for having one
+       * handler be called before another, independent of in which order they were
+       * added.
+       * @name Highcharts.EventOptionsObject#order
+       * @type {number}
+       */
+      /**
+       * Formats data as a string. Usually the data is accessible throught the `this`
+       * keyword.
+       *
+       * @callback Highcharts.FormatterCallbackFunction<T>
+       *
+       * @param {T} this
+       *        Context to format
+       *
+       * @return {string}
+       *         Formatted text
+       */
+      /**
+       * An object of key-value pairs for HTML attributes.
+       *
+       * @typedef {Highcharts.Dictionary<boolean|number|string|Function>} Highcharts.HTMLAttributes
+       */
+      /**
+       * An HTML DOM element. The type is a reference to the regular HTMLElement in
+       * the global scope.
+       *
+       * @typedef {global.HTMLElement} Highcharts.HTMLDOMElement
+       *
+       * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement
+       */
+      /**
+       * The iterator callback.
+       *
+       * @callback Highcharts.ObjectEachCallbackFunction<T>
+       *
+       * @param {T} this
+       *        The context.
+       *
+       * @param {*} value
+       *        The property value.
+       *
+       * @param {string} key
+       *        The property key.
+       *
+       * @param {*} obj
+       *        The object that objectEach is being applied to.
+       */
+      /**
+       * An object containing `left` and `top` properties for the position in the
+       * page.
+       *
+       * @interface Highcharts.OffsetObject
+       */ /**
+       * Left distance to the page border.
+       * @name Highcharts.OffsetObject#left
+       * @type {number}
+       */ /**
+       * Top distance to the page border.
+       * @name Highcharts.OffsetObject#top
+       * @type {number}
+       */
+      /**
+       * Describes a range.
+       *
+       * @interface Highcharts.RangeObject
+       */ /**
+       * Maximum number of the range.
+       * @name Highcharts.RangeObject#max
+       * @type {number}
+       */ /**
+       * Minimum number of the range.
+       * @name Highcharts.RangeObject#min
+       * @type {number}
+       */
+      /**
+       * If a number is given, it defines the pixel length. If a percentage string is
+       * given, like for example `'50%'`, the setting defines a length relative to a
+       * base size, for example the size of a container.
+       *
+       * @typedef {number|string} Highcharts.RelativeSize
+       */
+      /**
+       * Proceed function to call original (wrapped) function.
+       *
+       * @callback Highcharts.WrapProceedFunction
+       *
+       * @param {*} [arg1]
+       *        Optional argument. Without any arguments defaults to first argument of
+       *        the wrapping function.
+       *
+       * @param {*} [arg2]
+       *        Optional argument. Without any arguments defaults to second argument
+       *        of the wrapping function.
+       *
+       * @param {*} [arg3]
+       *        Optional argument. Without any arguments defaults to third argument of
+       *        the wrapping function.
+       *
+       * @return {*}
+       *         Return value of the original function.
+       */
+      /**
+       * The Highcharts object is the placeholder for all other members, and various
+       * utility functions. The most important member of the namespace would be the
+       * chart constructor.
+       *
+       * @example
+       * var chart = Highcharts.chart('container', { ... });
+       *
+       * @namespace Highcharts
+       */
+      H.timers = [];
+      var charts = H.charts,
+        doc = H.doc,
+        win = H.win;
+      /**
+       * Provide error messages for debugging, with links to online explanation. This
+       * function can be overridden to provide custom error handling.
+       *
+       * @sample highcharts/chart/highcharts-error/
+       *         Custom error handler
+       *
+       * @function Highcharts.error
+       *
+       * @param {number|string} code
+       *        The error code. See
+       *        [errors.xml](https://github.com/highcharts/highcharts/blob/master/errors/errors.xml)
+       *        for available codes. If it is a string, the error message is printed
+       *        directly in the console.
+       *
+       * @param {boolean} [stop=false]
+       *        Whether to throw an error or just log a warning in the console.
+       *
+       * @param {Highcharts.Chart} [chart]
+       *        Reference to the chart that causes the error. Used in 'debugger'
+       *        module to display errors directly on the chart.
+       *        Important note: This argument is undefined for errors that lack
+       *        access to the Chart instance.
+       *
+       * @param {Highcharts.Dictionary<string>} [params]
+       *        Additional parameters for the generated message.
+       *
+       * @return {void}
+       */
+      function error(code, stop, chart, params) {
+        var severity = stop ? "Highcharts error" : "Highcharts warning";
+        if (code === 32) {
+          code = severity + ": Deprecated member";
+        }
+        var isCode = isNumber(code),
+          message = isCode
+            ? severity +
+              " #" +
+              code +
+              ": www.highcharts.com/errors/" +
+              code +
+              "/"
+            : code.toString(),
+          defaultHandler = function () {
+            if (stop) {
+              throw new Error(message);
+            }
+            // else ...
+            if (
+              win.console &&
+              error.messages.indexOf(message) === -1 // prevent console flooting
+            ) {
+              console.log(message); // eslint-disable-line no-console
+            }
+          };
+        if (typeof params !== "undefined") {
+          var additionalMessages_1 = "";
+          if (isCode) {
+            message += "?";
+          }
+          objectEach(params, function (value, key) {
+            additionalMessages_1 += "\n - " + key + ": " + value;
+            if (isCode) {
+              message += encodeURI(key) + "=" + encodeURI(value);
+            }
+          });
+          message += additionalMessages_1;
+        }
+        if (chart) {
+          fireEvent(
+            chart,
+            "displayError",
+            { code: code, message: message, params: params },
+            defaultHandler
+          );
+        } else {
+          defaultHandler();
+        }
+        error.messages.push(message);
+      }
+      (function (error) {
+        error.messages = [];
+      })(error || (error = {}));
+      H.error = error;
+      /* eslint-disable valid-jsdoc */
+      /**
+       * Utility function to deep merge two or more objects and return a third object.
+       * If the first argument is true, the contents of the second object is copied
+       * into the first object. The merge function can also be used with a single
+       * object argument to create a deep copy of an object.
+       *
+       * @function Highcharts.merge<T>
+       *
+       * @param {boolean} extend
+       *        Whether to extend the left-side object (a) or return a whole new
+       *        object.
+       *
+       * @param {T|undefined} a
+       *        The first object to extend. When only this is given, the function
+       *        returns a deep copy.
+       *
+       * @param {...Array<object|undefined>} [n]
+       *        An object to merge into the previous one.
+       *
+       * @return {T}
+       *         The merged object. If the first argument is true, the return is the
+       *         same as the second argument.
+       */ /**
+       * Utility function to deep merge two or more objects and return a third object.
+       * The merge function can also be used with a single object argument to create a
+       * deep copy of an object.
+       *
+       * @function Highcharts.merge<T>
+       *
+       * @param {T|undefined} a
+       *        The first object to extend. When only this is given, the function
+       *        returns a deep copy.
+       *
+       * @param {...Array<object|undefined>} [n]
+       *        An object to merge into the previous one.
+       *
+       * @return {T}
+       *         The merged object. If the first argument is true, the return is the
+       *         same as the second argument.
+       */
+      function merge() {
+        /* eslint-enable valid-jsdoc */
+        var i,
+          args = arguments,
+          len,
+          ret = {},
+          doCopy = function (copy, original) {
+            // An object is replacing a primitive
+            if (typeof copy !== "object") {
+              copy = {};
+            }
+            objectEach(original, function (value, key) {
+              // Copy the contents of objects, but not arrays or DOM nodes
+              if (
+                isObject(value, true) &&
+                !isClass(value) &&
+                !isDOMElement(value)
+              ) {
+                copy[key] = doCopy(copy[key] || {}, value);
+                // Primitives and arrays are copied over directly
+              } else {
+                copy[key] = original[key];
+              }
+            });
+            return copy;
+          };
+        // If first argument is true, copy into the existing object. Used in
+        // setOptions.
+        if (args[0] === true) {
+          ret = args[1];
+          args = Array.prototype.slice.call(args, 2);
+        }
+        // For each argument, extend the return
+        len = args.length;
+        for (i = 0; i < len; i++) {
+          ret = doCopy(ret, args[i]);
+        }
+        return ret;
+      }
+      H.merge = merge;
+      /**
+       * Constrain a value to within a lower and upper threshold.
+       *
+       * @private
+       * @param {number} value The initial value
+       * @param {number} min The lower threshold
+       * @param {number} max The upper threshold
+       * @return {number} Returns a number value within min and max.
+       */
+      function clamp(value, min, max) {
+        return value > min ? (value < max ? value : max) : min;
+      }
+      /**
+       * Shortcut for parseInt
+       *
+       * @private
+       * @function Highcharts.pInt
+       *
+       * @param {*} s
+       *        any
+       *
+       * @param {number} [mag]
+       *        Magnitude
+       *
+       * @return {number}
+       *         number
+       */
+      var pInt = (H.pInt = function pInt(s, mag) {
+        return parseInt(s, mag || 10);
+      });
+      /**
+       * Utility function to check for string type.
+       *
+       * @function Highcharts.isString
+       *
+       * @param {*} s
+       *        The item to check.
+       *
+       * @return {boolean}
+       *         True if the argument is a string.
+       */
+      var isString = (H.isString = function isString(s) {
+        return typeof s === "string";
+      });
+      /**
+       * Utility function to check if an item is an array.
+       *
+       * @function Highcharts.isArray
+       *
+       * @param {*} obj
+       *        The item to check.
+       *
+       * @return {boolean}
+       *         True if the argument is an array.
+       */
+      var isArray = (H.isArray = function isArray(obj) {
+        var str = Object.prototype.toString.call(obj);
+        return str === "[object Array]" || str === "[object Array Iterator]";
+      });
+      /**
+       * Utility function to check if an item is of type object.
+       *
+       * @function Highcharts.isObject
+       *
+       * @param {*} obj
+       *        The item to check.
+       *
+       * @param {boolean} [strict=false]
+       *        Also checks that the object is not an array.
+       *
+       * @return {boolean}
+       *         True if the argument is an object.
+       */
+      function isObject(obj, strict) {
+        return !!obj && typeof obj === "object" && (!strict || !isArray(obj)); // eslint-disable-line @typescript-eslint/no-explicit-any
+      }
+      H.isObject = isObject;
+      /**
+       * Utility function to check if an Object is a HTML Element.
+       *
+       * @function Highcharts.isDOMElement
+       *
+       * @param {*} obj
+       *        The item to check.
+       *
+       * @return {boolean}
+       *         True if the argument is a HTML Element.
+       */
+      var isDOMElement = (H.isDOMElement = function isDOMElement(obj) {
+        return isObject(obj) && typeof obj.nodeType === "number";
+      });
+      /**
+       * Utility function to check if an Object is a class.
+       *
+       * @function Highcharts.isClass
+       *
+       * @param {object|undefined} obj
+       *        The item to check.
+       *
+       * @return {boolean}
+       *         True if the argument is a class.
+       */
+      var isClass = (H.isClass = function isClass(obj) {
+        var c = obj && obj.constructor;
+        return !!(
+          isObject(obj, true) &&
+          !isDOMElement(obj) &&
+          c &&
+          c.name &&
+          c.name !== "Object"
+        );
+      });
+      /**
+       * Utility function to check if an item is a number and it is finite (not NaN,
+       * Infinity or -Infinity).
+       *
+       * @function Highcharts.isNumber
+       *
+       * @param {*} n
+       *        The item to check.
+       *
+       * @return {boolean}
+       *         True if the item is a finite number
+       */
+      var isNumber = (H.isNumber = function isNumber(n) {
+        return (
+          typeof n === "number" && !isNaN(n) && n < Infinity && n > -Infinity
+        );
+      });
+      /**
+       * Remove the last occurence of an item from an array.
+       *
+       * @function Highcharts.erase
+       *
+       * @param {Array<*>} arr
+       *        The array.
+       *
+       * @param {*} item
+       *        The item to remove.
+       *
+       * @return {void}
+       */
+      var erase = (H.erase = function erase(arr, item) {
+        var i = arr.length;
+        while (i--) {
+          if (arr[i] === item) {
+            arr.splice(i, 1);
+            break;
+          }
+        }
+      });
+      /**
+       * Check if an object is null or undefined.
+       *
+       * @function Highcharts.defined
+       *
+       * @param {*} obj
+       *        The object to check.
+       *
+       * @return {boolean}
+       *         False if the object is null or undefined, otherwise true.
+       */
+      var defined = (H.defined = function defined(obj) {
+        return typeof obj !== "undefined" && obj !== null;
+      });
+      /**
+       * Set or get an attribute or an object of attributes. To use as a setter, pass
+       * a key and a value, or let the second argument be a collection of keys and
+       * values. To use as a getter, pass only a string as the second argument.
+       *
+       * @function Highcharts.attr
+       *
+       * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} elem
+       *        The DOM element to receive the attribute(s).
+       *
+       * @param {string|Highcharts.HTMLAttributes|Highcharts.SVGAttributes} [prop]
+       *        The property or an object of key-value pairs.
+       *
+       * @param {number|string} [value]
+       *        The value if a single property is set.
+       *
+       * @return {string|null|undefined}
+       *         When used as a getter, return the value.
+       */
+      function attr(elem, prop, value) {
+        var ret;
+        // if the prop is a string
+        if (isString(prop)) {
+          // set the value
+          if (defined(value)) {
+            elem.setAttribute(prop, value);
+            // get the value
+          } else if (elem && elem.getAttribute) {
+            ret = elem.getAttribute(prop);
+            // IE7 and below cannot get class through getAttribute (#7850)
+            if (!ret && prop === "class") {
+              ret = elem.getAttribute(prop + "Name");
+            }
+          }
+          // else if prop is defined, it is a hash of key/value pairs
+        } else {
+          objectEach(prop, function (val, key) {
+            elem.setAttribute(key, val);
+          });
+        }
+        return ret;
+      }
+      H.attr = attr;
+      /**
+       * Check if an element is an array, and if not, make it into an array.
+       *
+       * @function Highcharts.splat
+       *
+       * @param {*} obj
+       *        The object to splat.
+       *
+       * @return {Array}
+       *         The produced or original array.
+       */
+      var splat = (H.splat = function splat(obj) {
+        return isArray(obj) ? obj : [obj];
+      });
+      /**
+       * Set a timeout if the delay is given, otherwise perform the function
+       * synchronously.
+       *
+       * @function Highcharts.syncTimeout
+       *
+       * @param {Function} fn
+       *        The function callback.
+       *
+       * @param {number} delay
+       *        Delay in milliseconds.
+       *
+       * @param {*} [context]
+       *        An optional context to send to the function callback.
+       *
+       * @return {number}
+       *         An identifier for the timeout that can later be cleared with
+       *         Highcharts.clearTimeout. Returns -1 if there is no timeout.
+       */
+      var syncTimeout = (H.syncTimeout = function syncTimeout(
+        fn,
+        delay,
+        context
+      ) {
+        if (delay > 0) {
+          return setTimeout(fn, delay, context);
+        }
+        fn.call(0, context);
+        return -1;
+      });
+      /**
+       * Internal clear timeout. The function checks that the `id` was not removed
+       * (e.g. by `chart.destroy()`). For the details see
+       * [issue #7901](https://github.com/highcharts/highcharts/issues/7901).
+       *
+       * @function Highcharts.clearTimeout
+       *
+       * @param {number} id
+       *        Id of a timeout.
+       *
+       * @return {void}
+       */
+      var internalClearTimeout = (H.clearTimeout = function (id) {
+        if (defined(id)) {
+          clearTimeout(id);
+        }
+      });
+      /* eslint-disable valid-jsdoc */
+      /**
+       * Utility function to extend an object with the members of another.
+       *
+       * @function Highcharts.extend<T>
+       *
+       * @param {T|undefined} a
+       *        The object to be extended.
+       *
+       * @param {object} b
+       *        The object to add to the first one.
+       *
+       * @return {T}
+       *         Object a, the original object.
+       */
+      var extend = (H.extend = function extend(a, b) {
+        /* eslint-enable valid-jsdoc */
+        var n;
+        if (!a) {
+          a = {};
+        }
+        for (n in b) {
+          // eslint-disable-line guard-for-in
+          a[n] = b[n];
+        }
+        return a;
+      });
+      /* eslint-disable valid-jsdoc */
+      /**
+       * Return the first value that is not null or undefined.
+       *
+       * @function Highcharts.pick<T>
+       *
+       * @param {...Array<T|null|undefined>} items
+       *        Variable number of arguments to inspect.
+       *
+       * @return {T}
+       *         The value of the first argument that is not null or undefined.
+       */
+      function pick() {
+        var args = arguments;
+        var length = args.length;
+        for (var i = 0; i < length; i++) {
+          var arg = args[i];
+          if (typeof arg !== "undefined" && arg !== null) {
+            return arg;
+          }
+        }
+      }
+      H.pick = pick;
+      /**
+       * Set CSS on a given element.
+       *
+       * @function Highcharts.css
+       *
+       * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} el
+       *        An HTML DOM element.
+       *
+       * @param {Highcharts.CSSObject} styles
+       *        Style object with camel case property names.
+       *
+       * @return {void}
+       */
+      var css = (H.css = function css(el, styles) {
+        if (H.isMS && !H.svg) {
+          // #2686
+          if (styles && typeof styles.opacity !== "undefined") {
+            styles.filter = "alpha(opacity=" + styles.opacity * 100 + ")";
+          }
+        }
+        extend(el.style, styles);
+      });
+      /**
+       * Utility function to create an HTML element with attributes and styles.
+       *
+       * @function Highcharts.createElement
+       *
+       * @param {string} tag
+       *        The HTML tag.
+       *
+       * @param {Highcharts.HTMLAttributes} [attribs]
+       *        Attributes as an object of key-value pairs.
+       *
+       * @param {Highcharts.CSSObject} [styles]
+       *        Styles as an object of key-value pairs.
+       *
+       * @param {Highcharts.HTMLDOMElement} [parent]
+       *        The parent HTML object.
+       *
+       * @param {boolean} [nopad=false]
+       *        If true, remove all padding, border and margin.
+       *
+       * @return {Highcharts.HTMLDOMElement}
+       *         The created DOM element.
+       */
+      var createElement = (H.createElement = function createElement(
+        tag,
+        attribs,
+        styles,
+        parent,
+        nopad
+      ) {
+        var el = doc.createElement(tag);
+        if (attribs) {
+          extend(el, attribs);
+        }
+        if (nopad) {
+          css(el, { padding: "0", border: "none", margin: "0" });
+        }
+        if (styles) {
+          css(el, styles);
+        }
+        if (parent) {
+          parent.appendChild(el);
+        }
+        return el;
+      });
+      // eslint-disable-next-line valid-jsdoc
+      /**
+       * Extend a prototyped class by new members.
+       *
+       * @function Highcharts.extendClass<T>
+       *
+       * @param {Highcharts.Class<T>} parent
+       *        The parent prototype to inherit.
+       *
+       * @param {Highcharts.Dictionary<*>} members
+       *        A collection of prototype members to add or override compared to the
+       *        parent prototype.
+       *
+       * @return {Highcharts.Class<T>}
+       *         A new prototype.
+       */
+      var extendClass = (H.extendClass = function extendClass(parent, members) {
+        var obj = function () {};
+        obj.prototype = new parent(); // eslint-disable-line new-cap
+        extend(obj.prototype, members);
+        return obj;
+      });
+      /**
+       * Left-pad a string to a given length by adding a character repetetively.
+       *
+       * @function Highcharts.pad
+       *
+       * @param {number} number
+       *        The input string or number.
+       *
+       * @param {number} [length]
+       *        The desired string length.
+       *
+       * @param {string} [padder=0]
+       *        The character to pad with.
+       *
+       * @return {string}
+       *         The padded string.
+       */
+      var pad = (H.pad = function pad(number, length, padder) {
+        return (
+          new Array(
+            (length || 2) + 1 - String(number).replace("-", "").length
+          ).join(padder || "0") + number
+        );
+      });
+      /**
+       * Return a length based on either the integer value, or a percentage of a base.
+       *
+       * @function Highcharts.relativeLength
+       *
+       * @param {Highcharts.RelativeSize} value
+       *        A percentage string or a number.
+       *
+       * @param {number} base
+       *        The full length that represents 100%.
+       *
+       * @param {number} [offset=0]
+       *        A pixel offset to apply for percentage values. Used internally in
+       *        axis positioning.
+       *
+       * @return {number}
+       *         The computed length.
+       */
+      var relativeLength = (H.relativeLength = function relativeLength(
+        value,
+        base,
+        offset
+      ) {
+        return /%$/.test(value)
+          ? (base * parseFloat(value)) / 100 + (offset || 0)
+          : parseFloat(value);
+      });
+      /**
+       * Wrap a method with extended functionality, preserving the original function.
+       *
+       * @function Highcharts.wrap
+       *
+       * @param {*} obj
+       *        The context object that the method belongs to. In real cases, this is
+       *        often a prototype.
+       *
+       * @param {string} method
+       *        The name of the method to extend.
+       *
+       * @param {Highcharts.WrapProceedFunction} func
+       *        A wrapper function callback. This function is called with the same
+       *        arguments as the original function, except that the original function
+       *        is unshifted and passed as the first argument.
+       */
+      var wrap = (H.wrap = function wrap(obj, method, func) {
+        var proceed = obj[method];
+        obj[method] = function () {
+          var args = Array.prototype.slice.call(arguments),
+            outerArgs = arguments,
+            ctx = this,
+            ret;
+          ctx.proceed = function () {
+            proceed.apply(ctx, arguments.length ? arguments : outerArgs);
+          };
+          args.unshift(proceed);
+          ret = func.apply(this, args);
+          ctx.proceed = null;
+          return ret;
+        };
+      });
+      /**
+       * Format a string according to a subset of the rules of Python's String.format
+       * method.
+       *
+       * @example
+       * var s = Highcharts.format(
+       *     'The {color} fox was {len:.2f} feet long',
+       *     { color: 'red', len: Math.PI }
+       * );
+       * // => The red fox was 3.14 feet long
+       *
+       * @function Highcharts.format
+       *
+       * @param {string} str
+       *        The string to format.
+       *
+       * @param {Record<string, *>} ctx
+       *        The context, a collection of key-value pairs where each key is
+       *        replaced by its value.
+       *
+       * @param {Highcharts.Chart} [chart]
+       *        A `Chart` instance used to get numberFormatter and time.
+       *
+       * @return {string}
+       *         The formatted string.
+       */
+      var format = (H.format = function (str, ctx, chart) {
+        var splitter = "{",
+          isInside = false,
+          segment,
+          valueAndFormat,
+          ret = [],
+          val,
+          index;
+        var floatRegex = /f$/;
+        var decRegex = /\.([0-9])/;
+        var lang = H.defaultOptions.lang;
+        var time = (chart && chart.time) || H.time;
+        var numberFormatter = (chart && chart.numberFormatter) || numberFormat;
+        while (str) {
+          index = str.indexOf(splitter);
+          if (index === -1) {
+            break;
+          }
+          segment = str.slice(0, index);
+          if (isInside) {
+            // we're on the closing bracket looking back
+            valueAndFormat = segment.split(":");
+            val = getNestedProperty(valueAndFormat.shift() || "", ctx);
+            // Format the replacement
+            if (valueAndFormat.length && typeof val === "number") {
+              segment = valueAndFormat.join(":");
+              if (floatRegex.test(segment)) {
+                // float
+                var decimals = parseInt(
+                  (segment.match(decRegex) || ["", "-1"])[1],
+                  10
+                );
+                if (val !== null) {
+                  val = numberFormatter(
+                    val,
+                    decimals,
+                    lang.decimalPoint,
+                    segment.indexOf(",") > -1 ? lang.thousandsSep : ""
+                  );
+                }
+              } else {
+                val = time.dateFormat(segment, val);
+              }
+            }
+            // Push the result and advance the cursor
+            ret.push(val);
+          } else {
+            ret.push(segment);
+          }
+          str = str.slice(index + 1); // the rest
+          isInside = !isInside; // toggle
+          splitter = isInside ? "}" : "{"; // now look for next matching bracket
+        }
+        ret.push(str);
+        return ret.join("");
+      });
+      /**
+       * Get the magnitude of a number.
+       *
+       * @function Highcharts.getMagnitude
+       *
+       * @param {number} num
+       *        The number.
+       *
+       * @return {number}
+       *         The magnitude, where 1-9 are magnitude 1, 10-99 magnitude 2 etc.
+       */
+      var getMagnitude = (H.getMagnitude = function (num) {
+        return Math.pow(10, Math.floor(Math.log(num) / Math.LN10));
+      });
+      /**
+       * Take an interval and normalize it to multiples of round numbers.
+       *
+       * @deprecated
+       * @function Highcharts.normalizeTickInterval
+       *
+       * @param {number} interval
+       *        The raw, un-rounded interval.
+       *
+       * @param {Array<*>} [multiples]
+       *        Allowed multiples.
+       *
+       * @param {number} [magnitude]
+       *        The magnitude of the number.
+       *
+       * @param {boolean} [allowDecimals]
+       *        Whether to allow decimals.
+       *
+       * @param {boolean} [hasTickAmount]
+       *        If it has tickAmount, avoid landing on tick intervals lower than
+       *        original.
+       *
+       * @return {number}
+       *         The normalized interval.
+       *
+       * @todo
+       * Move this function to the Axis prototype. It is here only for historical
+       * reasons.
+       */
+      var normalizeTickInterval = (H.normalizeTickInterval = function (
+        interval,
+        multiples,
+        magnitude,
+        allowDecimals,
+        hasTickAmount
+      ) {
+        var normalized,
+          i,
+          retInterval = interval;
+        // round to a tenfold of 1, 2, 2.5 or 5
+        magnitude = pick(magnitude, 1);
+        normalized = interval / magnitude;
+        // multiples for a linear scale
+        if (!multiples) {
+          multiples = hasTickAmount
+            ? // Finer grained ticks when the tick amount is hard set, including
+              // when alignTicks is true on multiple axes (#4580).
+              [1, 1.2, 1.5, 2, 2.5, 3, 4, 5, 6, 8, 10]
+            : // Else, let ticks fall on rounder numbers
+              [1, 2, 2.5, 5, 10];
+          // the allowDecimals option
+          if (allowDecimals === false) {
+            if (magnitude === 1) {
+              multiples = multiples.filter(function (num) {
+                return num % 1 === 0;
+              });
+            } else if (magnitude <= 0.1) {
+              multiples = [1 / magnitude];
+            }
+          }
+        }
+        // normalize the interval to the nearest multiple
+        for (i = 0; i < multiples.length; i++) {
+          retInterval = multiples[i];
+          // only allow tick amounts smaller than natural
+          if (
+            (hasTickAmount && retInterval * magnitude >= interval) ||
+            (!hasTickAmount &&
+              normalized <=
+                (multiples[i] + (multiples[i + 1] || multiples[i])) / 2)
+          ) {
+            break;
+          }
+        }
+        // Multiply back to the correct magnitude. Correct floats to appropriate
+        // precision (#6085).
+        retInterval = correctFloat(
+          retInterval * magnitude,
+          -Math.round(Math.log(0.001) / Math.LN10)
+        );
+        return retInterval;
+      });
+      /**
+       * Sort an object array and keep the order of equal items. The ECMAScript
+       * standard does not specify the behaviour when items are equal.
+       *
+       * @function Highcharts.stableSort
+       *
+       * @param {Array<*>} arr
+       *        The array to sort.
+       *
+       * @param {Function} sortFunction
+       *        The function to sort it with, like with regular Array.prototype.sort.
+       *
+       * @return {void}
+       */
+      var stableSort = (H.stableSort = function stableSort(arr, sortFunction) {
+        // @todo It seems like Chrome since v70 sorts in a stable way internally,
+        // plus all other browsers do it, so over time we may be able to remove this
+        // function
+        var length = arr.length,
+          sortValue,
+          i;
+        // Add index to each item
+        for (i = 0; i < length; i++) {
+          arr[i].safeI = i; // stable sort index
+        }
+        arr.sort(function (a, b) {
+          sortValue = sortFunction(a, b);
+          return sortValue === 0 ? a.safeI - b.safeI : sortValue;
         });
-    } else {
-        if (root.Highcharts) {
-            root.Highcharts.error(16, true);
+        // Remove index from items
+        for (i = 0; i < length; i++) {
+          delete arr[i].safeI; // stable sort index
         }
-        root.Highcharts = factory(root);
-    }
-}(typeof window !== 'undefined' ? window : this, function (win) {
-    var _modules = {};
-    function _registerModule(obj, path, args, fn) {
-        if (!obj.hasOwnProperty(path)) {
-            obj[path] = fn.apply(null, args);
+      });
+      /**
+       * Non-recursive method to find the lowest member of an array. `Math.min` raises
+       * a maximum call stack size exceeded error in Chrome when trying to apply more
+       * than 150.000 points. This method is slightly slower, but safe.
+       *
+       * @function Highcharts.arrayMin
+       *
+       * @param {Array<*>} data
+       *        An array of numbers.
+       *
+       * @return {number}
+       *         The lowest number.
+       */
+      var arrayMin = (H.arrayMin = function arrayMin(data) {
+        var i = data.length,
+          min = data[0];
+        while (i--) {
+          if (data[i] < min) {
+            min = data[i];
+          }
         }
-    }
-    _registerModule(_modules, 'Core/Globals.js', [], function () {
-        /* *
+        return min;
+      });
+      /**
+       * Non-recursive method to find the lowest member of an array. `Math.max` raises
+       * a maximum call stack size exceeded error in Chrome when trying to apply more
+       * than 150.000 points. This method is slightly slower, but safe.
+       *
+       * @function Highcharts.arrayMax
+       *
+       * @param {Array<*>} data
+       *        An array of numbers.
+       *
+       * @return {number}
+       *         The highest number.
+       */
+      var arrayMax = (H.arrayMax = function arrayMax(data) {
+        var i = data.length,
+          max = data[0];
+        while (i--) {
+          if (data[i] > max) {
+            max = data[i];
+          }
+        }
+        return max;
+      });
+      /**
+       * Utility method that destroys any SVGElement instances that are properties on
+       * the given object. It loops all properties and invokes destroy if there is a
+       * destroy method. The property is then delete.
+       *
+       * @function Highcharts.destroyObjectProperties
+       *
+       * @param {*} obj
+       *        The object to destroy properties on.
+       *
+       * @param {*} [except]
+       *        Exception, do not destroy this property, only delete it.
+       */
+      var destroyObjectProperties = (H.destroyObjectProperties =
+        function destroyObjectProperties(obj, except) {
+          objectEach(obj, function (val, n) {
+            // If the object is non-null and destroy is defined
+            if (val && val !== except && val.destroy) {
+              // Invoke the destroy
+              val.destroy();
+            }
+            // Delete the property from the object.
+            delete obj[n];
+          });
+        });
+      /**
+       * Discard a HTML element by moving it to the bin and delete.
+       *
+       * @function Highcharts.discardElement
+       *
+       * @param {Highcharts.HTMLDOMElement} element
+       *        The HTML node to discard.
+       */
+      var discardElement = (H.discardElement = function discardElement(
+        element
+      ) {
+        var garbageBin = H.garbageBin;
+        // create a garbage bin element, not part of the DOM
+        if (!garbageBin) {
+          garbageBin = createElement("div");
+        }
+        // move the node and empty bin
+        if (element) {
+          garbageBin.appendChild(element);
+        }
+        garbageBin.innerHTML = "";
+      });
+      /**
+       * Fix JS round off float errors.
+       *
+       * @function Highcharts.correctFloat
+       *
+       * @param {number} num
+       *        A float number to fix.
+       *
+       * @param {number} [prec=14]
+       *        The precision.
+       *
+       * @return {number}
+       *         The corrected float number.
+       */
+      var correctFloat = (H.correctFloat = function correctFloat(num, prec) {
+        return parseFloat(num.toPrecision(prec || 14));
+      });
+      /**
+       * The time unit lookup
+       *
+       * @ignore
+       */
+      var timeUnits = (H.timeUnits = {
+        millisecond: 1,
+        second: 1000,
+        minute: 60000,
+        hour: 3600000,
+        day: 24 * 3600000,
+        week: 7 * 24 * 3600000,
+        month: 28 * 24 * 3600000,
+        year: 364 * 24 * 3600000,
+      });
+      /**
+       * Format a number and return a string based on input settings.
+       *
+       * @sample highcharts/members/highcharts-numberformat/
+       *         Custom number format
+       *
+       * @function Highcharts.numberFormat
+       *
+       * @param {number} number
+       *        The input number to format.
+       *
+       * @param {number} decimals
+       *        The amount of decimals. A value of -1 preserves the amount in the
+       *        input number.
+       *
+       * @param {string} [decimalPoint]
+       *        The decimal point, defaults to the one given in the lang options, or
+       *        a dot.
+       *
+       * @param {string} [thousandsSep]
+       *        The thousands separator, defaults to the one given in the lang
+       *        options, or a space character.
+       *
+       * @return {string}
+       *         The formatted number.
+       */
+      var numberFormat = (H.numberFormat = function numberFormat(
+        number,
+        decimals,
+        decimalPoint,
+        thousandsSep
+      ) {
+        number = +number || 0;
+        decimals = +decimals;
+        var lang = H.defaultOptions.lang,
+          origDec = (number.toString().split(".")[1] || "").split("e")[0]
+            .length,
+          strinteger,
+          thousands,
+          ret,
+          roundedNumber,
+          exponent = number.toString().split("e"),
+          fractionDigits;
+        if (decimals === -1) {
+          // Preserve decimals. Not huge numbers (#3793).
+          decimals = Math.min(origDec, 20);
+        } else if (!isNumber(decimals)) {
+          decimals = 2;
+        } else if (decimals && exponent[1] && exponent[1] < 0) {
+          // Expose decimals from exponential notation (#7042)
+          fractionDigits = decimals + +exponent[1];
+          if (fractionDigits >= 0) {
+            // remove too small part of the number while keeping the notation
+            exponent[0] = (+exponent[0])
+              .toExponential(fractionDigits)
+              .split("e")[0];
+            decimals = fractionDigits;
+          } else {
+            // fractionDigits < 0
+            exponent[0] = exponent[0].split(".")[0] || 0;
+            if (decimals < 20) {
+              // use number instead of exponential notation (#7405)
+              number = (exponent[0] * Math.pow(10, exponent[1])).toFixed(
+                decimals
+              );
+            } else {
+              // or zero
+              number = 0;
+            }
+            exponent[1] = 0;
+          }
+        }
+        // Add another decimal to avoid rounding errors of float numbers. (#4573)
+        // Then use toFixed to handle rounding.
+        roundedNumber = (
+          Math.abs(exponent[1] ? exponent[0] : number) +
+          Math.pow(10, -Math.max(decimals, origDec) - 1)
+        ).toFixed(decimals);
+        // A string containing the positive integer component of the number
+        strinteger = String(pInt(roundedNumber));
+        // Leftover after grouping into thousands. Can be 0, 1 or 2.
+        thousands = strinteger.length > 3 ? strinteger.length % 3 : 0;
+        // Language
+        decimalPoint = pick(decimalPoint, lang.decimalPoint);
+        thousandsSep = pick(thousandsSep, lang.thousandsSep);
+        // Start building the return
+        ret = number < 0 ? "-" : "";
+        // Add the leftover after grouping into thousands. For example, in the
+        // number 42 000 000, this line adds 42.
+        ret += thousands ? strinteger.substr(0, thousands) + thousandsSep : "";
+        // Add the remaining thousands groups, joined by the thousands separator
+        ret += strinteger
+          .substr(thousands)
+          .replace(/(\d{3})(?=\d)/g, "$1" + thousandsSep);
+        // Add the decimal point and the decimal component
+        if (decimals) {
+          // Get the decimal component
+          ret += decimalPoint + roundedNumber.slice(-decimals);
+        }
+        if (exponent[1] && +ret !== 0) {
+          ret += "e" + exponent[1];
+        }
+        return ret;
+      });
+      /**
+       * Easing definition
+       *
+       * @private
+       * @function Math.easeInOutSine
+       *
+       * @param {number} pos
+       *        Current position, ranging from 0 to 1.
+       *
+       * @return {number}
+       *         Ease result
+       */
+      Math.easeInOutSine = function (pos) {
+        return -0.5 * (Math.cos(Math.PI * pos) - 1);
+      };
+      /**
+       * Returns the value of a property path on a given object.
+       *
+       * @private
+       * @function getNestedProperty
+       *
+       * @param {string} path
+       * Path to the property, for example `custom.myValue`.
+       *
+       * @param {unknown} obj
+       * Instance containing the property on the specific path.
+       *
+       * @return {unknown}
+       * The unknown property value.
+       */
+      function getNestedProperty(path, obj) {
+        if (!path) {
+          return obj;
+        }
+        var pathElements = path.split(".").reverse();
+        var subProperty = obj;
+        if (pathElements.length === 1) {
+          return subProperty[path];
+        }
+        var pathElement = pathElements.pop();
+        while (
+          typeof pathElement !== "undefined" &&
+          typeof subProperty !== "undefined" &&
+          subProperty !== null
+        ) {
+          subProperty = subProperty[pathElement];
+          pathElement = pathElements.pop();
+        }
+        return subProperty;
+      }
+      /**
+       * Get the computed CSS value for given element and property, only for numerical
+       * properties. For width and height, the dimension of the inner box (excluding
+       * padding) is returned. Used for fitting the chart within the container.
+       *
+       * @function Highcharts.getStyle
+       *
+       * @param {Highcharts.HTMLDOMElement} el
+       *        An HTML element.
+       *
+       * @param {string} prop
+       *        The property name.
+       *
+       * @param {boolean} [toInt=true]
+       *        Parse to integer.
+       *
+       * @return {number|string}
+       *         The numeric value.
+       */
+      var getStyle = (H.getStyle = function (el, prop, toInt) {
+        var style;
+        // For width and height, return the actual inner pixel size (#4913)
+        if (prop === "width") {
+          var offsetWidth = Math.min(el.offsetWidth, el.scrollWidth);
+          // In flex boxes, we need to use getBoundingClientRect and floor it,
+          // because scrollWidth doesn't support subpixel precision (#6427) ...
+          var boundingClientRectWidth =
+            el.getBoundingClientRect && el.getBoundingClientRect().width;
+          // ...unless if the containing div or its parents are transform-scaled
+          // down, in which case the boundingClientRect can't be used as it is
+          // also scaled down (#9871, #10498).
+          if (
+            boundingClientRectWidth < offsetWidth &&
+            boundingClientRectWidth >= offsetWidth - 1
+          ) {
+            offsetWidth = Math.floor(boundingClientRectWidth);
+          }
+          return Math.max(
+            0, // #8377
+            offsetWidth -
+              H.getStyle(el, "padding-left") -
+              H.getStyle(el, "padding-right")
+          );
+        }
+        if (prop === "height") {
+          return Math.max(
+            0, // #8377
+            Math.min(el.offsetHeight, el.scrollHeight) -
+              H.getStyle(el, "padding-top") -
+              H.getStyle(el, "padding-bottom")
+          );
+        }
+        if (!win.getComputedStyle) {
+          // SVG not supported, forgot to load oldie.js?
+          error(27, true);
+        }
+        // Otherwise, get the computed style
+        style = win.getComputedStyle(el, undefined); // eslint-disable-line no-undefined
+        if (style) {
+          style = style.getPropertyValue(prop);
+          if (pick(toInt, prop !== "opacity")) {
+            style = pInt(style);
+          }
+        }
+        return style;
+      });
+      /**
+       * Search for an item in an array.
+       *
+       * @function Highcharts.inArray
+       *
+       * @deprecated
+       *
+       * @param {*} item
+       *        The item to search for.
+       *
+       * @param {Array<*>} arr
+       *        The array or node collection to search in.
+       *
+       * @param {number} [fromIndex=0]
+       *        The index to start searching from.
+       *
+       * @return {number}
+       *         The index within the array, or -1 if not found.
+       */
+      var inArray = (H.inArray = function (item, arr, fromIndex) {
+        error(32, false, void 0, { "Highcharts.inArray": "use Array.indexOf" });
+        return arr.indexOf(item, fromIndex);
+      });
+      /* eslint-disable valid-jsdoc */
+      /**
+       * Return the value of the first element in the array that satisfies the
+       * provided testing function.
+       *
+       * @function Highcharts.find<T>
+       *
+       * @param {Array<T>} arr
+       *        The array to test.
+       *
+       * @param {Function} callback
+       *        The callback function. The function receives the item as the first
+       *        argument. Return `true` if this item satisfies the condition.
+       *
+       * @return {T|undefined}
+       *         The value of the element.
+       */
+      var find = (H.find = Array.prototype.find
+        ? /* eslint-enable valid-jsdoc */
+          function (arr, callback) {
+            return arr.find(callback);
+          }
+        : // Legacy implementation. PhantomJS, IE <= 11 etc. #7223.
+          function (arr, callback) {
+            var i,
+              length = arr.length;
+            for (i = 0; i < length; i++) {
+              if (callback(arr[i], i)) {
+                // eslint-disable-line callback-return
+                return arr[i];
+              }
+            }
+          });
+      /**
+       * Returns an array of a given object's own properties.
+       *
+       * @function Highcharts.keys
+       * @deprecated
+       *
+       * @param {*} obj
+       *        The object of which the properties are to be returned.
+       *
+       * @return {Array<string>}
+       *         An array of strings that represents all the properties.
+       */
+      H.keys = function (obj) {
+        error(32, false, void 0, { "Highcharts.keys": "use Object.keys" });
+        return Object.keys(obj);
+      };
+      /**
+       * Get the element's offset position, corrected for `overflow: auto`.
+       *
+       * @function Highcharts.offset
+       *
+       * @param {global.Element} el
+       *        The DOM element.
+       *
+       * @return {Highcharts.OffsetObject}
+       *         An object containing `left` and `top` properties for the position in
+       *         the page.
+       */
+      var offset = (H.offset = function offset(el) {
+        var docElem = doc.documentElement,
+          box =
+            el.parentElement || el.parentNode
+              ? el.getBoundingClientRect()
+              : { top: 0, left: 0 };
+        return {
+          top:
+            box.top +
+            (win.pageYOffset || docElem.scrollTop) -
+            (docElem.clientTop || 0),
+          left:
+            box.left +
+            (win.pageXOffset || docElem.scrollLeft) -
+            (docElem.clientLeft || 0),
+        };
+      });
+      /* eslint-disable valid-jsdoc */
+      /**
+       * Iterate over object key pairs in an object.
+       *
+       * @function Highcharts.objectEach<T>
+       *
+       * @param {*} obj
+       *        The object to iterate over.
+       *
+       * @param {Highcharts.ObjectEachCallbackFunction<T>} fn
+       *        The iterator callback. It passes three arguments:
+       *        * value - The property value.
+       *        * key - The property key.
+       *        * obj - The object that objectEach is being applied to.
+       *
+       * @param {T} [ctx]
+       *        The context.
+       *
+       * @return {void}
+       */
+      var objectEach = (H.objectEach = function objectEach(obj, fn, ctx) {
+        /* eslint-enable valid-jsdoc */
+        for (var key in obj) {
+          if (Object.hasOwnProperty.call(obj, key)) {
+            fn.call(ctx || obj[key], obj[key], key, obj);
+          }
+        }
+      });
+      /**
+       * Iterate over an array.
+       *
+       * @deprecated
+       * @function Highcharts.each
+       *
+       * @param {Array<*>} arr
+       *        The array to iterate over.
+       *
+       * @param {Function} fn
+       *        The iterator callback. It passes three arguments:
+       *        - `item`: The array item.
+       *        - `index`: The item's index in the array.
+       *        - `arr`: The array that each is being applied to.
+       *
+       * @param {*} [ctx]
+       *        The context.
+       *
+       * @return {void}
+       */
+      /**
+       * Filter an array by a callback.
+       *
+       * @deprecated
+       * @function Highcharts.grep
+       *
+       * @param {Array<*>} arr
+       *        The array to filter.
+       *
+       * @param {Function} callback
+       *        The callback function. The function receives the item as the first
+       *        argument. Return `true` if the item is to be preserved.
+       *
+       * @return {Array<*>}
+       *         A new, filtered array.
+       */
+      /**
+       * Map an array by a callback.
+       *
+       * @deprecated
+       * @function Highcharts.map
+       *
+       * @param {Array<*>} arr
+       *        The array to map.
+       *
+       * @param {Function} fn
+       *        The callback function. Return the new value for the new array.
+       *
+       * @return {Array<*>}
+       *         A new array item with modified items.
+       */
+      /**
+       * Reduce an array to a single value.
+       *
+       * @deprecated
+       * @function Highcharts.reduce
+       *
+       * @param {Array<*>} arr
+       *        The array to reduce.
+       *
+       * @param {Function} fn
+       *        The callback function. Return the reduced value. Receives 4
+       *        arguments: Accumulated/reduced value, current value, current array
+       *        index, and the array.
+       *
+       * @param {*} initialValue
+       *        The initial value of the accumulator.
+       *
+       * @return {*}
+       *         The reduced value.
+       */
+      /**
+       * Test whether at least one element in the array passes the test implemented by
+       * the provided function.
+       *
+       * @deprecated
+       * @function Highcharts.some
+       *
+       * @param {Array<*>} arr
+       *        The array to test
+       *
+       * @param {Function} fn
+       *        The function to run on each item. Return truty to pass the test.
+       *        Receives arguments `currentValue`, `index` and `array`.
+       *
+       * @param {*} ctx
+       *        The context.
+       *
+       * @return {boolean}
+       */
+      objectEach(
+        {
+          map: "map",
+          each: "forEach",
+          grep: "filter",
+          reduce: "reduce",
+          some: "some",
+        },
+        function (val, key) {
+          H[key] = function (arr) {
+            var _a;
+            error(
+              32,
+              false,
+              void 0,
+              ((_a = {}), (_a["Highcharts." + key] = "use Array." + val), _a)
+            );
+            return Array.prototype[val].apply(arr, [].slice.call(arguments, 1));
+          };
+        }
+      );
+      /* eslint-disable valid-jsdoc */
+      /**
+       * Add an event listener.
+       *
+       * @function Highcharts.addEvent<T>
+       *
+       * @param {Highcharts.Class<T>|T} el
+       *        The element or object to add a listener to. It can be a
+       *        {@link HTMLDOMElement}, an {@link SVGElement} or any other object.
+       *
+       * @param {string} type
+       *        The event type.
+       *
+       * @param {Highcharts.EventCallbackFunction<T>|Function} fn
+       *        The function callback to execute when the event is fired.
+       *
+       * @param {Highcharts.EventOptionsObject} [options]
+       *        Options for adding the event.
+       *
+       * @return {Function}
+       *         A callback function to remove the added event.
+       */
+      var addEvent = (H.addEvent = function (el, type, fn, options) {
+        if (options === void 0) {
+          options = {};
+        }
+        /* eslint-enable valid-jsdoc */
+        var events,
+          addEventListener = el.addEventListener || H.addEventListenerPolyfill;
+        // If we're setting events directly on the constructor, use a separate
+        // collection, `protoEvents` to distinguish it from the item events in
+        // `hcEvents`.
+        if (typeof el === "function" && el.prototype) {
+          events = el.prototype.protoEvents = el.prototype.protoEvents || {};
+        } else {
+          events = el.hcEvents = el.hcEvents || {};
+        }
+        // Allow click events added to points, otherwise they will be prevented by
+        // the TouchPointer.pinch function after a pinch zoom operation (#7091).
+        if (H.Point && el instanceof H.Point && el.series && el.series.chart) {
+          el.series.chart.runTrackerClick = true;
+        }
+        // Handle DOM events
+        if (addEventListener) {
+          addEventListener.call(el, type, fn, false);
+        }
+        if (!events[type]) {
+          events[type] = [];
+        }
+        var eventObject = {
+          fn: fn,
+          order: typeof options.order === "number" ? options.order : Infinity,
+        };
+        events[type].push(eventObject);
+        // Order the calls
+        events[type].sort(function (a, b) {
+          return a.order - b.order;
+        });
+        // Return a function that can be called to remove this event.
+        return function () {
+          removeEvent(el, type, fn);
+        };
+      });
+      /* eslint-disable valid-jsdoc */
+      /**
+       * Remove an event that was added with {@link Highcharts#addEvent}.
+       *
+       * @function Highcharts.removeEvent<T>
+       *
+       * @param {Highcharts.Class<T>|T} el
+       *        The element to remove events on.
+       *
+       * @param {string} [type]
+       *        The type of events to remove. If undefined, all events are removed
+       *        from the element.
+       *
+       * @param {Highcharts.EventCallbackFunction<T>} [fn]
+       *        The specific callback to remove. If undefined, all events that match
+       *        the element and optionally the type are removed.
+       *
+       * @return {void}
+       */
+      var removeEvent = (H.removeEvent = function removeEvent(el, type, fn) {
+        /* eslint-enable valid-jsdoc */
+        var events;
+        /**
+         * @private
+         * @param {string} type - event type
+         * @param {Highcharts.EventCallbackFunction<T>} fn - callback
+         * @return {void}
+         */
+        function removeOneEvent(type, fn) {
+          var removeEventListener =
+            el.removeEventListener || H.removeEventListenerPolyfill;
+          if (removeEventListener) {
+            removeEventListener.call(el, type, fn, false);
+          }
+        }
+        /**
+         * @private
+         * @param {any} eventCollection - collection
+         * @return {void}
+         */
+        function removeAllEvents(eventCollection) {
+          var types, len;
+          if (!el.nodeName) {
+            return; // break on non-DOM events
+          }
+          if (type) {
+            types = {};
+            types[type] = true;
+          } else {
+            types = eventCollection;
+          }
+          objectEach(types, function (_val, n) {
+            if (eventCollection[n]) {
+              len = eventCollection[n].length;
+              while (len--) {
+                removeOneEvent(n, eventCollection[n][len].fn);
+              }
+            }
+          });
+        }
+        ["protoEvents", "hcEvents"].forEach(function (coll, i) {
+          var eventElem = i ? el : el.prototype;
+          var eventCollection = eventElem && eventElem[coll];
+          if (eventCollection) {
+            if (type) {
+              events = eventCollection[type] || [];
+              if (fn) {
+                eventCollection[type] = events.filter(function (obj) {
+                  return fn !== obj.fn;
+                });
+                removeOneEvent(type, fn);
+              } else {
+                removeAllEvents(eventCollection);
+                eventCollection[type] = [];
+              }
+            } else {
+              removeAllEvents(eventCollection);
+              eventElem[coll] = {};
+            }
+          }
+        });
+      });
+      /* eslint-disable valid-jsdoc */
+      /**
+       * Fire an event that was registered with {@link Highcharts#addEvent}.
+       *
+       * @function Highcharts.fireEvent<T>
+       *
+       * @param {T} el
+       *        The object to fire the event on. It can be a {@link HTMLDOMElement},
+       *        an {@link SVGElement} or any other object.
+       *
+       * @param {string} type
+       *        The type of event.
+       *
+       * @param {Highcharts.Dictionary<*>|Event} [eventArguments]
+       *        Custom event arguments that are passed on as an argument to the event
+       *        handler.
+       *
+       * @param {Highcharts.EventCallbackFunction<T>|Function} [defaultFunction]
+       *        The default function to execute if the other listeners haven't
+       *        returned false.
+       *
+       * @return {void}
+       */
+      var fireEvent = (H.fireEvent = function (
+        el,
+        type,
+        eventArguments,
+        defaultFunction
+      ) {
+        /* eslint-enable valid-jsdoc */
+        var e, i;
+        eventArguments = eventArguments || {};
+        if (doc.createEvent && (el.dispatchEvent || el.fireEvent)) {
+          e = doc.createEvent("Events");
+          e.initEvent(type, true, true);
+          extend(e, eventArguments);
+          if (el.dispatchEvent) {
+            el.dispatchEvent(e);
+          } else {
+            el.fireEvent(type, e);
+          }
+        } else {
+          if (!eventArguments.target) {
+            // We're running a custom event
+            extend(eventArguments, {
+              // Attach a simple preventDefault function to skip
+              // default handler if called. The built-in
+              // defaultPrevented property is not overwritable (#5112)
+              preventDefault: function () {
+                eventArguments.defaultPrevented = true;
+              },
+              // Setting target to native events fails with clicking
+              // the zoom-out button in Chrome.
+              target: el,
+              // If the type is not set, we're running a custom event
+              // (#2297). If it is set, we're running a browser event,
+              // and setting it will cause en error in IE8 (#2465).
+              type: type,
+            });
+          }
+          var fireInOrder = function (protoEvents, hcEvents) {
+            if (protoEvents === void 0) {
+              protoEvents = [];
+            }
+            if (hcEvents === void 0) {
+              hcEvents = [];
+            }
+            var iA = 0;
+            var iB = 0;
+            var length = protoEvents.length + hcEvents.length;
+            for (i = 0; i < length; i++) {
+              var obj = !protoEvents[iA]
+                ? hcEvents[iB++]
+                : !hcEvents[iB]
+                ? protoEvents[iA++]
+                : protoEvents[iA].order <= hcEvents[iB].order
+                ? protoEvents[iA++]
+                : hcEvents[iB++];
+              // If the event handler return false, prevent the default
+              // handler from executing
+              if (obj.fn.call(el, eventArguments) === false) {
+                eventArguments.preventDefault();
+              }
+            }
+          };
+          fireInOrder(
+            el.protoEvents && el.protoEvents[type],
+            el.hcEvents && el.hcEvents[type]
+          );
+        }
+        // Run the default if not prevented
+        if (defaultFunction && !eventArguments.defaultPrevented) {
+          defaultFunction.call(el, eventArguments);
+        }
+      });
+      var serialMode;
+      /**
+       * Get a unique key for using in internal element id's and pointers. The key is
+       * composed of a random hash specific to this Highcharts instance, and a
+       * counter.
+       *
+       * @example
+       * var id = uniqueKey(); // => 'highcharts-x45f6hp-0'
+       *
+       * @function Highcharts.uniqueKey
+       *
+       * @return {string}
+       * A unique key.
+       */
+      var uniqueKey = (H.uniqueKey = (function () {
+        var hash = Math.random().toString(36).substring(2, 9) + "-";
+        var id = 0;
+        return function () {
+          return "highcharts-" + (serialMode ? "" : hash) + id++;
+        };
+      })());
+      /**
+       * Activates a serial mode for element IDs provided by
+       * {@link Highcharts.uniqueKey}. This mode can be used in automated tests, where
+       * a simple comparison of two rendered SVG graphics is needed.
+       *
+       * **Note:** This is only for testing purposes and will break functionality in
+       * webpages with multiple charts.
+       *
+       * @example
+       * if (
+       *   process &&
+       *   process.env.NODE_ENV === 'development'
+       * ) {
+       *   Highcharts.useSerialIds(true);
+       * }
+       *
+       * @function Highcharts.useSerialIds
+       *
+       * @param {boolean} [mode]
+       * Changes the state of serial mode.
+       *
+       * @return {boolean|undefined}
+       * State of the serial mode.
+       */
+      var useSerialIds = (H.useSerialIds = function (mode) {
+        return (serialMode = pick(mode, serialMode));
+      });
+      var isFunction = (H.isFunction = function (obj) {
+        return typeof obj === "function";
+      });
+      /**
+       * Get the updated default options. Until 3.0.7, merely exposing defaultOptions
+       * for outside modules wasn't enough because the setOptions method created a new
+       * object.
+       *
+       * @function Highcharts.getOptions
+       *
+       * @return {Highcharts.Options}
+       */
+      var getOptions = (H.getOptions = function () {
+        return H.defaultOptions;
+      });
+      /**
+       * Merge the default options with custom options and return the new options
+       * structure. Commonly used for defining reusable templates.
+       *
+       * @sample highcharts/global/useutc-false Setting a global option
+       * @sample highcharts/members/setoptions Applying a global theme
+       *
+       * @function Highcharts.setOptions
+       *
+       * @param {Highcharts.Options} options
+       *        The new custom chart options.
+       *
+       * @return {Highcharts.Options}
+       *         Updated options.
+       */
+      var setOptions = (H.setOptions = function (options) {
+        // Copy in the default options
+        H.defaultOptions = merge(true, H.defaultOptions, options);
+        // Update the time object
+        if (options.time || options.global) {
+          H.time.update(
+            merge(
+              H.defaultOptions.global,
+              H.defaultOptions.time,
+              options.global,
+              options.time
+            )
+          );
+        }
+        return H.defaultOptions;
+      });
+      // Register Highcharts as a plugin in jQuery
+      if (win.jQuery) {
+        /**
+         * Highcharts-extended JQuery.
          *
-         *  (c) 2010-2020 Torstein Honsi
+         * @external JQuery
+         */
+        /**
+         * Helper function to return the chart of the current JQuery selector
+         * element.
          *
-         *  License: www.highcharts.com/license
+         * @function external:JQuery#highcharts
          *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+         * @return {Highcharts.Chart}
+         *         The chart that is linked to the JQuery selector element.
+         */ /**
+         * Factory function to create a chart in the current JQuery selector
+         * element.
          *
-         * */
-        /* globals Image, window */
-        /**
-         * Reference to the global SVGElement class as a workaround for a name conflict
-         * in the Highcharts namespace.
-         *
-         * @global
-         * @typedef {global.SVGElement} GlobalSVGElement
-         *
-         * @see https://developer.mozilla.org/en-US/docs/Web/API/SVGElement
-         */
-        // glob is a temporary fix to allow our es-modules to work.
-        var glob = ( // @todo UMD variable named `window`, and glob named `win`
-            typeof win !== 'undefined' ?
-                win :
-                typeof window !== 'undefined' ?
-                    window :
-                    {}), doc = glob.document, SVG_NS = 'http://www.w3.org/2000/svg', userAgent = (glob.navigator && glob.navigator.userAgent) || '', svg = (doc &&
-                doc.createElementNS &&
-                !!doc.createElementNS(SVG_NS, 'svg').createSVGRect), isMS = /(edge|msie|trident)/i.test(userAgent) && !glob.opera, isFirefox = userAgent.indexOf('Firefox') !== -1, isChrome = userAgent.indexOf('Chrome') !== -1, hasBidiBug = (isFirefox &&
-                parseInt(userAgent.split('Firefox/')[1], 10) < 4 // issue #38
-            );
-        var H = {
-                product: 'Highcharts',
-                version: '8.2.2',
-                deg2rad: Math.PI * 2 / 360,
-                doc: doc,
-                hasBidiBug: hasBidiBug,
-                hasTouch: !!glob.TouchEvent,
-                isMS: isMS,
-                isWebKit: userAgent.indexOf('AppleWebKit') !== -1,
-                isFirefox: isFirefox,
-                isChrome: isChrome,
-                isSafari: !isChrome && userAgent.indexOf('Safari') !== -1,
-                isTouchDevice: /(Mobile|Android|Windows Phone)/.test(userAgent),
-                SVG_NS: SVG_NS,
-                chartCount: 0,
-                seriesTypes: {},
-                symbolSizes: {},
-                svg: svg,
-                win: glob,
-                marginNames: ['plotTop', 'marginRight', 'marginBottom', 'plotLeft'],
-                noop: function () { },
-                /**
-                 * Theme options that should get applied to the chart. In module mode it
-                 * might not be possible to change this property because of read-only
-                 * restrictions, instead use {@link Highcharts.setOptions}.
-                 *
-                 * @name Highcharts.theme
-                 * @type {Highcharts.Options}
-                 */
-                /**
-                 * An array containing the current chart objects in the page. A chart's
-                 * position in the array is preserved throughout the page's lifetime. When
-                 * a chart is destroyed, the array item becomes `undefined`.
-                 *
-                 * @name Highcharts.charts
-                 * @type {Array<Highcharts.Chart|undefined>}
-                 */
-                charts: [],
-                /**
-                 * A hook for defining additional date format specifiers. New
-                 * specifiers are defined as key-value pairs by using the
-                 * specifier as key, and a function which takes the timestamp as
-                 * value. This function returns the formatted portion of the
-                 * date.
-                 *
-                 * @sample highcharts/global/dateformats/
-                 *         Adding support for week number
-                 *
-                 * @name Highcharts.dateFormats
-                 * @type {Highcharts.Dictionary<Highcharts.TimeFormatCallbackFunction>}
-                 */
-                dateFormats: {}
-            };
+         * @function external:JQuery#highcharts
+         *
+         * @param {'Chart'|'Map'|'StockChart'|string} [className]
+         *        Name of the factory class in the Highcharts namespace.
+         *
+         * @param {Highcharts.Options} [options]
+         *        The chart options structure.
+         *
+         * @param {Highcharts.ChartCallbackFunction} [callback]
+         *        Function to run when the chart has loaded and and all external
+         *        images are loaded. Defining a
+         *        [chart.events.load](https://api.highcharts.com/highcharts/chart.events.load)
+         *        handler is equivalent.
+         *
+         * @return {JQuery}
+         *         The current JQuery selector.
+         */
+        win.jQuery.fn.highcharts = function () {
+          var args = [].slice.call(arguments);
+          if (this[0]) {
+            // this[0] is the renderTo div
+            // Create the chart
+            if (args[0]) {
+              new H[ // eslint-disable-line computed-property-spacing, no-new
+                // Constructor defaults to Chart
+                isString(args[0]) ? args.shift() : "Chart"
+              ](this[0], args[0], args[1]);
+              return this;
+            }
+            // When called without parameters or with the return argument,
+            // return an existing chart
+            return charts[attr(this[0], "data-highcharts-chart")];
+          }
+        };
+      }
+      // TODO use named exports when supported.
+      var utilitiesModule = {
+        addEvent: addEvent,
+        arrayMax: arrayMax,
+        arrayMin: arrayMin,
+        attr: attr,
+        clamp: clamp,
+        clearTimeout: internalClearTimeout,
+        correctFloat: correctFloat,
+        createElement: createElement,
+        css: css,
+        defined: defined,
+        destroyObjectProperties: destroyObjectProperties,
+        discardElement: discardElement,
+        erase: erase,
+        error: error,
+        extend: extend,
+        extendClass: extendClass,
+        find: find,
+        fireEvent: fireEvent,
+        format: format,
+        getMagnitude: getMagnitude,
+        getNestedProperty: getNestedProperty,
+        getOptions: getOptions,
+        getStyle: getStyle,
+        inArray: inArray,
+        isArray: isArray,
+        isClass: isClass,
+        isDOMElement: isDOMElement,
+        isFunction: isFunction,
+        isNumber: isNumber,
+        isObject: isObject,
+        isString: isString,
+        merge: merge,
+        normalizeTickInterval: normalizeTickInterval,
+        numberFormat: numberFormat,
+        objectEach: objectEach,
+        offset: offset,
+        pad: pad,
+        pick: pick,
+        pInt: pInt,
+        relativeLength: relativeLength,
+        removeEvent: removeEvent,
+        setOptions: setOptions,
+        splat: splat,
+        stableSort: stableSort,
+        syncTimeout: syncTimeout,
+        timeUnits: timeUnits,
+        uniqueKey: uniqueKey,
+        useSerialIds: useSerialIds,
+        wrap: wrap,
+      };
 
-        return H;
-    });
-    _registerModule(_modules, 'Core/Utilities.js', [_modules['Core/Globals.js']], function (H) {
+      return utilitiesModule;
+    }
+  );
+  _registerModule(
+    _modules,
+    "Core/Color/Color.js",
+    [_modules["Core/Globals.js"], _modules["Core/Utilities.js"]],
+    function (H, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      var isNumber = U.isNumber,
+        merge = U.merge,
+        pInt = U.pInt;
+      /**
+       * A valid color to be parsed and handled by Highcharts. Highcharts internally
+       * supports hex colors like `#ffffff`, rgb colors like `rgb(255,255,255)` and
+       * rgba colors like `rgba(255,255,255,1)`. Other colors may be supported by the
+       * browsers and displayed correctly, but Highcharts is not able to process them
+       * and apply concepts like opacity and brightening.
+       *
+       * @typedef {string} Highcharts.ColorString
+       */
+      /**
+       * A valid color type than can be parsed and handled by Highcharts. It can be a
+       * color string, a gradient object, or a pattern object.
+       *
+       * @typedef {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} Highcharts.ColorType
+       */
+      /**
+       * Gradient options instead of a solid color.
+       *
+       * @example
+       * // Linear gradient used as a color option
+       * color: {
+       *     linearGradient: { x1: 0, x2: 0, y1: 0, y2: 1 },
+       *     stops: [
+       *         [0, '#003399'], // start
+       *         [0.5, '#ffffff'], // middle
+       *         [1, '#3366AA'] // end
+       *     ]
+       * }
+       *
+       * @interface Highcharts.GradientColorObject
+       */ /**
+       * Holds an object that defines the start position and the end position relative
+       * to the shape.
+       * @name Highcharts.GradientColorObject#linearGradient
+       * @type {Highcharts.LinearGradientColorObject|undefined}
+       */ /**
+       * Holds an object that defines the center position and the radius.
+       * @name Highcharts.GradientColorObject#radialGradient
+       * @type {Highcharts.RadialGradientColorObject|undefined}
+       */ /**
+       * The first item in each tuple is the position in the gradient, where 0 is the
+       * start of the gradient and 1 is the end of the gradient. Multiple stops can be
+       * applied. The second item is the color for each stop. This color can also be
+       * given in the rgba format.
+       * @name Highcharts.GradientColorObject#stops
+       * @type {Array<Highcharts.GradientColorStopObject>}
+       */
+      /**
+       * Color stop tuple.
+       *
+       * @see Highcharts.GradientColorObject
+       *
+       * @interface Highcharts.GradientColorStopObject
+       */ /**
+       * @name Highcharts.GradientColorStopObject#0
+       * @type {number}
+       */ /**
+       * @name Highcharts.GradientColorStopObject#1
+       * @type {Highcharts.ColorString}
+       */ /**
+       * @name Highcharts.GradientColorStopObject#color
+       * @type {Highcharts.Color|undefined}
+       */
+      /**
+       * Defines the start position and the end position for a gradient relative
+       * to the shape. Start position (x1, y1) and end position (x2, y2) are relative
+       * to the shape, where 0 means top/left and 1 is bottom/right.
+       *
+       * @interface Highcharts.LinearGradientColorObject
+       */ /**
+       * Start horizontal position of the gradient. Float ranges 0-1.
+       * @name Highcharts.LinearGradientColorObject#x1
+       * @type {number}
+       */ /**
+       * End horizontal position of the gradient. Float ranges 0-1.
+       * @name Highcharts.LinearGradientColorObject#x2
+       * @type {number}
+       */ /**
+       * Start vertical position of the gradient. Float ranges 0-1.
+       * @name Highcharts.LinearGradientColorObject#y1
+       * @type {number}
+       */ /**
+       * End vertical position of the gradient. Float ranges 0-1.
+       * @name Highcharts.LinearGradientColorObject#y2
+       * @type {number}
+       */
+      /**
+       * Defines the center position and the radius for a gradient.
+       *
+       * @interface Highcharts.RadialGradientColorObject
+       */ /**
+       * Center horizontal position relative to the shape. Float ranges 0-1.
+       * @name Highcharts.RadialGradientColorObject#cx
+       * @type {number}
+       */ /**
+       * Center vertical position relative to the shape. Float ranges 0-1.
+       * @name Highcharts.RadialGradientColorObject#cy
+       * @type {number}
+       */ /**
+       * Radius relative to the shape. Float ranges 0-1.
+       * @name Highcharts.RadialGradientColorObject#r
+       * @type {number}
+       */
+      (""); // detach doclets above
+      /* *
+       *
+       *  Class
+       *
+       * */
+      /* eslint-disable no-invalid-this, valid-jsdoc */
+      /**
+       * Handle color operations. Some object methods are chainable.
+       *
+       * @class
+       * @name Highcharts.Color
+       *
+       * @param {Highcharts.ColorType} input
+       * The input color in either rbga or hex format
+       */
+      var Color = /** @class */ (function () {
         /* *
          *
-         *  (c) 2010-2020 Torstein Honsi
+         *  Constructors
          *
-         *  License: www.highcharts.com/license
+         * */
+        function Color(input) {
+          // Collection of parsers. This can be extended from the outside by pushing
+          // parsers to Highcharts.Color.prototype.parsers.
+          this.parsers = [
+            {
+              // RGBA color
+              // eslint-disable-next-line max-len
+              regex:
+                /rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]?(?:\.[0-9]+)?)\s*\)/,
+              parse: function (result) {
+                return [
+                  pInt(result[1]),
+                  pInt(result[2]),
+                  pInt(result[3]),
+                  parseFloat(result[4], 10),
+                ];
+              },
+            },
+            {
+              // RGB color
+              regex:
+                /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/,
+              parse: function (result) {
+                return [pInt(result[1]), pInt(result[2]), pInt(result[3]), 1];
+              },
+            },
+          ];
+          this.rgba = [];
+          // Backwards compatibility, allow class overwrite
+          if (H.Color !== Color) {
+            return new H.Color(input);
+          }
+          // Backwards compatibility, allow instanciation without new (#13053)
+          if (!(this instanceof Color)) {
+            return new Color(input);
+          }
+          this.init(input);
+        }
+        /* *
          *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+         *  Static Functions
          *
          * */
         /**
-         * An animation configuration. Animation configurations can also be defined as
-         * booleans, where `false` turns off animation and `true` defaults to a duration
-         * of 500ms and defer of 0ms.
+         * Creates a color instance out of a color string or object.
          *
-         * @interface Highcharts.AnimationOptionsObject
-         */ /**
-        * A callback function to exectute when the animation finishes.
-        * @name Highcharts.AnimationOptionsObject#complete
-        * @type {Function|undefined}
-        */ /**
-        * The animation defer in milliseconds.
-        * @name Highcharts.AnimationOptionsObject#defer
-        * @type {number|undefined}
-        */ /**
-        * The animation duration in milliseconds.
-        * @name Highcharts.AnimationOptionsObject#duration
-        * @type {number|undefined}
-        */ /**
-        * The name of an easing function as defined on the `Math` object.
-        * @name Highcharts.AnimationOptionsObject#easing
-        * @type {string|Function|undefined}
-        */ /**
-        * A callback function to execute on each step of each attribute or CSS property
-        * that's being animated. The first argument contains information about the
-        * animation and progress.
-        * @name Highcharts.AnimationOptionsObject#step
-        * @type {Function|undefined}
-        */
-        /**
-         * Creates a frame for the animated SVG element.
-         *
-         * @callback Highcharts.AnimationStepCallbackFunction
-         *
-         * @param {Highcharts.SVGElement} this
-         *        The SVG element to animate.
-         *
-         * @return {void}
-         */
-        /**
-         * Interface description for a class.
+         * @function Highcharts.Color.parse
          *
-         * @interface Highcharts.Class<T>
-         * @extends Function
-         */ /**
-        * Class costructor.
-        * @function Highcharts.Class<T>#new
-        * @param {...Array<*>} args
-        *        Constructor arguments.
-        * @return {T}
-        *         Class instance.
-        */
-        /**
-         * A style object with camel case property names to define visual appearance of
-         * a SVG element or HTML element. The properties can be whatever styles are
-         * supported on the given SVG or HTML element.
+         * @param {Highcharts.ColorType} input
+         * The input color in either rbga or hex format.
          *
-         * @example
-         * {
-         *    fontFamily: 'monospace',
-         *    fontSize: '1.2em'
-         * }
+         * @return {Highcharts.Color}
+         * Color instance.
+         */
+        Color.parse = function (input) {
+          return new Color(input);
+        };
+        /* *
          *
-         * @interface Highcharts.CSSObject
-         */ /**
-        * @name Highcharts.CSSObject#[key:string]
-        * @type {boolean|number|string|undefined}
-        */ /**
-        * Background style for the element.
-        * @name Highcharts.CSSObject#background
-        * @type {string|undefined}
-        */ /**
-        * Background color of the element.
-        * @name Highcharts.CSSObject#backgroundColor
-        * @type {Highcharts.ColorString|undefined}
-        */ /**
-        * Border style for the element.
-        * @name Highcharts.CSSObject#border
-        * @type {string|undefined}
-        */ /**
-        * Radius of the element border.
-        * @name Highcharts.CSSObject#borderRadius
-        * @type {number|undefined}
-        */ /**
-        * Color used in the element. The 'contrast' option is a Highcharts custom
-        * property that results in black or white, depending on the background of the
-        * element.
-        * @name Highcharts.CSSObject#color
-        * @type {'contrast'|Highcharts.ColorString|undefined}
-        */ /**
-        * Style of the mouse cursor when resting over the element.
-        * @name Highcharts.CSSObject#cursor
-        * @type {Highcharts.CursorValue|undefined}
-        */ /**
-        * Font family of the element text. Multiple values have to be in decreasing
-        * preference order and separated by comma.
-        * @name Highcharts.CSSObject#fontFamily
-        * @type {string|undefined}
-        */ /**
-        * Font size of the element text.
-        * @name Highcharts.CSSObject#fontSize
-        * @type {string|undefined}
-        */ /**
-        * Font weight of the element text.
-        * @name Highcharts.CSSObject#fontWeight
-        * @type {string|undefined}
-        */ /**
-        * Height of the element.
-        * @name Highcharts.CSSObject#height
-        * @type {number|undefined}
-        */ /**
-        * Width of the element border.
-        * @name Highcharts.CSSObject#lineWidth
-        * @type {number|undefined}
-        */ /**
-        * Opacity of the element.
-        * @name Highcharts.CSSObject#opacity
-        * @type {number|undefined}
-        */ /**
-        * Space around the element content.
-        * @name Highcharts.CSSObject#padding
-        * @type {string|undefined}
-        */ /**
-        * Behaviour of the element when the mouse cursor rests over it.
-        * @name Highcharts.CSSObject#pointerEvents
-        * @type {string|undefined}
-        */ /**
-        * Positioning of the element.
-        * @name Highcharts.CSSObject#position
-        * @type {string|undefined}
-        */ /**
-        * Alignment of the element text.
-        * @name Highcharts.CSSObject#textAlign
-        * @type {string|undefined}
-        */ /**
-        * Additional decoration of the element text.
-        * @name Highcharts.CSSObject#textDecoration
-        * @type {string|undefined}
-        */ /**
-        * Outline style of the element text.
-        * @name Highcharts.CSSObject#textOutline
-        * @type {string|undefined}
-        */ /**
-        * Line break style of the element text. Highcharts SVG elements support
-        * `ellipsis` when a `width` is set.
-        * @name Highcharts.CSSObject#textOverflow
-        * @type {string|undefined}
-        */ /**
-        * Top spacing of the element relative to the parent element.
-        * @name Highcharts.CSSObject#top
-        * @type {string|undefined}
-        */ /**
-        * Animated transition of selected element properties.
-        * @name Highcharts.CSSObject#transition
-        * @type {string|undefined}
-        */ /**
-        * Line break style of the element text.
-        * @name Highcharts.CSSObject#whiteSpace
-        * @type {string|undefined}
-        */ /**
-        * Width of the element.
-        * @name Highcharts.CSSObject#width
-        * @type {number|undefined}
-        */
-        /**
-         * All possible cursor styles.
-         *
-         * @typedef {'alias'|'all-scroll'|'auto'|'cell'|'col-resize'|'context-menu'|'copy'|'crosshair'|'default'|'e-resize'|'ew-resize'|'grab'|'grabbing'|'help'|'move'|'n-resize'|'ne-resize'|'nesw-resize'|'no-drop'|'none'|'not-allowed'|'ns-resize'|'nw-resize'|'nwse-resize'|'pointer'|'progress'|'row-resize'|'s-resize'|'se-resize'|'sw-resize'|'text'|'vertical-text'|'w-resize'|'wait'|'zoom-in'|'zoom-out'} Highcharts.CursorValue
-         */
-        /**
-         * All possible dash styles.
-         *
-         * @typedef {'Dash'|'DashDot'|'Dot'|'LongDash'|'LongDashDot'|'LongDashDotDot'|'ShortDash'|'ShortDashDot'|'ShortDashDotDot'|'ShortDot'|'Solid'} Highcharts.DashStyleValue
-         */
-        /**
-         * Generic dictionary in TypeScript notation.
-         * Use the native `Record<string, any>` instead.
+         *  Functions
          *
-         * @deprecated
-         * @interface Highcharts.Dictionary<T>
-         */ /**
-        * @name Highcharts.Dictionary<T>#[key:string]
-        * @type {T}
-        */
+         * */
         /**
-         * The function callback to execute when the event is fired. The `this` context
-         * contains the instance, that fired the event.
+         * Parse the input color to rgba array
          *
-         * @callback Highcharts.EventCallbackFunction<T>
-         *
-         * @param {T} this
+         * @private
+         * @function Highcharts.Color#init
          *
-         * @param {Highcharts.Dictionary<*>|Event} [eventArguments]
-         *        Event arguments.
+         * @param {Highcharts.ColorType} input
+         *        The input color in either rbga or hex format
          *
-         * @return {boolean|void}
+         * @return {void}
          */
+        Color.prototype.init = function (input) {
+          var result, rgba, i, parser, len;
+          this.input = input =
+            Color.names[
+              input && input.toLowerCase ? input.toLowerCase() : ""
+            ] || input;
+          // Gradients
+          if (input && input.stops) {
+            this.stops = input.stops.map(function (stop) {
+              return new Color(stop[1]);
+            });
+            // Solid colors
+          } else {
+            // Bitmasking as input[0] is not working for legacy IE.
+            if (input && input.charAt && input.charAt() === "#") {
+              len = input.length;
+              input = parseInt(input.substr(1), 16);
+              // Handle long-form, e.g. #AABBCC
+              if (len === 7) {
+                rgba = [
+                  (input & 0xff0000) >> 16,
+                  (input & 0xff00) >> 8,
+                  input & 0xff,
+                  1,
+                ];
+                // Handle short-form, e.g. #ABC
+                // In short form, the value is assumed to be the same
+                // for both nibbles for each component. e.g. #ABC = #AABBCC
+              } else if (len === 4) {
+                rgba = [
+                  ((input & 0xf00) >> 4) | ((input & 0xf00) >> 8),
+                  ((input & 0xf0) >> 4) | (input & 0xf0),
+                  ((input & 0xf) << 4) | (input & 0xf),
+                  1,
+                ];
+              }
+            }
+            // Otherwise, check regex parsers
+            if (!rgba) {
+              i = this.parsers.length;
+              while (i-- && !rgba) {
+                parser = this.parsers[i];
+                result = parser.regex.exec(input);
+                if (result) {
+                  rgba = parser.parse(result);
+                }
+              }
+            }
+          }
+          this.rgba = rgba || [];
+        };
         /**
-         * The event options for adding function callback.
-         *
-         * @interface Highcharts.EventOptionsObject
-         */ /**
-        * The order the event handler should be called. This opens for having one
-        * handler be called before another, independent of in which order they were
-        * added.
-        * @name Highcharts.EventOptionsObject#order
-        * @type {number}
-        */
-        /**
-         * Formats data as a string. Usually the data is accessible throught the `this`
-         * keyword.
+         * Return the color or gradient stops in the specified format
          *
-         * @callback Highcharts.FormatterCallbackFunction<T>
+         * @function Highcharts.Color#get
          *
-         * @param {T} this
-         *        Context to format
+         * @param {string} [format]
+         *        Possible values are 'a', 'rgb', 'rgba' (default).
          *
-         * @return {string}
-         *         Formatted text
+         * @return {Highcharts.ColorType}
+         *         This color as a string or gradient stops.
          */
+        Color.prototype.get = function (format) {
+          var input = this.input,
+            rgba = this.rgba,
+            ret;
+          if (typeof this.stops !== "undefined") {
+            ret = merge(input);
+            ret.stops = [].concat(ret.stops);
+            this.stops.forEach(function (stop, i) {
+              ret.stops[i] = [ret.stops[i][0], stop.get(format)];
+            });
+            // it's NaN if gradient colors on a column chart
+          } else if (rgba && isNumber(rgba[0])) {
+            if (format === "rgb" || (!format && rgba[3] === 1)) {
+              ret = "rgb(" + rgba[0] + "," + rgba[1] + "," + rgba[2] + ")";
+            } else if (format === "a") {
+              ret = rgba[3];
+            } else {
+              ret = "rgba(" + rgba.join(",") + ")";
+            }
+          } else {
+            ret = input;
+          }
+          return ret;
+        };
         /**
-         * An object of key-value pairs for HTML attributes.
+         * Brighten the color instance.
          *
-         * @typedef {Highcharts.Dictionary<boolean|number|string|Function>} Highcharts.HTMLAttributes
-         */
+         * @function Highcharts.Color#brighten
+         *
+         * @param {number} alpha
+         *        The alpha value.
+         *
+         * @return {Highcharts.Color}
+         *         This color with modifications.
+         */
+        Color.prototype.brighten = function (alpha) {
+          var i,
+            rgba = this.rgba;
+          if (this.stops) {
+            this.stops.forEach(function (stop) {
+              stop.brighten(alpha);
+            });
+          } else if (isNumber(alpha) && alpha !== 0) {
+            for (i = 0; i < 3; i++) {
+              rgba[i] += pInt(alpha * 255);
+              if (rgba[i] < 0) {
+                rgba[i] = 0;
+              }
+              if (rgba[i] > 255) {
+                rgba[i] = 255;
+              }
+            }
+          }
+          return this;
+        };
         /**
-         * An HTML DOM element. The type is a reference to the regular HTMLElement in
-         * the global scope.
+         * Set the color's opacity to a given alpha value.
          *
-         * @typedef {global.HTMLElement} Highcharts.HTMLDOMElement
+         * @function Highcharts.Color#setOpacity
          *
-         * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement
+         * @param {number} alpha
+         *        Opacity between 0 and 1.
+         *
+         * @return {Highcharts.Color}
+         *         Color with modifications.
          */
+        Color.prototype.setOpacity = function (alpha) {
+          this.rgba[3] = alpha;
+          return this;
+        };
         /**
-         * The iterator callback.
+         * Return an intermediate color between two colors.
          *
-         * @callback Highcharts.ObjectEachCallbackFunction<T>
+         * @function Highcharts.Color#tweenTo
          *
-         * @param {T} this
-         *        The context.
+         * @param {Highcharts.Color} to
+         *        The color object to tween to.
          *
-         * @param {*} value
-         *        The property value.
+         * @param {number} pos
+         *        The intermediate position, where 0 is the from color (current
+         *        color item), and 1 is the `to` color.
+         *
+         * @return {Highcharts.ColorString}
+         *         The intermediate color in rgba notation.
+         */
+        Color.prototype.tweenTo = function (to, pos) {
+          // Check for has alpha, because rgba colors perform worse due to lack of
+          // support in WebKit.
+          var fromRgba = this.rgba,
+            toRgba = to.rgba,
+            hasAlpha,
+            ret;
+          // Unsupported color, return to-color (#3920, #7034)
+          if (!toRgba.length || !fromRgba || !fromRgba.length) {
+            ret = to.input || "none";
+            // Interpolate
+          } else {
+            hasAlpha = toRgba[3] !== 1 || fromRgba[3] !== 1;
+            ret =
+              (hasAlpha ? "rgba(" : "rgb(") +
+              Math.round(toRgba[0] + (fromRgba[0] - toRgba[0]) * (1 - pos)) +
+              "," +
+              Math.round(toRgba[1] + (fromRgba[1] - toRgba[1]) * (1 - pos)) +
+              "," +
+              Math.round(toRgba[2] + (fromRgba[2] - toRgba[2]) * (1 - pos)) +
+              (hasAlpha
+                ? "," + (toRgba[3] + (fromRgba[3] - toRgba[3]) * (1 - pos))
+                : "") +
+              ")";
+          }
+          return ret;
+        };
+        /* *
          *
-         * @param {string} key
-         *        The property key.
+         *  Static Properties
          *
-         * @param {*} obj
-         *        The object that objectEach is being applied to.
-         */
-        /**
-         * An object containing `left` and `top` properties for the position in the
-         * page.
+         * */
+        // Collection of named colors. Can be extended from the outside by adding
+        // colors to Highcharts.Color.names.
+        Color.names = {
+          white: "#ffffff",
+          black: "#000000",
+        };
+        return Color;
+      })();
+      H.Color = Color;
+      /**
+       * Creates a color instance out of a color string.
+       *
+       * @function Highcharts.color
+       *
+       * @param {Highcharts.ColorType} input
+       *        The input color in either rbga or hex format
+       *
+       * @return {Highcharts.Color}
+       *         Color instance
+       */
+      H.color = Color.parse;
+      /* *
+       *
+       *  Export
+       *
+       * */
+
+      return Color;
+    }
+  );
+  _registerModule(
+    _modules,
+    "Core/Animation/Fx.js",
+    [_modules["Core/Globals.js"], _modules["Core/Utilities.js"]],
+    function (H, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      var win = H.win;
+      var isNumber = U.isNumber,
+        objectEach = U.objectEach;
+      /* eslint-disable no-invalid-this, valid-jsdoc */
+      /**
+       * An animator object used internally. One instance applies to one property
+       * (attribute or style prop) on one element. Animation is always initiated
+       * through {@link SVGElement#animate}.
+       *
+       * @example
+       * var rect = renderer.rect(0, 0, 10, 10).add();
+       * rect.animate({ width: 100 });
+       *
+       * @private
+       * @class
+       * @name Highcharts.Fx
+       */
+      var Fx = /** @class */ (function () {
+        /* *
          *
-         * @interface Highcharts.OffsetObject
-         */ /**
-        * Left distance to the page border.
-        * @name Highcharts.OffsetObject#left
-        * @type {number}
-        */ /**
-        * Top distance to the page border.
-        * @name Highcharts.OffsetObject#top
-        * @type {number}
-        */
-        /**
-         * Describes a range.
-         *
-         * @interface Highcharts.RangeObject
-         */ /**
-        * Maximum number of the range.
-        * @name Highcharts.RangeObject#max
-        * @type {number}
-        */ /**
-        * Minimum number of the range.
-        * @name Highcharts.RangeObject#min
-        * @type {number}
-        */
-        /**
-         * If a number is given, it defines the pixel length. If a percentage string is
-         * given, like for example `'50%'`, the setting defines a length relative to a
-         * base size, for example the size of a container.
+         *  Constructors
          *
-         * @typedef {number|string} Highcharts.RelativeSize
-         */
+         * */
         /**
-         * Proceed function to call original (wrapped) function.
          *
-         * @callback Highcharts.WrapProceedFunction
+         * @param {Highcharts.HTMLDOMElement|Highcharts.SVGElement} elem
+         *        The element to animate.
          *
-         * @param {*} [arg1]
-         *        Optional argument. Without any arguments defaults to first argument of
-         *        the wrapping function.
+         * @param {Partial<Highcharts.AnimationOptionsObject>} options
+         *        Animation options.
          *
-         * @param {*} [arg2]
-         *        Optional argument. Without any arguments defaults to second argument
-         *        of the wrapping function.
+         * @param {string} prop
+         *        The single attribute or CSS property to animate.
+         */
+        function Fx(elem, options, prop) {
+          this.pos = NaN;
+          this.options = options;
+          this.elem = elem;
+          this.prop = prop;
+        }
+        /* *
          *
-         * @param {*} [arg3]
-         *        Optional argument. Without any arguments defaults to third argument of
-         *        the wrapping function.
+         *  Functions
          *
-         * @return {*}
-         *         Return value of the original function.
-         */
+         * */
         /**
-         * The Highcharts object is the placeholder for all other members, and various
-         * utility functions. The most important member of the namespace would be the
-         * chart constructor.
+         * Set the current step of a path definition on SVGElement.
          *
-         * @example
-         * var chart = Highcharts.chart('container', { ... });
+         * @function Highcharts.Fx#dSetter
          *
-         * @namespace Highcharts
+         * @return {void}
          */
-        H.timers = [];
-        var charts = H.charts,
-            doc = H.doc,
-            win = H.win;
+        Fx.prototype.dSetter = function () {
+          var paths = this.paths,
+            start = paths && paths[0],
+            end = paths && paths[1],
+            path = [],
+            now = this.now || 0;
+          // Land on the final path without adjustment points appended in the ends
+          if (now === 1 || !start || !end) {
+            path = this.toD || [];
+          } else if (start.length === end.length && now < 1) {
+            for (var i = 0; i < end.length; i++) {
+              // Tween between the start segment and the end segment. Start
+              // with a copy of the end segment and tween the appropriate
+              // numerics
+              var startSeg = start[i];
+              var endSeg = end[i];
+              var tweenSeg = [];
+              for (var j = 0; j < endSeg.length; j++) {
+                var startItem = startSeg[j];
+                var endItem = endSeg[j];
+                // Tween numbers
+                if (
+                  typeof startItem === "number" &&
+                  typeof endItem === "number" &&
+                  // Arc boolean flags
+                  !(endSeg[0] === "A" && (j === 4 || j === 5))
+                ) {
+                  tweenSeg[j] = startItem + now * (endItem - startItem);
+                  // Strings, take directly from the end segment
+                } else {
+                  tweenSeg[j] = endItem;
+                }
+              }
+              path.push(tweenSeg);
+            }
+            // If animation is finished or length not matching, land on right value
+          } else {
+            path = end;
+          }
+          this.elem.attr("d", path, void 0, true);
+        };
         /**
-         * Provide error messages for debugging, with links to online explanation. This
-         * function can be overridden to provide custom error handling.
+         * Update the element with the current animation step.
          *
-         * @sample highcharts/chart/highcharts-error/
-         *         Custom error handler
+         * @function Highcharts.Fx#update
          *
-         * @function Highcharts.error
+         * @return {void}
+         */
+        Fx.prototype.update = function () {
+          var elem = this.elem,
+            prop = this.prop, // if destroyed, it is null
+            now = this.now,
+            step = this.options.step;
+          // Animation setter defined from outside
+          if (this[prop + "Setter"]) {
+            this[prop + "Setter"]();
+            // Other animations on SVGElement
+          } else if (elem.attr) {
+            if (elem.element) {
+              elem.attr(prop, now, null, true);
+            }
+            // HTML styles, raw HTML content like container size
+          } else {
+            elem.style[prop] = now + this.unit;
+          }
+          if (step) {
+            step.call(elem, now, this);
+          }
+        };
+        /**
+         * Run an animation.
          *
-         * @param {number|string} code
-         *        The error code. See
-         *        [errors.xml](https://github.com/highcharts/highcharts/blob/master/errors/errors.xml)
-         *        for available codes. If it is a string, the error message is printed
-         *        directly in the console.
+         * @function Highcharts.Fx#run
          *
-         * @param {boolean} [stop=false]
-         *        Whether to throw an error or just log a warning in the console.
+         * @param {number} from
+         *        The current value, value to start from.
          *
-         * @param {Highcharts.Chart} [chart]
-         *        Reference to the chart that causes the error. Used in 'debugger'
-         *        module to display errors directly on the chart.
-         *        Important note: This argument is undefined for errors that lack
-         *        access to the Chart instance.
+         * @param {number} to
+         *        The end value, value to land on.
          *
-         * @param {Highcharts.Dictionary<string>} [params]
-         *        Additional parameters for the generated message.
+         * @param {string} unit
+         *        The property unit, for example `px`.
          *
          * @return {void}
          */
-        function error(code, stop, chart, params) {
-            var severity = stop ? 'Highcharts error' : 'Highcharts warning';
-            if (code === 32) {
-                code = severity + ": Deprecated member";
-            }
-            var isCode = isNumber(code),
-                message = isCode ?
-                    severity + " #" + code + ": www.highcharts.com/errors/" + code + "/" :
-                    code.toString(),
-                defaultHandler = function () {
-                    if (stop) {
-                        throw new Error(message);
-                }
-                // else ...
-                if (win.console &&
-                    error.messages.indexOf(message) === -1 // prevent console flooting
-                ) {
-                    console.log(message); // eslint-disable-line no-console
-                }
-            };
-            if (typeof params !== 'undefined') {
-                var additionalMessages_1 = '';
-                if (isCode) {
-                    message += '?';
-                }
-                objectEach(params, function (value, key) {
-                    additionalMessages_1 += "\n - " + key + ": " + value;
-                    if (isCode) {
-                        message += encodeURI(key) + '=' + encodeURI(value);
-                    }
-                });
-                message += additionalMessages_1;
-            }
-            if (chart) {
-                fireEvent(chart, 'displayError', { code: code, message: message, params: params }, defaultHandler);
+        Fx.prototype.run = function (from, to, unit) {
+          var self = this,
+            options = self.options,
+            timer = function (gotoEnd) {
+              return timer.stopped ? false : self.step(gotoEnd);
+            },
+            requestAnimationFrame =
+              win.requestAnimationFrame ||
+              function (step) {
+                setTimeout(step, 13);
+              },
+            step = function () {
+              for (var i = 0; i < H.timers.length; i++) {
+                if (!H.timers[i]()) {
+                  H.timers.splice(i--, 1);
+                }
+              }
+              if (H.timers.length) {
+                requestAnimationFrame(step);
+              }
+            };
+          if (from === to && !this.elem["forceAnimate:" + this.prop]) {
+            delete options.curAnim[this.prop];
+            if (options.complete && Object.keys(options.curAnim).length === 0) {
+              options.complete.call(this.elem);
             }
-            else {
-                defaultHandler();
+          } else {
+            // #7166
+            this.startTime = +new Date();
+            this.start = from;
+            this.end = to;
+            this.unit = unit;
+            this.now = this.start;
+            this.pos = 0;
+            timer.elem = this.elem;
+            timer.prop = this.prop;
+            if (timer() && H.timers.push(timer) === 1) {
+              requestAnimationFrame(step);
             }
-            error.messages.push(message);
-        }
-        (function (error) {
-            error.messages = [];
-        })(error || (error = {}));
-        H.error = error;
-        /* eslint-disable valid-jsdoc */
+          }
+        };
         /**
-         * Utility function to deep merge two or more objects and return a third object.
-         * If the first argument is true, the contents of the second object is copied
-         * into the first object. The merge function can also be used with a single
-         * object argument to create a deep copy of an object.
+         * Run a single step in the animation.
          *
-         * @function Highcharts.merge<T>
+         * @function Highcharts.Fx#step
          *
-         * @param {boolean} extend
-         *        Whether to extend the left-side object (a) or return a whole new
-         *        object.
+         * @param {boolean} [gotoEnd]
+         *        Whether to go to the endpoint of the animation after abort.
          *
-         * @param {T|undefined} a
-         *        The first object to extend. When only this is given, the function
-         *        returns a deep copy.
-         *
-         * @param {...Array<object|undefined>} [n]
-         *        An object to merge into the previous one.
-         *
-         * @return {T}
-         *         The merged object. If the first argument is true, the return is the
-         *         same as the second argument.
-         */ /**
-        * Utility function to deep merge two or more objects and return a third object.
-        * The merge function can also be used with a single object argument to create a
-        * deep copy of an object.
-        *
-        * @function Highcharts.merge<T>
-        *
-        * @param {T|undefined} a
-        *        The first object to extend. When only this is given, the function
-        *        returns a deep copy.
-        *
-        * @param {...Array<object|undefined>} [n]
-        *        An object to merge into the previous one.
-        *
-        * @return {T}
-        *         The merged object. If the first argument is true, the return is the
-        *         same as the second argument.
-        */
-        function merge() {
-            /* eslint-enable valid-jsdoc */
-            var i,
-                args = arguments,
-                len,
-                ret = {},
-                doCopy = function (copy,
-                original) {
-                    // An object is replacing a primitive
-                    if (typeof copy !== 'object') {
-                        copy = {};
-                }
-                objectEach(original, function (value, key) {
-                    // Copy the contents of objects, but not arrays or DOM nodes
-                    if (isObject(value, true) &&
-                        !isClass(value) &&
-                        !isDOMElement(value)) {
-                        copy[key] = doCopy(copy[key] || {}, value);
-                        // Primitives and arrays are copied over directly
-                    }
-                    else {
-                        copy[key] = original[key];
-                    }
-                });
-                return copy;
-            };
-            // If first argument is true, copy into the existing object. Used in
-            // setOptions.
-            if (args[0] === true) {
-                ret = args[1];
-                args = Array.prototype.slice.call(args, 2);
-            }
-            // For each argument, extend the return
-            len = args.length;
-            for (i = 0; i < len; i++) {
-                ret = doCopy(ret, args[i]);
+         * @return {boolean}
+         *         Returns `true` if animation continues.
+         */
+        Fx.prototype.step = function (gotoEnd) {
+          var t = +new Date(),
+            ret,
+            done,
+            options = this.options,
+            elem = this.elem,
+            complete = options.complete,
+            duration = options.duration,
+            curAnim = options.curAnim;
+          if (elem.attr && !elem.element) {
+            // #2616, element is destroyed
+            ret = false;
+          } else if (gotoEnd || t >= duration + this.startTime) {
+            this.now = this.end;
+            this.pos = 1;
+            this.update();
+            curAnim[this.prop] = true;
+            done = true;
+            objectEach(curAnim, function (val) {
+              if (val !== true) {
+                done = false;
+              }
+            });
+            if (done && complete) {
+              complete.call(elem);
             }
-            return ret;
-        }
-        H.merge = merge;
+            ret = false;
+          } else {
+            this.pos = options.easing((t - this.startTime) / duration);
+            this.now = this.start + (this.end - this.start) * this.pos;
+            this.update();
+            ret = true;
+          }
+          return ret;
+        };
         /**
-         * Constrain a value to within a lower and upper threshold.
+         * Prepare start and end values so that the path can be animated one to one.
          *
-         * @private
-         * @param {number} value The initial value
-         * @param {number} min The lower threshold
-         * @param {number} max The upper threshold
-         * @return {number} Returns a number value within min and max.
-         */
-        function clamp(value, min, max) {
-            return value > min ? value < max ? value : max : min;
-        }
-        /**
-         * Shortcut for parseInt
+         * @function Highcharts.Fx#initPath
          *
-         * @private
-         * @function Highcharts.pInt
+         * @param {Highcharts.SVGElement} elem
+         *        The SVGElement item.
          *
-         * @param {*} s
-         *        any
+         * @param {Highcharts.SVGPathArray|undefined} fromD
+         *        Starting path definition.
          *
-         * @param {number} [mag]
-         *        Magnitude
+         * @param {Highcharts.SVGPathArray} toD
+         *        Ending path definition.
          *
-         * @return {number}
-         *         number
+         * @return {Array<Highcharts.SVGPathArray,Highcharts.SVGPathArray>}
+         *         An array containing start and end paths in array form so that
+         *         they can be animated in parallel.
          */
-        var pInt = H.pInt = function pInt(s,
-            mag) {
-                return parseInt(s,
-            mag || 10);
+        Fx.prototype.initPath = function (elem, fromD, toD) {
+          var shift,
+            startX = elem.startX,
+            endX = elem.endX,
+            fullLength,
+            i,
+            start = fromD && fromD.slice(), // copy
+            end = toD.slice(), // copy
+            isArea = elem.isArea,
+            positionFactor = isArea ? 2 : 1,
+            reverse;
+          if (!start) {
+            return [end, end];
+          }
+          /**
+           * If shifting points, prepend a dummy point to the end path.
+           * @private
+           * @param {Highcharts.SVGPathArray} arr - array
+           * @param {Highcharts.SVGPathArray} other - array
+           * @return {void}
+           */
+          function prepend(arr, other) {
+            while (arr.length < fullLength) {
+              // Move to, line to or curve to?
+              var moveSegment = arr[0],
+                otherSegment = other[fullLength - arr.length];
+              if (otherSegment && moveSegment[0] === "M") {
+                if (otherSegment[0] === "C") {
+                  arr[0] = [
+                    "C",
+                    moveSegment[1],
+                    moveSegment[2],
+                    moveSegment[1],
+                    moveSegment[2],
+                    moveSegment[1],
+                    moveSegment[2],
+                  ];
+                } else {
+                  arr[0] = ["L", moveSegment[1], moveSegment[2]];
+                }
+              }
+              // Prepend a copy of the first point
+              arr.unshift(moveSegment);
+              // For areas, the bottom path goes back again to the left, so we
+              // need to append a copy of the last point.
+              if (isArea) {
+                arr.push(arr[arr.length - 1]);
+              }
+            }
+          }
+          /**
+           * Copy and append last point until the length matches the end length.
+           * @private
+           * @param {Highcharts.SVGPathArray} arr - array
+           * @param {Highcharts.SVGPathArray} other - array
+           * @return {void}
+           */
+          function append(arr, other) {
+            while (arr.length < fullLength) {
+              // Pull out the slice that is going to be appended or inserted.
+              // In a line graph, the positionFactor is 1, and the last point
+              // is sliced out. In an area graph, the positionFactor is 2,
+              // causing the middle two points to be sliced out, since an area
+              // path starts at left, follows the upper path then turns and
+              // follows the bottom back.
+              var segmentToAdd = arr[arr.length / positionFactor - 1].slice();
+              // Disable the first control point of curve segments
+              if (segmentToAdd[0] === "C") {
+                segmentToAdd[1] = segmentToAdd[5];
+                segmentToAdd[2] = segmentToAdd[6];
+              }
+              if (!isArea) {
+                arr.push(segmentToAdd);
+              } else {
+                var lowerSegmentToAdd =
+                  arr[arr.length / positionFactor].slice();
+                arr.splice(arr.length / 2, 0, segmentToAdd, lowerSegmentToAdd);
+              }
+            }
+          }
+          // For sideways animation, find out how much we need to shift to get the
+          // start path Xs to match the end path Xs.
+          if (startX && endX) {
+            for (i = 0; i < startX.length; i++) {
+              // Moving left, new points coming in on right
+              if (startX[i] === endX[0]) {
+                shift = i;
+                break;
+                // Moving right
+              } else if (startX[0] === endX[endX.length - startX.length + i]) {
+                shift = i;
+                reverse = true;
+                break;
+                // Fixed from the right side, "scaling" left
+              } else if (
+                startX[startX.length - 1] ===
+                endX[endX.length - startX.length + i]
+              ) {
+                shift = startX.length - i;
+                break;
+              }
+            }
+            if (typeof shift === "undefined") {
+              start = [];
+            }
+          }
+          if (start.length && isNumber(shift)) {
+            // The common target length for the start and end array, where both
+            // arrays are padded in opposite ends
+            fullLength = end.length + shift * positionFactor;
+            if (!reverse) {
+              prepend(end, start);
+              append(start, end);
+            } else {
+              prepend(start, end);
+              append(end, start);
+            }
+          }
+          return [start, end];
         };
         /**
-         * Utility function to check for string type.
+         * Handle animation of the color attributes directly.
          *
-         * @function Highcharts.isString
+         * @function Highcharts.Fx#fillSetter
          *
-         * @param {*} s
-         *        The item to check.
-         *
-         * @return {boolean}
-         *         True if the argument is a string.
+         * @return {void}
          */
-        var isString = H.isString = function isString(s) {
-                return typeof s === 'string';
+        Fx.prototype.fillSetter = function () {
+          Fx.prototype.strokeSetter.apply(this, arguments);
         };
         /**
-         * Utility function to check if an item is an array.
-         *
-         * @function Highcharts.isArray
+         * Handle animation of the color attributes directly.
          *
-         * @param {*} obj
-         *        The item to check.
+         * @function Highcharts.Fx#strokeSetter
          *
-         * @return {boolean}
-         *         True if the argument is an array.
+         * @return {void}
          */
-        var isArray = H.isArray = function isArray(obj) {
-                var str = Object.prototype.toString.call(obj);
-            return str === '[object Array]' || str === '[object Array Iterator]';
+        Fx.prototype.strokeSetter = function () {
+          this.elem.attr(
+            this.prop,
+            H.color(this.start).tweenTo(H.color(this.end), this.pos),
+            null,
+            true
+          );
         };
-        /**
-         * Utility function to check if an item is of type object.
-         *
-         * @function Highcharts.isObject
-         *
-         * @param {*} obj
-         *        The item to check.
+        return Fx;
+      })();
+      H.Fx = Fx;
+
+      return Fx;
+    }
+  );
+  _registerModule(
+    _modules,
+    "Core/Animation/AnimationUtilities.js",
+    [
+      _modules["Core/Animation/Fx.js"],
+      _modules["Core/Globals.js"],
+      _modules["Core/Utilities.js"],
+    ],
+    function (Fx, H, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      var defined = U.defined,
+        getStyle = U.getStyle,
+        isArray = U.isArray,
+        isNumber = U.isNumber,
+        isObject = U.isObject,
+        merge = U.merge,
+        objectEach = U.objectEach,
+        pick = U.pick;
+      /**
+       * Set the global animation to either a given value, or fall back to the given
+       * chart's animation option.
+       *
+       * @function Highcharts.setAnimation
+       *
+       * @param {boolean|Partial<Highcharts.AnimationOptionsObject>|undefined} animation
+       *        The animation object.
+       *
+       * @param {Highcharts.Chart} chart
+       *        The chart instance.
+       *
+       * @todo
+       * This function always relates to a chart, and sets a property on the renderer,
+       * so it should be moved to the SVGRenderer.
+       */
+      var setAnimation = (H.setAnimation = function setAnimation(
+        animation,
+        chart
+      ) {
+        chart.renderer.globalAnimation = pick(
+          animation,
+          chart.options.chart.animation,
+          true
+        );
+      });
+      /**
+       * Get the animation in object form, where a disabled animation is always
+       * returned as `{ duration: 0 }`.
+       *
+       * @function Highcharts.animObject
+       *
+       * @param {boolean|Highcharts.AnimationOptionsObject} [animation=0]
+       *        An animation setting. Can be an object with duration, complete and
+       *        easing properties, or a boolean to enable or disable.
+       *
+       * @return {Highcharts.AnimationOptionsObject}
+       *         An object with at least a duration property.
+       */
+      var animObject = (H.animObject = function animObject(animation) {
+        return isObject(animation)
+          ? H.merge({ duration: 500, defer: 0 }, animation)
+          : { duration: animation ? 500 : 0, defer: 0 };
+      });
+      /**
+       * Get the defer as a number value from series animation options.
+       *
+       * @function Highcharts.getDeferredAnimation
+       *
+       * @param {Highcharts.Chart} chart
+       *        The chart instance.
+       *
+       * @param {boolean|Highcharts.AnimationOptionsObject} animation
+       *        An animation setting. Can be an object with duration, complete and
+       *        easing properties, or a boolean to enable or disable.
+       *
+       * @param {Highcharts.Series} [series]
+       *        Series to defer animation.
+       *
+       * @return {number}
+       *        The numeric value.
+       */
+      var getDeferredAnimation = (H.getDeferredAnimation = function (
+        chart,
+        animation,
+        series
+      ) {
+        var labelAnimation = animObject(animation);
+        var s = series ? [series] : chart.series;
+        var defer = 0;
+        var duration = 0;
+        s.forEach(function (series) {
+          var seriesAnim = animObject(series.options.animation);
+          defer =
+            animation && defined(animation.defer)
+              ? labelAnimation.defer
+              : Math.max(defer, seriesAnim.duration + seriesAnim.defer);
+          duration = Math.min(labelAnimation.duration, seriesAnim.duration);
+        });
+        // Disable defer for exporting
+        if (chart.renderer.forExport) {
+          defer = 0;
+        }
+        var anim = {
+          defer: Math.max(0, defer - duration),
+          duration: Math.min(defer, duration),
+        };
+        return anim;
+      });
+      /**
+       * The global animate method, which uses Fx to create individual animators.
+       *
+       * @function Highcharts.animate
+       *
+       * @param {Highcharts.HTMLDOMElement|Highcharts.SVGElement} el
+       *        The element to animate.
+       *
+       * @param {Highcharts.CSSObject|Highcharts.SVGAttributes} params
+       *        An object containing key-value pairs of the properties to animate.
+       *        Supports numeric as pixel-based CSS properties for HTML objects and
+       *        attributes for SVGElements.
+       *
+       * @param {Partial<Highcharts.AnimationOptionsObject>} [opt]
+       *        Animation options.
+       *
+       * @return {void}
+       */
+      var animate = (H.animate = function (el, params, opt) {
+        var start,
+          unit = "",
+          end,
+          fx,
+          args;
+        if (!isObject(opt)) {
+          // Number or undefined/null
+          args = arguments;
+          opt = {
+            duration: args[2],
+            easing: args[3],
+            complete: args[4],
+          };
+        }
+        if (!isNumber(opt.duration)) {
+          opt.duration = 400;
+        }
+        opt.easing =
+          typeof opt.easing === "function"
+            ? opt.easing
+            : Math[opt.easing] || Math.easeInOutSine;
+        opt.curAnim = merge(params);
+        objectEach(params, function (val, prop) {
+          // Stop current running animation of this property
+          stop(el, prop);
+          fx = new Fx(el, opt, prop);
+          end = null;
+          if (prop === "d" && isArray(params.d)) {
+            fx.paths = fx.initPath(el, el.pathArray, params.d);
+            fx.toD = params.d;
+            start = 0;
+            end = 1;
+          } else if (el.attr) {
+            start = el.attr(prop);
+          } else {
+            start = parseFloat(getStyle(el, prop)) || 0;
+            if (prop !== "opacity") {
+              unit = "px";
+            }
+          }
+          if (!end) {
+            end = val;
+          }
+          if (end && end.match && end.match("px")) {
+            end = end.replace(/px/g, ""); // #4351
+          }
+          fx.run(start, end, unit);
+        });
+      });
+      /**
+       * Stop running animation.
+       *
+       * @function Highcharts.stop
+       *
+       * @param {Highcharts.SVGElement} el
+       *        The SVGElement to stop animation on.
+       *
+       * @param {string} [prop]
+       *        The property to stop animating. If given, the stop method will stop a
+       *        single property from animating, while others continue.
+       *
+       * @return {void}
+       *
+       * @todo
+       * A possible extension to this would be to stop a single property, when
+       * we want to continue animating others. Then assign the prop to the timer
+       * in the Fx.run method, and check for the prop here. This would be an
+       * improvement in all cases where we stop the animation from .attr. Instead of
+       * stopping everything, we can just stop the actual attributes we're setting.
+       */
+      var stop = (H.stop = function (el, prop) {
+        var i = H.timers.length;
+        // Remove timers related to this element (#4519)
+        while (i--) {
+          if (H.timers[i].elem === el && (!prop || prop === H.timers[i].prop)) {
+            H.timers[i].stopped = true; // #4667
+          }
+        }
+      });
+      var animationExports = {
+        animate: animate,
+        animObject: animObject,
+        getDeferredAnimation: getDeferredAnimation,
+        setAnimation: setAnimation,
+        stop: stop,
+      };
+
+      return animationExports;
+    }
+  );
+  _registerModule(
+    _modules,
+    "Core/Renderer/SVG/SVGElement.js",
+    [
+      _modules["Core/Animation/AnimationUtilities.js"],
+      _modules["Core/Color/Color.js"],
+      _modules["Core/Globals.js"],
+      _modules["Core/Utilities.js"],
+    ],
+    function (A, Color, H, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      var animate = A.animate,
+        animObject = A.animObject,
+        stop = A.stop;
+      var deg2rad = H.deg2rad,
+        doc = H.doc,
+        hasTouch = H.hasTouch,
+        isFirefox = H.isFirefox,
+        noop = H.noop,
+        svg = H.svg,
+        SVG_NS = H.SVG_NS,
+        win = H.win;
+      var attr = U.attr,
+        createElement = U.createElement,
+        css = U.css,
+        defined = U.defined,
+        erase = U.erase,
+        extend = U.extend,
+        fireEvent = U.fireEvent,
+        isArray = U.isArray,
+        isFunction = U.isFunction,
+        isNumber = U.isNumber,
+        isString = U.isString,
+        merge = U.merge,
+        objectEach = U.objectEach,
+        pick = U.pick,
+        pInt = U.pInt,
+        syncTimeout = U.syncTimeout,
+        uniqueKey = U.uniqueKey;
+      /**
+       * The horizontal alignment of an element.
+       *
+       * @typedef {"center"|"left"|"right"} Highcharts.AlignValue
+       */
+      /**
+       * Options to align the element relative to the chart or another box.
+       *
+       * @interface Highcharts.AlignObject
+       */ /**
+       * Horizontal alignment. Can be one of `left`, `center` and `right`.
+       *
+       * @name Highcharts.AlignObject#align
+       * @type {Highcharts.AlignValue|undefined}
+       *
+       * @default left
+       */ /**
+       * Vertical alignment. Can be one of `top`, `middle` and `bottom`.
+       *
+       * @name Highcharts.AlignObject#verticalAlign
+       * @type {Highcharts.VerticalAlignValue|undefined}
+       *
+       * @default top
+       */ /**
+       * Horizontal pixel offset from alignment.
+       *
+       * @name Highcharts.AlignObject#x
+       * @type {number|undefined}
+       *
+       * @default 0
+       */ /**
+       * Vertical pixel offset from alignment.
+       *
+       * @name Highcharts.AlignObject#y
+       * @type {number|undefined}
+       *
+       * @default 0
+       */ /**
+       * Use the `transform` attribute with translateX and translateY custom
+       * attributes to align this elements rather than `x` and `y` attributes.
+       *
+       * @name Highcharts.AlignObject#alignByTranslate
+       * @type {boolean|undefined}
+       *
+       * @default false
+       */
+      /**
+       * Bounding box of an element.
+       *
+       * @interface Highcharts.BBoxObject
+       * @extends Highcharts.PositionObject
+       */ /**
+       * Height of the bounding box.
+       *
+       * @name Highcharts.BBoxObject#height
+       * @type {number}
+       */ /**
+       * Width of the bounding box.
+       *
+       * @name Highcharts.BBoxObject#width
+       * @type {number}
+       */ /**
+       * Horizontal position of the bounding box.
+       *
+       * @name Highcharts.BBoxObject#x
+       * @type {number}
+       */ /**
+       * Vertical position of the bounding box.
+       *
+       * @name Highcharts.BBoxObject#y
+       * @type {number}
+       */
+      /**
+       * An object of key-value pairs for SVG attributes. Attributes in Highcharts
+       * elements for the most parts correspond to SVG, but some are specific to
+       * Highcharts, like `zIndex`, `rotation`, `rotationOriginX`,
+       * `rotationOriginY`, `translateX`, `translateY`, `scaleX` and `scaleY`. SVG
+       * attributes containing a hyphen are _not_ camel-cased, they should be
+       * quoted to preserve the hyphen.
+       *
+       * @example
+       * {
+       *     'stroke': '#ff0000', // basic
+       *     'stroke-width': 2, // hyphenated
+       *     'rotation': 45 // custom
+       *     'd': ['M', 10, 10, 'L', 30, 30, 'z'] // path definition, note format
+       * }
+       *
+       * @interface Highcharts.SVGAttributes
+       */ /**
+       * @name Highcharts.SVGAttributes#[key:string]
+       * @type {*}
+       */ /**
+       * @name Highcharts.SVGAttributes#d
+       * @type {string|Highcharts.SVGPathArray|undefined}
+       */ /**
+       * @name Highcharts.SVGAttributes#fill
+       * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject|undefined}
+       */ /**
+       * @name Highcharts.SVGAttributes#inverted
+       * @type {boolean|undefined}
+       */ /**
+       * @name Highcharts.SVGAttributes#matrix
+       * @type {Array<number>|undefined}
+       */ /**
+       * @name Highcharts.SVGAttributes#rotation
+       * @type {number|undefined}
+       */ /**
+       * @name Highcharts.SVGAttributes#rotationOriginX
+       * @type {number|undefined}
+       */ /**
+       * @name Highcharts.SVGAttributes#rotationOriginY
+       * @type {number|undefined}
+       */ /**
+       * @name Highcharts.SVGAttributes#scaleX
+       * @type {number|undefined}
+       */ /**
+       * @name Highcharts.SVGAttributes#scaleY
+       * @type {number|undefined}
+       */ /**
+       * @name Highcharts.SVGAttributes#stroke
+       * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject|undefined}
+       */ /**
+       * @name Highcharts.SVGAttributes#style
+       * @type {string|Highcharts.CSSObject|undefined}
+       */ /**
+       * @name Highcharts.SVGAttributes#translateX
+       * @type {number|undefined}
+       */ /**
+       * @name Highcharts.SVGAttributes#translateY
+       * @type {number|undefined}
+       */ /**
+       * @name Highcharts.SVGAttributes#zIndex
+       * @type {number|undefined}
+       */
+      /**
+       * An SVG DOM element. The type is a reference to the regular SVGElement in the
+       * global scope.
+       *
+       * @typedef {globals.GlobalSVGElement} Highcharts.SVGDOMElement
+       *
+       * @see https://developer.mozilla.org/en-US/docs/Web/API/SVGElement
+       */
+      /**
+       * The vertical alignment of an element.
+       *
+       * @typedef {"bottom"|"middle"|"top"} Highcharts.VerticalAlignValue
+       */
+      (""); // detach doclets above
+      /* eslint-disable no-invalid-this, valid-jsdoc */
+      /**
+       * The SVGElement prototype is a JavaScript wrapper for SVG elements used in the
+       * rendering layer of Highcharts. Combined with the
+       * {@link Highcharts.SVGRenderer}
+       * object, these prototypes allow freeform annotation in the charts or even in
+       * HTML pages without instanciating a chart. The SVGElement can also wrap HTML
+       * labels, when `text` or `label` elements are created with the `useHTML`
+       * parameter.
+       *
+       * The SVGElement instances are created through factory functions on the
+       * {@link Highcharts.SVGRenderer}
+       * object, like
+       * {@link Highcharts.SVGRenderer#rect|rect},
+       * {@link Highcharts.SVGRenderer#path|path},
+       * {@link Highcharts.SVGRenderer#text|text},
+       * {@link Highcharts.SVGRenderer#label|label},
+       * {@link Highcharts.SVGRenderer#g|g}
+       * and more.
+       *
+       * @class
+       * @name Highcharts.SVGElement
+       */
+      var SVGElement = /** @class */ (function () {
+        function SVGElement() {
+          /* *
+           *
+           *  Properties
+           *
+           * */
+          this.element = void 0;
+          this.height = void 0;
+          this.opacity = 1; // Default base for animation
+          this.renderer = void 0;
+          this.SVG_NS = SVG_NS;
+          // Custom attributes used for symbols, these should be filtered out when
+          // setting SVGElement attributes (#9375).
+          this.symbolCustomAttribs = [
+            "x",
+            "y",
+            "width",
+            "height",
+            "r",
+            "start",
+            "end",
+            "innerR",
+            "anchorX",
+            "anchorY",
+            "rounded",
+          ];
+          this.width = void 0;
+        }
+        /* *
          *
-         * @param {boolean} [strict=false]
-         *        Also checks that the object is not an array.
+         *  Functions
          *
-         * @return {boolean}
-         *         True if the argument is an object.
-         */
-        function isObject(obj, strict) {
-            return (!!obj &&
-                typeof obj === 'object' &&
-                (!strict || !isArray(obj))); // eslint-disable-line @typescript-eslint/no-explicit-any
-        }
-        H.isObject = isObject;
+         * */
         /**
-         * Utility function to check if an Object is a HTML Element.
+         * Get the current value of an attribute or pseudo attribute,
+         * used mainly for animation. Called internally from
+         * the {@link Highcharts.SVGRenderer#attr} function.
          *
-         * @function Highcharts.isDOMElement
+         * @private
+         * @function Highcharts.SVGElement#_defaultGetter
          *
-         * @param {*} obj
-         *        The item to check.
+         * @param {string} key
+         *        Property key.
          *
-         * @return {boolean}
-         *         True if the argument is a HTML Element.
-         */
-        var isDOMElement = H.isDOMElement = function isDOMElement(obj) {
-                return isObject(obj) && typeof obj.nodeType === 'number';
+         * @return {number|string}
+         *         Property value.
+         */
+        SVGElement.prototype._defaultGetter = function (key) {
+          var ret = pick(
+            this[key + "Value"], // align getter
+            this[key],
+            this.element ? this.element.getAttribute(key) : null,
+            0
+          );
+          if (/^[\-0-9\.]+$/.test(ret)) {
+            // is numerical
+            ret = parseFloat(ret);
+          }
+          return ret;
         };
         /**
-         * Utility function to check if an Object is a class.
+         * @private
+         * @function Highcharts.SVGElement#_defaultSetter
+         *
+         * @param {string} value
          *
-         * @function Highcharts.isClass
+         * @param {string} key
          *
-         * @param {object|undefined} obj
-         *        The item to check.
+         * @param {Highcharts.SVGDOMElement} element
          *
-         * @return {boolean}
-         *         True if the argument is a class.
+         * @return {void}
          */
-        var isClass = H.isClass = function isClass(obj) {
-                var c = obj && obj.constructor;
-            return !!(isObject(obj, true) &&
-                !isDOMElement(obj) &&
-                (c && c.name && c.name !== 'Object'));
+        SVGElement.prototype._defaultSetter = function (value, key, element) {
+          element.setAttribute(key, value);
+        };
+        /**
+         * Add the element to the DOM. All elements must be added this way.
+         *
+         * @sample highcharts/members/renderer-g
+         *         Elements added to a group
+         *
+         * @function Highcharts.SVGElement#add
+         *
+         * @param {Highcharts.SVGElement} [parent]
+         *        The parent item to add it to. If undefined, the element is added
+         *        to the {@link Highcharts.SVGRenderer.box}.
+         *
+         * @return {Highcharts.SVGElement}
+         *         Returns the SVGElement for chaining.
+         */
+        SVGElement.prototype.add = function (parent) {
+          var renderer = this.renderer,
+            element = this.element,
+            inserted;
+          if (parent) {
+            this.parentGroup = parent;
+          }
+          // Mark as inverted
+          this.parentInverted = parent && parent.inverted;
+          // Build formatted text
+          if (
+            typeof this.textStr !== "undefined" &&
+            this.element.nodeName === "text" // Not for SVGLabel instances
+          ) {
+            renderer.buildText(this);
+          }
+          // Mark as added
+          this.added = true;
+          // If we're adding to renderer root, or other elements in the group
+          // have a z index, we need to handle it
+          if (!parent || parent.handleZ || this.zIndex) {
+            inserted = this.zIndexSetter();
+          }
+          // If zIndex is not handled, append at the end
+          if (!inserted) {
+            (parent ? parent.element : renderer.box).appendChild(element);
+          }
+          // fire an event for internal hooks
+          if (this.onAdd) {
+            this.onAdd();
+          }
+          return this;
+        };
+        /**
+         * Add a class name to an element.
+         *
+         * @function Highcharts.SVGElement#addClass
+         *
+         * @param {string} className
+         * The new class name to add.
+         *
+         * @param {boolean} [replace=false]
+         * When true, the existing class name(s) will be overwritten with the new
+         * one. When false, the new one is added.
+         *
+         * @return {Highcharts.SVGElement}
+         * Return the SVG element for chainability.
+         */
+        SVGElement.prototype.addClass = function (className, replace) {
+          var currentClassName = replace ? "" : this.attr("class") || "";
+          // Trim the string and remove duplicates
+          className = (className || "")
+            .split(/ /g)
+            .reduce(
+              function (newClassName, name) {
+                if (currentClassName.indexOf(name) === -1) {
+                  newClassName.push(name);
+                }
+                return newClassName;
+              },
+              currentClassName ? [currentClassName] : []
+            )
+            .join(" ");
+          if (className !== currentClassName) {
+            this.attr("class", className);
+          }
+          return this;
         };
         /**
-         * Utility function to check if an item is a number and it is finite (not NaN,
-         * Infinity or -Infinity).
+         * This method is executed in the end of `attr()`, after setting all
+         * attributes in the hash. In can be used to efficiently consolidate
+         * multiple attributes in one SVG property -- e.g., translate, rotate and
+         * scale are merged in one "transform" attribute in the SVG node.
          *
-         * @function Highcharts.isNumber
+         * @private
+         * @function Highcharts.SVGElement#afterSetters
+         */
+        SVGElement.prototype.afterSetters = function () {
+          // Update transform. Do this outside the loop to prevent redundant
+          // updating for batch setting of attributes.
+          if (this.doTransform) {
+            this.updateTransform();
+            this.doTransform = false;
+          }
+        };
+        /**
+         * Align the element relative to the chart or another box.
          *
-         * @param {*} n
-         *        The item to check.
+         * @function Highcharts.SVGElement#align
          *
-         * @return {boolean}
-         *         True if the item is a finite number
-         */
-        var isNumber = H.isNumber = function isNumber(n) {
-                return typeof n === 'number' && !isNaN(n) && n < Infinity && n > -Infinity;
+         * @param {Highcharts.AlignObject} [alignOptions]
+         *        The alignment options. The function can be called without this
+         *        parameter in order to re-align an element after the box has been
+         *        updated.
+         *
+         * @param {boolean} [alignByTranslate]
+         *        Align element by translation.
+         *
+         * @param {string|Highcharts.BBoxObject} [box]
+         *        The box to align to, needs a width and height. When the box is a
+         *        string, it refers to an object in the Renderer. For example, when
+         *        box is `spacingBox`, it refers to `Renderer.spacingBox` which
+         *        holds `width`, `height`, `x` and `y` properties.
+         *
+         * @return {Highcharts.SVGElement} Returns the SVGElement for chaining.
+         */
+        SVGElement.prototype.align = function (
+          alignOptions,
+          alignByTranslate,
+          box
+        ) {
+          var align,
+            vAlign,
+            x,
+            y,
+            attribs = {},
+            alignTo,
+            renderer = this.renderer,
+            alignedObjects = renderer.alignedObjects,
+            alignFactor,
+            vAlignFactor;
+          // First call on instanciate
+          if (alignOptions) {
+            this.alignOptions = alignOptions;
+            this.alignByTranslate = alignByTranslate;
+            if (!box || isString(box)) {
+              this.alignTo = alignTo = box || "renderer";
+              // prevent duplicates, like legendGroup after resize
+              erase(alignedObjects, this);
+              alignedObjects.push(this);
+              box = void 0; // reassign it below
+            }
+            // When called on resize, no arguments are supplied
+          } else {
+            alignOptions = this.alignOptions;
+            alignByTranslate = this.alignByTranslate;
+            alignTo = this.alignTo;
+          }
+          box = pick(box, renderer[alignTo], renderer);
+          // Assign variables
+          align = alignOptions.align;
+          vAlign = alignOptions.verticalAlign;
+          // default: left align
+          x = (box.x || 0) + (alignOptions.x || 0);
+          // default: top align
+          y = (box.y || 0) + (alignOptions.y || 0);
+          // Align
+          if (align === "right") {
+            alignFactor = 1;
+          } else if (align === "center") {
+            alignFactor = 2;
+          }
+          if (alignFactor) {
+            x += (box.width - (alignOptions.width || 0)) / alignFactor;
+          }
+          attribs[alignByTranslate ? "translateX" : "x"] = Math.round(x);
+          // Vertical align
+          if (vAlign === "bottom") {
+            vAlignFactor = 1;
+          } else if (vAlign === "middle") {
+            vAlignFactor = 2;
+          }
+          if (vAlignFactor) {
+            y += (box.height - (alignOptions.height || 0)) / vAlignFactor;
+          }
+          attribs[alignByTranslate ? "translateY" : "y"] = Math.round(y);
+          // Animate only if already placed
+          this[this.placed ? "animate" : "attr"](attribs);
+          this.placed = true;
+          this.alignAttr = attribs;
+          return this;
+        };
+        /**
+         * @private
+         * @function Highcharts.SVGElement#alignSetter
+         * @param {"left"|"center"|"right"} value
+         */
+        SVGElement.prototype.alignSetter = function (value) {
+          var convert = {
+            left: "start",
+            center: "middle",
+            right: "end",
+          };
+          if (convert[value]) {
+            this.alignValue = value;
+            this.element.setAttribute("text-anchor", convert[value]);
+          }
         };
         /**
-         * Remove the last occurence of an item from an array.
+         * Animate to given attributes or CSS properties.
          *
-         * @function Highcharts.erase
+         * @sample highcharts/members/element-on/
+         *         Setting some attributes by animation
          *
-         * @param {Array<*>} arr
-         *        The array.
+         * @function Highcharts.SVGElement#animate
          *
-         * @param {*} item
-         *        The item to remove.
+         * @param {Highcharts.SVGAttributes} params
+         *        SVG attributes or CSS to animate.
          *
-         * @return {void}
-         */
-        var erase = H.erase = function erase(arr,
-            item) {
-                var i = arr.length;
-            while (i--) {
-                if (arr[i] === item) {
-                    arr.splice(i, 1);
-                    break;
-                }
+         * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [options]
+         *        Animation options.
+         *
+         * @param {Function} [complete]
+         *        Function to perform at the end of animation.
+         *
+         * @return {Highcharts.SVGElement}
+         *         Returns the SVGElement for chaining.
+         */
+        SVGElement.prototype.animate = function (params, options, complete) {
+          var _this = this;
+          var animOptions = animObject(
+              pick(options, this.renderer.globalAnimation, true)
+            ),
+            deferTime = animOptions.defer;
+          // When the page is hidden save resources in the background by not
+          // running animation at all (#9749).
+          if (pick(doc.hidden, doc.msHidden, doc.webkitHidden, false)) {
+            animOptions.duration = 0;
+          }
+          if (animOptions.duration !== 0) {
+            // allows using a callback with the global animation without
+            // overwriting it
+            if (complete) {
+              animOptions.complete = complete;
             }
+            // If defer option is defined delay the animation #12901
+            syncTimeout(function () {
+              if (_this.element) {
+                animate(_this, params, animOptions);
+              }
+            }, deferTime);
+          } else {
+            this.attr(params, void 0, complete);
+            // Call the end step synchronously
+            objectEach(
+              params,
+              function (val, prop) {
+                if (animOptions.step) {
+                  animOptions.step.call(this, val, { prop: prop, pos: 1 });
+                }
+              },
+              this
+            );
+          }
+          return this;
         };
         /**
-         * Check if an object is null or undefined.
-         *
-         * @function Highcharts.defined
+         * Apply a text outline through a custom CSS property, by copying the text
+         * element and apply stroke to the copy. Used internally. Contrast checks at
+         * [example](https://jsfiddle.net/highcharts/43soe9m1/2/).
          *
-         * @param {*} obj
-         *        The object to check.
+         * @example
+         * // Specific color
+         * text.css({
+         *    textOutline: '1px black'
+         * });
+         * // Automatic contrast
+         * text.css({
+         *    color: '#000000', // black text
+         *    textOutline: '1px contrast' // => white outline
+         * });
          *
-         * @return {boolean}
-         *         False if the object is null or undefined, otherwise true.
-         */
-        var defined = H.defined = function defined(obj) {
-                return typeof obj !== 'undefined' && obj !== null;
+         * @private
+         * @function Highcharts.SVGElement#applyTextOutline
+         *
+         * @param {string} textOutline
+         *        A custom CSS `text-outline` setting, defined by `width color`.
+         */
+        SVGElement.prototype.applyTextOutline = function (textOutline) {
+          var elem = this.element,
+            tspans,
+            hasContrast = textOutline.indexOf("contrast") !== -1,
+            styles = {},
+            color,
+            strokeWidth,
+            firstRealChild;
+          // When the text shadow is set to contrast, use dark stroke for light
+          // text and vice versa.
+          if (hasContrast) {
+            styles.textOutline = textOutline = textOutline.replace(
+              /contrast/g,
+              this.renderer.getContrast(elem.style.fill)
+            );
+          }
+          // Extract the stroke width and color
+          textOutline = textOutline.split(" ");
+          color = textOutline[textOutline.length - 1];
+          strokeWidth = textOutline[0];
+          if (strokeWidth && strokeWidth !== "none" && H.svg) {
+            this.fakeTS = true; // Fake text shadow
+            tspans = [].slice.call(elem.getElementsByTagName("tspan"));
+            // In order to get the right y position of the clone,
+            // copy over the y setter
+            this.ySetter = this.xSetter;
+            // Since the stroke is applied on center of the actual outline, we
+            // need to double it to get the correct stroke-width outside the
+            // glyphs.
+            strokeWidth = strokeWidth.replace(
+              /(^[\d\.]+)(.*?)$/g,
+              function (match, digit, unit) {
+                return 2 * digit + unit;
+              }
+            );
+            // Remove shadows from previous runs.
+            this.removeTextOutline(tspans);
+            // Check if the element contains RTL characters.
+            // Comparing against Hebrew and Arabic characters,
+            // excluding Arabic digits. Source:
+            // https://www.unicode.org/Public/UNIDATA/extracted/DerivedBidiClass.txt
+            var isRTL_1 = elem.textContent
+              ? /^[\u0591-\u065F\u066A-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC]/.test(
+                  elem.textContent
+                )
+              : false;
+            // For each of the tspans, create a stroked copy behind it.
+            firstRealChild = elem.firstChild;
+            tspans.forEach(function (tspan, y) {
+              var clone;
+              // Let the first line start at the correct X position
+              if (y === 0) {
+                tspan.setAttribute("x", elem.getAttribute("x"));
+                y = elem.getAttribute("y");
+                tspan.setAttribute("y", y || 0);
+                if (y === null) {
+                  elem.setAttribute("y", 0);
+                }
+              }
+              // Create the clone and apply outline properties.
+              // For RTL elements apply outline properties for orginal element
+              // to prevent outline from overlapping the text.
+              // For RTL in Firefox keep the orginal order (#10162).
+              clone = tspan.cloneNode(true);
+              attr(isRTL_1 && !isFirefox ? tspan : clone, {
+                class: "highcharts-text-outline",
+                fill: color,
+                stroke: color,
+                "stroke-width": strokeWidth,
+                "stroke-linejoin": "round",
+              });
+              elem.insertBefore(clone, firstRealChild);
+            });
+            // Create a whitespace between tspan and clone,
+            // to fix the display of Arabic characters in Firefox.
+            if (isRTL_1 && isFirefox && tspans[0]) {
+              var whitespace = tspans[0].cloneNode(true);
+              whitespace.textContent = " ";
+              elem.insertBefore(whitespace, firstRealChild);
+            }
+          }
         };
         /**
-         * Set or get an attribute or an object of attributes. To use as a setter, pass
-         * a key and a value, or let the second argument be a collection of keys and
-         * values. To use as a getter, pass only a string as the second argument.
+         * @function Highcharts.SVGElement#attr
+         * @param {string} key
+         * @return {number|string}
+         */ /**
+         * Apply native and custom attributes to the SVG elements.
          *
-         * @function Highcharts.attr
+         * In order to set the rotation center for rotation, set x and y to 0 and
+         * use `translateX` and `translateY` attributes to position the element
+         * instead.
          *
-         * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} elem
-         *        The DOM element to receive the attribute(s).
+         * Attributes frequently used in Highcharts are `fill`, `stroke`,
+         * `stroke-width`.
          *
-         * @param {string|Highcharts.HTMLAttributes|Highcharts.SVGAttributes} [prop]
-         *        The property or an object of key-value pairs.
+         * @sample highcharts/members/renderer-rect/
+         *         Setting some attributes
          *
-         * @param {number|string} [value]
-         *        The value if a single property is set.
+         * @example
+         * // Set multiple attributes
+         * element.attr({
+         *     stroke: 'red',
+         *     fill: 'blue',
+         *     x: 10,
+         *     y: 10
+         * });
          *
-         * @return {string|null|undefined}
-         *         When used as a getter, return the value.
-         */
-        function attr(elem, prop, value) {
-            var ret;
-            // if the prop is a string
-            if (isString(prop)) {
-                // set the value
-                if (defined(value)) {
-                    elem.setAttribute(prop, value);
-                    // get the value
-                }
-                else if (elem && elem.getAttribute) {
-                    ret = elem.getAttribute(prop);
-                    // IE7 and below cannot get class through getAttribute (#7850)
-                    if (!ret && prop === 'class') {
-                        ret = elem.getAttribute(prop + 'Name');
-                    }
+         * // Set a single attribute
+         * element.attr('stroke', 'red');
+         *
+         * // Get an attribute
+         * element.attr('stroke'); // => 'red'
+         *
+         * @function Highcharts.SVGElement#attr
+         *
+         * @param {string|Highcharts.SVGAttributes} [hash]
+         *        The native and custom SVG attributes.
+         *
+         * @param {number|string|Highcharts.SVGPathArray} [val]
+         *        If the type of the first argument is `string`, the second can be a
+         *        value, which will serve as a single attribute setter. If the first
+         *        argument is a string and the second is undefined, the function
+         *        serves as a getter and the current value of the property is
+         *        returned.
+         *
+         * @param {Function} [complete]
+         *        A callback function to execute after setting the attributes. This
+         *        makes the function compliant and interchangeable with the
+         *        {@link SVGElement#animate} function.
+         *
+         * @param {boolean} [continueAnimation=true]
+         *        Used internally when `.attr` is called as part of an animation
+         *        step. Otherwise, calling `.attr` for an attribute will stop
+         *        animation for that attribute.
+         *
+         * @return {Highcharts.SVGElement}
+         *         If used as a setter, it returns the current
+         *         {@link Highcharts.SVGElement} so the calls can be chained. If
+         *         used as a getter, the current value of the attribute is returned.
+         */
+        SVGElement.prototype.attr = function (
+          hash,
+          val,
+          complete,
+          continueAnimation
+        ) {
+          var key,
+            element = this.element,
+            hasSetSymbolSize,
+            ret = this,
+            skipAttr,
+            setter,
+            symbolCustomAttribs = this.symbolCustomAttribs;
+          // single key-value pair
+          if (typeof hash === "string" && typeof val !== "undefined") {
+            key = hash;
+            hash = {};
+            hash[key] = val;
+          }
+          // used as a getter: first argument is a string, second is undefined
+          if (typeof hash === "string") {
+            ret = (this[hash + "Getter"] || this._defaultGetter).call(
+              this,
+              hash,
+              element
+            );
+            // setter
+          } else {
+            objectEach(
+              hash,
+              function eachAttribute(val, key) {
+                skipAttr = false;
+                // Unless .attr is from the animator update, stop current
+                // running animation of this property
+                if (!continueAnimation) {
+                  stop(this, key);
+                }
+                // Special handling of symbol attributes
+                if (
+                  this.symbolName &&
+                  symbolCustomAttribs.indexOf(key) !== -1
+                ) {
+                  if (!hasSetSymbolSize) {
+                    this.symbolAttr(hash);
+                    hasSetSymbolSize = true;
+                  }
+                  skipAttr = true;
+                }
+                if (this.rotation && (key === "x" || key === "y")) {
+                  this.doTransform = true;
+                }
+                if (!skipAttr) {
+                  setter = this[key + "Setter"] || this._defaultSetter;
+                  setter.call(this, val, key, element);
+                  // Let the shadow follow the main element
+                  if (
+                    !this.styledMode &&
+                    this.shadows &&
+                    /^(width|height|visibility|x|y|d|transform|cx|cy|r)$/.test(
+                      key
+                    )
+                  ) {
+                    this.updateShadows(key, val, setter);
+                  }
                 }
-                // else if prop is defined, it is a hash of key/value pairs
-            }
-            else {
-                objectEach(prop, function (val, key) {
-                    elem.setAttribute(key, val);
-                });
-            }
-            return ret;
-        }
-        H.attr = attr;
+              },
+              this
+            );
+            this.afterSetters();
+          }
+          // In accordance with animate, run a complete callback
+          if (complete) {
+            complete.call(this);
+          }
+          return ret;
+        };
         /**
-         * Check if an element is an array, and if not, make it into an array.
+         * Apply a clipping rectangle to this element.
          *
-         * @function Highcharts.splat
+         * @function Highcharts.SVGElement#clip
          *
-         * @param {*} obj
-         *        The object to splat.
+         * @param {Highcharts.ClipRectElement} [clipRect]
+         *        The clipping rectangle. If skipped, the current clip is removed.
          *
-         * @return {Array}
-         *         The produced or original array.
+         * @return {Highcharts.SVGElement}
+         *         Returns the SVG element to allow chaining.
          */
-        var splat = H.splat = function splat(obj) {
-                return isArray(obj) ? obj : [obj];
+        SVGElement.prototype.clip = function (clipRect) {
+          return this.attr(
+            "clip-path",
+            clipRect
+              ? "url(" + this.renderer.url + "#" + clipRect.id + ")"
+              : "none"
+          );
         };
         /**
-         * Set a timeout if the delay is given, otherwise perform the function
-         * synchronously.
-         *
-         * @function Highcharts.syncTimeout
-         *
-         * @param {Function} fn
-         *        The function callback.
-         *
-         * @param {number} delay
-         *        Delay in milliseconds.
-         *
-         * @param {*} [context]
-         *        An optional context to send to the function callback.
-         *
-         * @return {number}
-         *         An identifier for the timeout that can later be cleared with
-         *         Highcharts.clearTimeout. Returns -1 if there is no timeout.
-         */
-        var syncTimeout = H.syncTimeout = function syncTimeout(fn,
-            delay,
-            context) {
-                if (delay > 0) {
-                    return setTimeout(fn,
-            delay,
-            context);
-            }
-            fn.call(0, context);
-            return -1;
+         * Calculate the coordinates needed for drawing a rectangle crisply and
+         * return the calculated attributes.
+         *
+         * @function Highcharts.SVGElement#crisp
+         *
+         * @param {Highcharts.RectangleObject} rect
+         * Rectangle to crisp.
+         *
+         * @param {number} [strokeWidth]
+         * The stroke width to consider when computing crisp positioning. It can
+         * also be set directly on the rect parameter.
+         *
+         * @return {Highcharts.RectangleObject}
+         * The modified rectangle arguments.
+         */
+        SVGElement.prototype.crisp = function (rect, strokeWidth) {
+          var wrapper = this,
+            normalizer;
+          strokeWidth = strokeWidth || rect.strokeWidth || 0;
+          // Math.round because strokeWidth can sometimes have roundoff errors
+          normalizer = (Math.round(strokeWidth) % 2) / 2;
+          // normalize for crisp edges
+          rect.x = Math.floor(rect.x || wrapper.x || 0) + normalizer;
+          rect.y = Math.floor(rect.y || wrapper.y || 0) + normalizer;
+          rect.width = Math.floor(
+            (rect.width || wrapper.width || 0) - 2 * normalizer
+          );
+          rect.height = Math.floor(
+            (rect.height || wrapper.height || 0) - 2 * normalizer
+          );
+          if (defined(rect.strokeWidth)) {
+            rect.strokeWidth = strokeWidth;
+          }
+          return rect;
         };
         /**
-         * Internal clear timeout. The function checks that the `id` was not removed
-         * (e.g. by `chart.destroy()`). For the details see
-         * [issue #7901](https://github.com/highcharts/highcharts/issues/7901).
+         * Build and apply an SVG gradient out of a common JavaScript configuration
+         * object. This function is called from the attribute setters. An event
+         * hook is added for supporting other complex color types.
          *
-         * @function Highcharts.clearTimeout
+         * @private
+         * @function Highcharts.SVGElement#complexColor
          *
-         * @param {number} id
-         *        Id of a timeout.
+         * @param {Highcharts.GradientColorObject|Highcharts.PatternObject} colorOptions
+         * The gradient or pattern options structure.
          *
-         * @return {void}
-         */
-        var internalClearTimeout = H.clearTimeout = function (id) {
-                if (defined(id)) {
-                    clearTimeout(id);
+         * @param {string} prop
+         * The property to apply, can either be `fill` or `stroke`.
+         *
+         * @param {Highcharts.SVGDOMElement} elem
+         * SVG element to apply the gradient on.
+         */
+        SVGElement.prototype.complexColor = function (
+          colorOptions,
+          prop,
+          elem
+        ) {
+          var renderer = this.renderer,
+            colorObject,
+            gradName,
+            gradAttr,
+            radAttr,
+            gradients,
+            stops,
+            stopColor,
+            stopOpacity,
+            radialReference,
+            id,
+            key = [],
+            value;
+          fireEvent(
+            this.renderer,
+            "complexColor",
+            {
+              args: arguments,
+            },
+            function () {
+              // Apply linear or radial gradients
+              if (colorOptions.radialGradient) {
+                gradName = "radialGradient";
+              } else if (colorOptions.linearGradient) {
+                gradName = "linearGradient";
+              }
+              if (gradName) {
+                gradAttr = colorOptions[gradName];
+                gradients = renderer.gradients;
+                stops = colorOptions.stops;
+                radialReference = elem.radialReference;
+                // Keep < 2.2 kompatibility
+                if (isArray(gradAttr)) {
+                  colorOptions[gradName] = gradAttr = {
+                    x1: gradAttr[0],
+                    y1: gradAttr[1],
+                    x2: gradAttr[2],
+                    y2: gradAttr[3],
+                    gradientUnits: "userSpaceOnUse",
+                  };
+                }
+                // Correct the radial gradient for the radial reference system
+                if (
+                  gradName === "radialGradient" &&
+                  radialReference &&
+                  !defined(gradAttr.gradientUnits)
+                ) {
+                  // Save the radial attributes for updating
+                  radAttr = gradAttr;
+                  gradAttr = merge(
+                    gradAttr,
+                    renderer.getRadialAttr(radialReference, radAttr),
+                    { gradientUnits: "userSpaceOnUse" }
+                  );
+                }
+                // Build the unique key to detect whether we need to create a
+                // new element (#1282)
+                objectEach(gradAttr, function (val, n) {
+                  if (n !== "id") {
+                    key.push(n, val);
+                  }
+                });
+                objectEach(stops, function (val) {
+                  key.push(val);
+                });
+                key = key.join(",");
+                // Check if a gradient object with the same config object is
+                // created within this renderer
+                if (gradients[key]) {
+                  id = gradients[key].attr("id");
+                } else {
+                  // Set the id and create the element
+                  gradAttr.id = id = uniqueKey();
+                  var gradientObject_1 = (gradients[key] = renderer
+                    .createElement(gradName)
+                    .attr(gradAttr)
+                    .add(renderer.defs));
+                  gradientObject_1.radAttr = radAttr;
+                  // The gradient needs to keep a list of stops to be able to
+                  // destroy them
+                  gradientObject_1.stops = [];
+                  stops.forEach(function (stop) {
+                    var stopObject;
+                    if (stop[1].indexOf("rgba") === 0) {
+                      colorObject = Color.parse(stop[1]);
+                      stopColor = colorObject.get("rgb");
+                      stopOpacity = colorObject.get("a");
+                    } else {
+                      stopColor = stop[1];
+                      stopOpacity = 1;
+                    }
+                    stopObject = renderer
+                      .createElement("stop")
+                      .attr({
+                        offset: stop[0],
+                        "stop-color": stopColor,
+                        "stop-opacity": stopOpacity,
+                      })
+                      .add(gradientObject_1);
+                    // Add the stop element to the gradient
+                    gradientObject_1.stops.push(stopObject);
+                  });
+                }
+                // Set the reference to the gradient object
+                value = "url(" + renderer.url + "#" + id + ")";
+                elem.setAttribute(prop, value);
+                elem.gradient = key;
+                // Allow the color to be concatenated into tooltips formatters
+                // etc. (#2995)
+                colorOptions.toString = function () {
+                  return value;
+                };
+              }
             }
+          );
         };
-        /* eslint-disable valid-jsdoc */
         /**
-         * Utility function to extend an object with the members of another.
+         * Set styles for the element. In addition to CSS styles supported by
+         * native SVG and HTML elements, there are also some custom made for
+         * Highcharts, like `width`, `ellipsis` and `textOverflow` for SVG text
+         * elements.
          *
-         * @function Highcharts.extend<T>
+         * @sample highcharts/members/renderer-text-on-chart/
+         *         Styled text
          *
-         * @param {T|undefined} a
-         *        The object to be extended.
+         * @function Highcharts.SVGElement#css
          *
-         * @param {object} b
-         *        The object to add to the first one.
-         *
-         * @return {T}
-         *         Object a, the original object.
-         */
-        var extend = H.extend = function extend(a,
-            b) {
-                /* eslint-enable valid-jsdoc */
-                var n;
-            if (!a) {
-                a = {};
+         * @param {Highcharts.CSSObject} styles
+         *        The new CSS styles.
+         *
+         * @return {Highcharts.SVGElement}
+         *         Return the SVG element for chaining.
+         */
+        SVGElement.prototype.css = function (styles) {
+          var oldStyles = this.styles,
+            newStyles = {},
+            elem = this.element,
+            textWidth,
+            serializedCss = "",
+            hyphenate,
+            hasNew = !oldStyles,
+            // These CSS properties are interpreted internally by the SVG
+            // renderer, but are not supported by SVG and should not be added to
+            // the DOM. In styled mode, no CSS should find its way to the DOM
+            // whatsoever (#6173, #6474).
+            svgPseudoProps = ["textOutline", "textOverflow", "width"];
+          // convert legacy
+          if (styles && styles.color) {
+            styles.fill = styles.color;
+          }
+          // Filter out existing styles to increase performance (#2640)
+          if (oldStyles) {
+            objectEach(styles, function (style, n) {
+              if (oldStyles && oldStyles[n] !== style) {
+                newStyles[n] = style;
+                hasNew = true;
+              }
+            });
+          }
+          if (hasNew) {
+            // Merge the new styles with the old ones
+            if (oldStyles) {
+              styles = extend(oldStyles, newStyles);
+            }
+            // Get the text width from style
+            if (styles) {
+              // Previously set, unset it (#8234)
+              if (styles.width === null || styles.width === "auto") {
+                delete this.textWidth;
+                // Apply new
+              } else if (
+                elem.nodeName.toLowerCase() === "text" &&
+                styles.width
+              ) {
+                textWidth = this.textWidth = pInt(styles.width);
+              }
+            }
+            // store object
+            this.styles = styles;
+            if (textWidth && !svg && this.renderer.forExport) {
+              delete styles.width;
             }
-            for (n in b) { // eslint-disable-line guard-for-in
-                a[n] = b[n];
+            // Serialize and set style attribute
+            if (elem.namespaceURI === this.SVG_NS) {
+              // #7633
+              hyphenate = function (a, b) {
+                return "-" + b.toLowerCase();
+              };
+              objectEach(styles, function (style, n) {
+                if (svgPseudoProps.indexOf(n) === -1) {
+                  serializedCss +=
+                    n.replace(/([A-Z])/g, hyphenate) + ":" + style + ";";
+                }
+              });
+              if (serializedCss) {
+                attr(elem, "style", serializedCss); // #1881
+              }
+            } else {
+              css(elem, styles);
             }
-            return a;
+            if (this.added) {
+              // Rebuild text after added. Cache mechanisms in the buildText
+              // will prevent building if there are no significant changes.
+              if (this.element.nodeName === "text") {
+                this.renderer.buildText(this);
+              }
+              // Apply text outline after added
+              if (styles && styles.textOutline) {
+                this.applyTextOutline(styles.textOutline);
+              }
+            }
+          }
+          return this;
         };
-        /* eslint-disable valid-jsdoc */
         /**
-         * Return the first value that is not null or undefined.
-         *
-         * @function Highcharts.pick<T>
-         *
-         * @param {...Array<T|null|undefined>} items
-         *        Variable number of arguments to inspect.
-         *
-         * @return {T}
-         *         The value of the first argument that is not null or undefined.
-         */
-        function pick() {
-            var args = arguments;
-            var length = args.length;
-            for (var i = 0; i < length; i++) {
-                var arg = args[i];
-                if (typeof arg !== 'undefined' && arg !== null) {
-                    return arg;
-                }
+         * @private
+         * @function Highcharts.SVGElement#dashstyleSetter
+         * @param {string} value
+         */
+        SVGElement.prototype.dashstyleSetter = function (value) {
+          var i,
+            strokeWidth = this["stroke-width"];
+          // If "inherit", like maps in IE, assume 1 (#4981). With HC5 and the new
+          // strokeWidth function, we should be able to use that instead.
+          if (strokeWidth === "inherit") {
+            strokeWidth = 1;
+          }
+          value = value && value.toLowerCase();
+          if (value) {
+            var v = value
+              .replace("shortdashdotdot", "3,1,1,1,1,1,")
+              .replace("shortdashdot", "3,1,1,1")
+              .replace("shortdot", "1,1,")
+              .replace("shortdash", "3,1,")
+              .replace("longdash", "8,3,")
+              .replace(/dot/g, "1,3,")
+              .replace("dash", "4,3,")
+              .replace(/,$/, "")
+              .split(","); // ending comma
+            i = v.length;
+            while (i--) {
+              v[i] = "" + pInt(v[i]) * pick(strokeWidth, NaN);
             }
-        }
-        H.pick = pick;
+            value = v.join(",").replace(/NaN/g, "none"); // #3226
+            this.element.setAttribute("stroke-dasharray", value);
+          }
+        };
         /**
-         * Set CSS on a given element.
-         *
-         * @function Highcharts.css
-         *
-         * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} el
-         *        An HTML DOM element.
+         * Destroy the element and element wrapper and clear up the DOM and event
+         * hooks.
+         *
+         * @function Highcharts.SVGElement#destroy
+         */
+        SVGElement.prototype.destroy = function () {
+          var wrapper = this,
+            element = wrapper.element || {},
+            renderer = wrapper.renderer,
+            parentToClean =
+              (renderer.isSVG &&
+                element.nodeName === "SPAN" &&
+                wrapper.parentGroup) ||
+              void 0,
+            grandParent,
+            ownerSVGElement = element.ownerSVGElement,
+            i;
+          // remove events
+          element.onclick =
+            element.onmouseout =
+            element.onmouseover =
+            element.onmousemove =
+            element.point =
+              null;
+          stop(wrapper); // stop running animations
+          if (wrapper.clipPath && ownerSVGElement) {
+            var clipPath_1 = wrapper.clipPath;
+            // Look for existing references to this clipPath and remove them
+            // before destroying the element (#6196).
+            // The upper case version is for Edge
+            [].forEach.call(
+              ownerSVGElement.querySelectorAll("[clip-path],[CLIP-PATH]"),
+              function (el) {
+                var clipPathAttr = el.getAttribute("clip-path");
+                if (clipPathAttr.indexOf(clipPath_1.element.id) > -1) {
+                  el.removeAttribute("clip-path");
+                }
+              }
+            );
+            wrapper.clipPath = clipPath_1.destroy();
+          }
+          // Destroy stops in case this is a gradient object @todo old code?
+          if (wrapper.stops) {
+            for (i = 0; i < wrapper.stops.length; i++) {
+              wrapper.stops[i].destroy();
+            }
+            wrapper.stops.length = 0;
+            wrapper.stops = void 0;
+          }
+          // remove element
+          wrapper.safeRemoveChild(element);
+          if (!renderer.styledMode) {
+            wrapper.destroyShadows();
+          }
+          // In case of useHTML, clean up empty containers emulating SVG groups
+          // (#1960, #2393, #2697).
+          while (
+            parentToClean &&
+            parentToClean.div &&
+            parentToClean.div.childNodes.length === 0
+          ) {
+            grandParent = parentToClean.parentGroup;
+            wrapper.safeRemoveChild(parentToClean.div);
+            delete parentToClean.div;
+            parentToClean = grandParent;
+          }
+          // remove from alignObjects
+          if (wrapper.alignTo) {
+            erase(renderer.alignedObjects, wrapper);
+          }
+          objectEach(wrapper, function (val, key) {
+            // Destroy child elements of a group
+            if (
+              wrapper[key] &&
+              wrapper[key].parentGroup === wrapper &&
+              wrapper[key].destroy
+            ) {
+              wrapper[key].destroy();
+            }
+            // Delete all properties
+            delete wrapper[key];
+          });
+          return;
+        };
+        /**
+         * Destroy shadows on the element.
          *
-         * @param {Highcharts.CSSObject} styles
-         *        Style object with camel case property names.
+         * @private
+         * @function Highcharts.SVGElement#destroyShadows
          *
          * @return {void}
          */
-        var css = H.css = function css(el,
-            styles) {
-                if (H.isMS && !H.svg) { // #2686
-                    if (styles && typeof styles.opacity !== 'undefined') {
-                        styles.filter =
-                            'alpha(opacity=' + (styles.opacity * 100) + ')';
-                }
+        SVGElement.prototype.destroyShadows = function () {
+          (this.shadows || []).forEach(function (shadow) {
+            this.safeRemoveChild(shadow);
+          }, this);
+          this.shadows = void 0;
+        };
+        /**
+         * @private
+         */
+        SVGElement.prototype.destroyTextPath = function (elem, path) {
+          var textElement = elem.getElementsByTagName("text")[0];
+          var tspans;
+          if (textElement) {
+            // Remove textPath attributes
+            textElement.removeAttribute("dx");
+            textElement.removeAttribute("dy");
+            // Remove ID's:
+            path.element.setAttribute("id", "");
+            // Check if textElement includes textPath,
+            if (
+              this.textPathWrapper &&
+              textElement.getElementsByTagName("textPath").length
+            ) {
+              // Move nodes to <text>
+              tspans = this.textPathWrapper.element.childNodes;
+              // Now move all <tspan>'s to the <textPath> node
+              while (tspans.length) {
+                textElement.appendChild(tspans[0]);
+              }
+              // Remove <textPath> from the DOM
+              textElement.removeChild(this.textPathWrapper.element);
             }
-            extend(el.style, styles);
+          } else if (elem.getAttribute("dx") || elem.getAttribute("dy")) {
+            // Remove textPath attributes from elem
+            // to get correct text-outline position
+            elem.removeAttribute("dx");
+            elem.removeAttribute("dy");
+          }
+          if (this.textPathWrapper) {
+            // Set textPathWrapper to undefined and destroy it
+            this.textPathWrapper = this.textPathWrapper.destroy();
+          }
         };
         /**
-         * Utility function to create an HTML element with attributes and styles.
-         *
-         * @function Highcharts.createElement
-         *
-         * @param {string} tag
-         *        The HTML tag.
-         *
-         * @param {Highcharts.HTMLAttributes} [attribs]
-         *        Attributes as an object of key-value pairs.
-         *
-         * @param {Highcharts.CSSObject} [styles]
-         *        Styles as an object of key-value pairs.
-         *
-         * @param {Highcharts.HTMLDOMElement} [parent]
-         *        The parent HTML object.
+         * @private
+         * @function Highcharts.SVGElement#dSettter
+         * @param {number|string|Highcharts.SVGPathArray} value
+         * @param {string} key
+         * @param {Highcharts.SVGDOMElement} element
+         */
+        SVGElement.prototype.dSetter = function (value, key, element) {
+          if (isArray(value)) {
+            // Backwards compatibility, convert one-dimensional array into an
+            // array of segments
+            if (typeof value[0] === "string") {
+              value = this.renderer.pathToSegments(value);
+            }
+            this.pathArray = value;
+            value = value.reduce(function (acc, seg, i) {
+              if (!seg || !seg.join) {
+                return (seg || "").toString();
+              }
+              return (i ? acc + " " : "") + seg.join(" ");
+            }, "");
+          }
+          if (/(NaN| {2}|^$)/.test(value)) {
+            value = "M 0 0";
+          }
+          // Check for cache before resetting. Resetting causes disturbance in the
+          // DOM, causing flickering in some cases in Edge/IE (#6747). Also
+          // possible performance gain.
+          if (this[key] !== value) {
+            element.setAttribute(key, value);
+            this[key] = value;
+          }
+        };
+        /**
+         * Fade out an element by animating its opacity down to 0, and hide it on
+         * complete. Used internally for the tooltip.
          *
-         * @param {boolean} [nopad=false]
-         *        If true, remove all padding, border and margin.
+         * @function Highcharts.SVGElement#fadeOut
          *
-         * @return {Highcharts.HTMLDOMElement}
-         *         The created DOM element.
+         * @param {number} [duration=150]
+         * The fade duration in milliseconds.
          */
-        var createElement = H.createElement = function createElement(tag,
-            attribs,
-            styles,
-            parent,
-            nopad) {
-                var el = doc.createElement(tag);
-            if (attribs) {
-                extend(el, attribs);
+        SVGElement.prototype.fadeOut = function (duration) {
+          var elemWrapper = this;
+          elemWrapper.animate(
+            {
+              opacity: 0,
+            },
+            {
+              duration: pick(duration, 150),
+              complete: function () {
+                // #3088, assuming we're only using this for tooltips
+                elemWrapper.attr({ y: -9999 }).hide();
+              },
             }
-            if (nopad) {
-                css(el, { padding: '0', border: 'none', margin: '0' });
+          );
+        };
+        /**
+         * @private
+         * @function Highcharts.SVGElement#fillSetter
+         * @param {Highcharts.ColorType} value
+         * @param {string} key
+         * @param {Highcharts.SVGDOMElement} element
+         */
+        SVGElement.prototype.fillSetter = function (value, key, element) {
+          if (typeof value === "string") {
+            element.setAttribute(key, value);
+          } else if (value) {
+            this.complexColor(value, key, element);
+          }
+        };
+        /**
+         * Get the bounding box (width, height, x and y) for the element. Generally
+         * used to get rendered text size. Since this is called a lot in charts,
+         * the results are cached based on text properties, in order to save DOM
+         * traffic. The returned bounding box includes the rotation, so for example
+         * a single text line of rotation 90 will report a greater height, and a
+         * width corresponding to the line-height.
+         *
+         * @sample highcharts/members/renderer-on-chart/
+         *         Draw a rectangle based on a text's bounding box
+         *
+         * @function Highcharts.SVGElement#getBBox
+         *
+         * @param {boolean} [reload]
+         *        Skip the cache and get the updated DOM bouding box.
+         *
+         * @param {number} [rot]
+         *        Override the element's rotation. This is internally used on axis
+         *        labels with a value of 0 to find out what the bounding box would
+         *        be have been if it were not rotated.
+         *
+         * @return {Highcharts.BBoxObject}
+         *         The bounding box with `x`, `y`, `width` and `height` properties.
+         */
+        SVGElement.prototype.getBBox = function (reload, rot) {
+          var wrapper = this,
+            bBox, // = wrapper.bBox,
+            renderer = wrapper.renderer,
+            width,
+            height,
+            element = wrapper.element,
+            styles = wrapper.styles,
+            fontSize,
+            textStr = wrapper.textStr,
+            toggleTextShadowShim,
+            cache = renderer.cache,
+            cacheKeys = renderer.cacheKeys,
+            isSVG = element.namespaceURI === wrapper.SVG_NS,
+            cacheKey;
+          var rotation = pick(rot, wrapper.rotation, 0);
+          fontSize = renderer.styledMode
+            ? element &&
+              SVGElement.prototype.getStyle.call(element, "font-size")
+            : styles && styles.fontSize;
+          // Avoid undefined and null (#7316)
+          if (defined(textStr)) {
+            cacheKey = textStr.toString();
+            // Since numbers are monospaced, and numerical labels appear a lot
+            // in a chart, we assume that a label of n characters has the same
+            // bounding box as others of the same length. Unless there is inner
+            // HTML in the label. In that case, leave the numbers as is (#5899).
+            if (cacheKey.indexOf("<") === -1) {
+              cacheKey = cacheKey.replace(/[0-9]/g, "0");
             }
-            if (styles) {
-                css(el, styles);
+            // Properties that affect bounding box
+            cacheKey += [
+              "",
+              rotation,
+              fontSize,
+              wrapper.textWidth,
+              styles && styles.textOverflow,
+              styles && styles.fontWeight, // #12163
+            ].join(",");
+          }
+          if (cacheKey && !reload) {
+            bBox = cache[cacheKey];
+          }
+          // No cache found
+          if (!bBox) {
+            // SVG elements
+            if (isSVG || renderer.forExport) {
+              try {
+                // Fails in Firefox if the container has display: none.
+                // When the text shadow shim is used, we need to hide the
+                // fake shadows to get the correct bounding box (#3872)
+                toggleTextShadowShim =
+                  this.fakeTS &&
+                  function (display) {
+                    [].forEach.call(
+                      element.querySelectorAll(".highcharts-text-outline"),
+                      function (tspan) {
+                        tspan.style.display = display;
+                      }
+                    );
+                  };
+                // Workaround for #3842, Firefox reporting wrong bounding
+                // box for shadows
+                if (isFunction(toggleTextShadowShim)) {
+                  toggleTextShadowShim("none");
+                }
+                bBox = element.getBBox
+                  ? // SVG: use extend because IE9 is not allowed to change
+                    // width and height in case of rotation (below)
+                    extend({}, element.getBBox())
+                  : {
+                      // Legacy IE in export mode
+                      width: element.offsetWidth,
+                      height: element.offsetHeight,
+                    };
+                // #3842
+                if (isFunction(toggleTextShadowShim)) {
+                  toggleTextShadowShim("");
+                }
+              } catch (e) {
+                ("");
+              }
+              // If the bBox is not set, the try-catch block above failed. The
+              // other condition is for Opera that returns a width of
+              // -Infinity on hidden elements.
+              if (!bBox || bBox.width < 0) {
+                bBox = { width: 0, height: 0 };
+              }
+              // VML Renderer or useHTML within SVG
+            } else {
+              bBox = wrapper.htmlGetBBox();
+            }
+            // True SVG elements as well as HTML elements in modern browsers
+            // using the .useHTML option need to compensated for rotation
+            if (renderer.isSVG) {
+              width = bBox.width;
+              height = bBox.height;
+              // Workaround for wrong bounding box in IE, Edge and Chrome on
+              // Windows. With Highcharts' default font, IE and Edge report
+              // a box height of 16.899 and Chrome rounds it to 17. If this
+              // stands uncorrected, it results in more padding added below
+              // the text than above when adding a label border or background.
+              // Also vertical positioning is affected.
+              // https://jsfiddle.net/highcharts/em37nvuj/
+              // (#1101, #1505, #1669, #2568, #6213).
+              if (isSVG) {
+                bBox.height = height =
+                  {
+                    "11px,17": 14,
+                    "13px,20": 16,
+                  }[styles && styles.fontSize + "," + Math.round(height)] ||
+                  height;
+              }
+              // Adjust for rotated text
+              if (rotation) {
+                var rad = rotation * deg2rad;
+                bBox.width =
+                  Math.abs(height * Math.sin(rad)) +
+                  Math.abs(width * Math.cos(rad));
+                bBox.height =
+                  Math.abs(height * Math.cos(rad)) +
+                  Math.abs(width * Math.sin(rad));
+              }
             }
-            if (parent) {
-                parent.appendChild(el);
+            // Cache it. When loading a chart in a hidden iframe in Firefox and
+            // IE/Edge, the bounding box height is 0, so don't cache it (#5620).
+            if (cacheKey && bBox.height > 0) {
+              // Rotate (#4681)
+              while (cacheKeys.length > 250) {
+                delete cache[cacheKeys.shift()];
+              }
+              if (!cache[cacheKey]) {
+                cacheKeys.push(cacheKey);
+              }
+              cache[cacheKey] = bBox;
             }
-            return el;
+          }
+          return bBox;
         };
-        // eslint-disable-next-line valid-jsdoc
         /**
-         * Extend a prototyped class by new members.
+         * Get the computed style. Only in styled mode.
          *
-         * @function Highcharts.extendClass<T>
+         * @example
+         * chart.series[0].points[0].graphic.getStyle('stroke-width'); // => '1px'
          *
-         * @param {Highcharts.Class<T>} parent
-         *        The parent prototype to inherit.
+         * @function Highcharts.SVGElement#getStyle
          *
-         * @param {Highcharts.Dictionary<*>} members
-         *        A collection of prototype members to add or override compared to the
-         *        parent prototype.
+         * @param {string} prop
+         *        The property name to check for.
          *
-         * @return {Highcharts.Class<T>}
-         *         A new prototype.
+         * @return {string}
+         *         The current computed value.
          */
-        var extendClass = H.extendClass = function extendClass(parent,
-            members) {
-                var obj = (function () { });
-            obj.prototype = new parent(); // eslint-disable-line new-cap
-            extend(obj.prototype, members);
-            return obj;
+        SVGElement.prototype.getStyle = function (prop) {
+          return win
+            .getComputedStyle(this.element || this, "")
+            .getPropertyValue(prop);
         };
         /**
-         * Left-pad a string to a given length by adding a character repetetively.
-         *
-         * @function Highcharts.pad
+         * Check if an element has the given class name.
          *
-         * @param {number} number
-         *        The input string or number.
+         * @function Highcharts.SVGElement#hasClass
          *
-         * @param {number} [length]
-         *        The desired string length.
+         * @param {string} className
+         * The class name to check for.
          *
-         * @param {string} [padder=0]
-         *        The character to pad with.
-         *
-         * @return {string}
-         *         The padded string.
+         * @return {boolean}
+         * Whether the class name is found.
          */
-        var pad = H.pad = function pad(number, length, padder) {
-                return new Array((length || 2) +
-                    1 -
-                    String(number)
-                        .replace('-', '')
-                        .length).join(padder || '0') + number;
+        SVGElement.prototype.hasClass = function (className) {
+          return ("" + this.attr("class")).split(" ").indexOf(className) !== -1;
         };
         /**
-         * Return a length based on either the integer value, or a percentage of a base.
-         *
-         * @function Highcharts.relativeLength
+         * Hide the element, similar to setting the `visibility` attribute to
+         * `hidden`.
          *
-         * @param {Highcharts.RelativeSize} value
-         *        A percentage string or a number.
+         * @function Highcharts.SVGElement#hide
          *
-         * @param {number} base
-         *        The full length that represents 100%.
+         * @param {boolean} [hideByTranslation=false]
+         *        The flag to determine if element should be hidden by moving out
+         *        of the viewport. Used for example for dataLabels.
          *
-         * @param {number} [offset=0]
-         *        A pixel offset to apply for percentage values. Used internally in
-         *        axis positioning.
-         *
-         * @return {number}
-         *         The computed length.
-         */
-        var relativeLength = H.relativeLength = function relativeLength(value,
-            base,
-            offset) {
-                return (/%$/).test(value) ?
-                    (base * parseFloat(value) / 100) + (offset || 0) :
-                    parseFloat(value);
-        };
-        /**
-         * Wrap a method with extended functionality, preserving the original function.
-         *
-         * @function Highcharts.wrap
-         *
-         * @param {*} obj
-         *        The context object that the method belongs to. In real cases, this is
-         *        often a prototype.
-         *
-         * @param {string} method
-         *        The name of the method to extend.
-         *
-         * @param {Highcharts.WrapProceedFunction} func
-         *        A wrapper function callback. This function is called with the same
-         *        arguments as the original function, except that the original function
-         *        is unshifted and passed as the first argument.
-         */
-        var wrap = H.wrap = function wrap(obj,
-            method,
-            func) {
-                var proceed = obj[method];
-            obj[method] = function () {
-                var args = Array.prototype.slice.call(arguments),
-                    outerArgs = arguments,
-                    ctx = this,
-                    ret;
-                ctx.proceed = function () {
-                    proceed.apply(ctx, arguments.length ? arguments : outerArgs);
-                };
-                args.unshift(proceed);
-                ret = func.apply(this, args);
-                ctx.proceed = null;
-                return ret;
-            };
+         * @return {Highcharts.SVGElement}
+         *         Returns the SVGElement for chaining.
+         */
+        SVGElement.prototype.hide = function (hideByTranslation) {
+          if (hideByTranslation) {
+            this.attr({ y: -9999 });
+          } else {
+            this.attr({ visibility: "hidden" });
+          }
+          return this;
         };
         /**
-         * Format a string according to a subset of the rules of Python's String.format
-         * method.
-         *
-         * @example
-         * var s = Highcharts.format(
-         *     'The {color} fox was {len:.2f} feet long',
-         *     { color: 'red', len: Math.PI }
-         * );
-         * // => The red fox was 3.14 feet long
-         *
-         * @function Highcharts.format
-         *
-         * @param {string} str
-         *        The string to format.
-         *
-         * @param {Record<string, *>} ctx
-         *        The context, a collection of key-value pairs where each key is
-         *        replaced by its value.
-         *
-         * @param {Highcharts.Chart} [chart]
-         *        A `Chart` instance used to get numberFormatter and time.
-         *
-         * @return {string}
-         *         The formatted string.
-         */
-        var format = H.format = function (str,
-            ctx,
-            chart) {
-                var splitter = '{',
-            isInside = false,
-            segment,
-            valueAndFormat,
-            ret = [],
-            val,
-            index;
-            var floatRegex = /f$/;
-            var decRegex = /\.([0-9])/;
-            var lang = H.defaultOptions.lang;
-            var time = chart && chart.time || H.time;
-            var numberFormatter = chart && chart.numberFormatter || numberFormat;
-            while (str) {
-                index = str.indexOf(splitter);
-                if (index === -1) {
-                    break;
-                }
-                segment = str.slice(0, index);
-                if (isInside) { // we're on the closing bracket looking back
-                    valueAndFormat = segment.split(':');
-                    val = getNestedProperty(valueAndFormat.shift() || '', ctx);
-                    // Format the replacement
-                    if (valueAndFormat.length && typeof val === 'number') {
-                        segment = valueAndFormat.join(':');
-                        if (floatRegex.test(segment)) { // float
-                            var decimals = parseInt((segment.match(decRegex) || ['', '-1'])[1], 10);
-                            if (val !== null) {
-                                val = numberFormatter(val, decimals, lang.decimalPoint, segment.indexOf(',') > -1 ? lang.thousandsSep : '');
-                            }
-                        }
-                        else {
-                            val = time.dateFormat(segment, val);
-                        }
-                    }
-                    // Push the result and advance the cursor
-                    ret.push(val);
-                }
-                else {
-                    ret.push(segment);
-                }
-                str = str.slice(index + 1); // the rest
-                isInside = !isInside; // toggle
-                splitter = isInside ? '}' : '{'; // now look for next matching bracket
-            }
-            ret.push(str);
-            return ret.join('');
+         * @private
+         */
+        SVGElement.prototype.htmlGetBBox = function () {
+          return { height: 0, width: 0, x: 0, y: 0 };
         };
         /**
-         * Get the magnitude of a number.
+         * Initialize the SVG element. This function only exists to make the
+         * initialization process overridable. It should not be called directly.
+         *
+         * @function Highcharts.SVGElement#init
+         *
+         * @param {Highcharts.SVGRenderer} renderer
+         * The SVGRenderer instance to initialize to.
+         *
+         * @param {string} nodeName
+         * The SVG node name.
+         */
+        SVGElement.prototype.init = function (renderer, nodeName) {
+          /**
+           * The primary DOM node. Each `SVGElement` instance wraps a main DOM
+           * node, but may also represent more nodes.
+           *
+           * @name Highcharts.SVGElement#element
+           * @type {Highcharts.SVGDOMElement|Highcharts.HTMLDOMElement}
+           */
+          this.element =
+            nodeName === "span"
+              ? createElement(nodeName)
+              : doc.createElementNS(this.SVG_NS, nodeName);
+          /**
+           * The renderer that the SVGElement belongs to.
+           *
+           * @name Highcharts.SVGElement#renderer
+           * @type {Highcharts.SVGRenderer}
+           */
+          this.renderer = renderer;
+          fireEvent(this, "afterInit");
+        };
+        /**
+         * Invert a group, rotate and flip. This is used internally on inverted
+         * charts, where the points and graphs are drawn as if not inverted, then
+         * the series group elements are inverted.
          *
-         * @function Highcharts.getMagnitude
+         * @function Highcharts.SVGElement#invert
          *
-         * @param {number} num
-         *        The number.
+         * @param {boolean} inverted
+         *        Whether to invert or not. An inverted shape can be un-inverted by
+         *        setting it to false.
          *
-         * @return {number}
-         *         The magnitude, where 1-9 are magnitude 1, 10-99 magnitude 2 etc.
+         * @return {Highcharts.SVGElement}
+         *         Return the SVGElement for chaining.
          */
-        var getMagnitude = H.getMagnitude = function (num) {
-                return Math.pow(10,
-            Math.floor(Math.log(num) / Math.LN10));
+        SVGElement.prototype.invert = function (inverted) {
+          var wrapper = this;
+          wrapper.inverted = inverted;
+          wrapper.updateTransform();
+          return wrapper;
         };
         /**
-         * Take an interval and normalize it to multiples of round numbers.
-         *
-         * @deprecated
-         * @function Highcharts.normalizeTickInterval
-         *
-         * @param {number} interval
-         *        The raw, un-rounded interval.
-         *
-         * @param {Array<*>} [multiples]
-         *        Allowed multiples.
-         *
-         * @param {number} [magnitude]
-         *        The magnitude of the number.
+         * Add an event listener. This is a simple setter that replaces all other
+         * events of the same type, opposed to the {@link Highcharts#addEvent}
+         * function.
          *
-         * @param {boolean} [allowDecimals]
-         *        Whether to allow decimals.
+         * @sample highcharts/members/element-on/
+         *         A clickable rectangle
+         *
+         * @function Highcharts.SVGElement#on
+         *
+         * @param {string} eventType
+         * The event type. If the type is `click`, Highcharts will internally
+         * translate it to a `touchstart` event on touch devices, to prevent the
+         * browser from waiting for a click event from firing.
+         *
+         * @param {Function} handler
+         * The handler callback.
+         *
+         * @return {Highcharts.SVGElement}
+         * The SVGElement for chaining.
+         */
+        SVGElement.prototype.on = function (eventType, handler) {
+          var svgElement = this,
+            element = svgElement.element,
+            touchStartPos,
+            touchEventFired;
+          // touch
+          if (hasTouch && eventType === "click") {
+            element.ontouchstart = function (e) {
+              // save touch position for later calculation
+              touchStartPos = {
+                clientX: e.touches[0].clientX,
+                clientY: e.touches[0].clientY,
+              };
+            };
+            // Instead of ontouchstart, event handlers should be called
+            // on touchend - similar to how current mouseup events are called
+            element.ontouchend = function (e) {
+              // hasMoved is a boolean variable containing logic if page
+              // was scrolled, so if touch position changed more than
+              // ~4px (value borrowed from general touch handler)
+              var hasMoved = touchStartPos.clientX
+                ? Math.sqrt(
+                    Math.pow(
+                      touchStartPos.clientX - e.changedTouches[0].clientX,
+                      2
+                    ) +
+                      Math.pow(
+                        touchStartPos.clientY - e.changedTouches[0].clientY,
+                        2
+                      )
+                  ) >= 4
+                : false;
+              if (!hasMoved) {
+                // only call handlers if page was not scrolled
+                handler.call(element, e);
+              }
+              touchEventFired = true;
+              if (e.cancelable !== false) {
+                // prevent other events from being fired. #9682
+                e.preventDefault();
+              }
+            };
+            element.onclick = function (e) {
+              // Do not call onclick handler if touch event was fired already.
+              if (!touchEventFired) {
+                handler.call(element, e);
+              }
+            };
+          } else {
+            // simplest possible event model for internal use
+            element["on" + eventType] = handler;
+          }
+          return this;
+        };
+        /**
+         * @private
+         * @function Highcharts.SVGElement#opacitySetter
+         * @param {string} value
+         * @param {string} key
+         * @param {Highcharts.SVGDOMElement} element
+         */
+        SVGElement.prototype.opacitySetter = function (value, key, element) {
+          // Round off to avoid float errors, like tests where opacity lands on
+          // 9.86957e-06 instead of 0
+          var opacity = Number(Number(value).toFixed(3));
+          this.opacity = opacity;
+          element.setAttribute(key, opacity);
+        };
+        /**
+         * Remove a class name from the element.
          *
-         * @param {boolean} [hasTickAmount]
-         *        If it has tickAmount, avoid landing on tick intervals lower than
-         *        original.
+         * @function Highcharts.SVGElement#removeClass
          *
-         * @return {number}
-         *         The normalized interval.
+         * @param {string|RegExp} className
+         *        The class name to remove.
          *
-         * @todo
-         * Move this function to the Axis prototype. It is here only for historical
-         * reasons.
+         * @return {Highcharts.SVGElement} Returns the SVG element for chainability.
          */
-        var normalizeTickInterval = H.normalizeTickInterval = function (interval,
-            multiples,
-            magnitude,
-            allowDecimals,
-            hasTickAmount) {
-                var normalized,
-            i,
-            retInterval = interval;
-            // round to a tenfold of 1, 2, 2.5 or 5
-            magnitude = pick(magnitude, 1);
-            normalized = interval / magnitude;
-            // multiples for a linear scale
-            if (!multiples) {
-                multiples = hasTickAmount ?
-                    // Finer grained ticks when the tick amount is hard set, including
-                    // when alignTicks is true on multiple axes (#4580).
-                    [1, 1.2, 1.5, 2, 2.5, 3, 4, 5, 6, 8, 10] :
-                    // Else, let ticks fall on rounder numbers
-                    [1, 2, 2.5, 5, 10];
-                // the allowDecimals option
-                if (allowDecimals === false) {
-                    if (magnitude === 1) {
-                        multiples = multiples.filter(function (num) {
-                            return num % 1 === 0;
-                        });
-                    }
-                    else if (magnitude <= 0.1) {
-                        multiples = [1 / magnitude];
-                    }
-                }
-            }
-            // normalize the interval to the nearest multiple
-            for (i = 0; i < multiples.length; i++) {
-                retInterval = multiples[i];
-                // only allow tick amounts smaller than natural
-                if ((hasTickAmount &&
-                    retInterval * magnitude >= interval) ||
-                    (!hasTickAmount &&
-                        (normalized <=
-                            (multiples[i] +
-                                (multiples[i + 1] || multiples[i])) / 2))) {
-                    break;
-                }
+        SVGElement.prototype.removeClass = function (className) {
+          return this.attr(
+            "class",
+            ("" + this.attr("class"))
+              .replace(
+                isString(className)
+                  ? new RegExp("(^| )" + className + "( |$)") // #12064, #13590
+                  : className,
+                " "
+              )
+              .replace(/ +/g, " ")
+              .trim()
+          );
+        };
+        /**
+         * @private
+         * @param {Array<Highcharts.SVGDOMElement>} tspans
+         * Text spans.
+         */
+        SVGElement.prototype.removeTextOutline = function (tspans) {
+          // Iterate from the end to
+          // support removing items inside the cycle (#6472).
+          var i = tspans.length,
+            tspan;
+          while (i--) {
+            tspan = tspans[i];
+            if (tspan.getAttribute("class") === "highcharts-text-outline") {
+              // Remove then erase
+              erase(tspans, this.element.removeChild(tspan));
             }
-            // Multiply back to the correct magnitude. Correct floats to appropriate
-            // precision (#6085).
-            retInterval = correctFloat(retInterval * magnitude, -Math.round(Math.log(0.001) / Math.LN10));
-            return retInterval;
+          }
         };
         /**
-         * Sort an object array and keep the order of equal items. The ECMAScript
-         * standard does not specify the behaviour when items are equal.
-         *
-         * @function Highcharts.stableSort
+         * Removes an element from the DOM.
          *
-         * @param {Array<*>} arr
-         *        The array to sort.
-         *
-         * @param {Function} sortFunction
-         *        The function to sort it with, like with regular Array.prototype.sort.
+         * @private
+         * @function Highcharts.SVGElement#safeRemoveChild
          *
-         * @return {void}
+         * @param {Highcharts.SVGDOMElement|Highcharts.HTMLDOMElement} element
+         * The DOM node to remove.
          */
-        var stableSort = H.stableSort = function stableSort(arr,
-            sortFunction) {
-                // @todo It seems like Chrome since v70 sorts in a stable way internally,
-                // plus all other browsers do it, so over time we may be able to remove this
-                // function
-                var length = arr.length,
-            sortValue,
-            i;
-            // Add index to each item
-            for (i = 0; i < length; i++) {
-                arr[i].safeI = i; // stable sort index
+        SVGElement.prototype.safeRemoveChild = function (element) {
+          var parentNode = element.parentNode;
+          if (parentNode) {
+            parentNode.removeChild(element);
+          }
+        };
+        /**
+         * Set the coordinates needed to draw a consistent radial gradient across
+         * a shape regardless of positioning inside the chart. Used on pie slices
+         * to make all the slices have the same radial reference point.
+         *
+         * @function Highcharts.SVGElement#setRadialReference
+         *
+         * @param {Array<number>} coordinates
+         * The center reference. The format is `[centerX, centerY, diameter]` in
+         * pixels.
+         *
+         * @return {Highcharts.SVGElement}
+         * Returns the SVGElement for chaining.
+         */
+        SVGElement.prototype.setRadialReference = function (coordinates) {
+          var existingGradient =
+            this.element.gradient &&
+            this.renderer.gradients[this.element.gradient];
+          this.element.radialReference = coordinates;
+          // On redrawing objects with an existing gradient, the gradient needs
+          // to be repositioned (#3801)
+          if (existingGradient && existingGradient.radAttr) {
+            existingGradient.animate(
+              this.renderer.getRadialAttr(coordinates, existingGradient.radAttr)
+            );
+          }
+          return this;
+        };
+        /**
+         * @private
+         * @function Highcharts.SVGElement#setTextPath
+         * @param {Highcharts.SVGElement} path
+         * Path to follow.
+         * @param {Highcharts.DataLabelsTextPathOptionsObject} textPathOptions
+         * Options.
+         * @return {Highcharts.SVGElement}
+         * Returns the SVGElement for chaining.
+         */
+        SVGElement.prototype.setTextPath = function (path, textPathOptions) {
+          var elem = this.element,
+            attribsMap = {
+              textAnchor: "text-anchor",
+            },
+            attrs,
+            adder = false,
+            textPathElement,
+            textPathId,
+            textPathWrapper = this.textPathWrapper,
+            tspans,
+            firstTime = !textPathWrapper;
+          // Defaults
+          textPathOptions = merge(
+            true,
+            {
+              enabled: true,
+              attributes: {
+                dy: -5,
+                startOffset: "50%",
+                textAnchor: "middle",
+              },
+            },
+            textPathOptions
+          );
+          attrs = textPathOptions.attributes;
+          if (path && textPathOptions && textPathOptions.enabled) {
+            // In case of fixed width for a text, string is rebuilt
+            // (e.g. ellipsis is applied), so we need to rebuild textPath too
+            if (
+              textPathWrapper &&
+              textPathWrapper.element.parentNode === null
+            ) {
+              // When buildText functionality was triggered again
+              // and deletes textPathWrapper parentNode
+              firstTime = true;
+              textPathWrapper = textPathWrapper.destroy();
+            } else if (textPathWrapper) {
+              // Case after drillup when spans were added into
+              // the DOM outside the textPathWrapper parentGroup
+              this.removeTextOutline.call(
+                textPathWrapper.parentGroup,
+                [].slice.call(elem.getElementsByTagName("tspan"))
+              );
+            }
+            // label() has padding, text() doesn't
+            if (this.options && this.options.padding) {
+              attrs.dx = -this.options.padding;
+            }
+            if (!textPathWrapper) {
+              // Create <textPath>, defer the DOM adder
+              this.textPathWrapper = textPathWrapper =
+                this.renderer.createElement("textPath");
+              adder = true;
+            }
+            textPathElement = textPathWrapper.element;
+            // Set ID for the path
+            textPathId = path.element.getAttribute("id");
+            if (!textPathId) {
+              path.element.setAttribute("id", (textPathId = uniqueKey()));
+            }
+            // Change DOM structure, by placing <textPath> tag in <text>
+            if (firstTime) {
+              tspans = elem.getElementsByTagName("tspan");
+              // Now move all <tspan>'s to the <textPath> node
+              while (tspans.length) {
+                // Remove "y" from tspans, as Firefox translates them
+                tspans[0].setAttribute("y", 0);
+                // Remove "x" from tspans
+                if (isNumber(attrs.dx)) {
+                  tspans[0].setAttribute("x", -attrs.dx);
+                }
+                textPathElement.appendChild(tspans[0]);
+              }
+            }
+            // Add <textPath> to the DOM
+            if (adder && textPathWrapper) {
+              textPathWrapper.add({
+                // label() is placed in a group, text() is standalone
+                element: this.text ? this.text.element : elem,
+              });
+            }
+            // Set basic options:
+            // Use `setAttributeNS` because Safari needs this..
+            textPathElement.setAttributeNS(
+              "http://www.w3.org/1999/xlink",
+              "href",
+              this.renderer.url + "#" + textPathId
+            );
+            // Presentation attributes:
+            // dx/dy options must by set on <text> (parent),
+            // the rest should be set on <textPath>
+            if (defined(attrs.dy)) {
+              textPathElement.parentNode.setAttribute("dy", attrs.dy);
+              delete attrs.dy;
             }
-            arr.sort(function (a, b) {
-                sortValue = sortFunction(a, b);
-                return sortValue === 0 ? a.safeI - b.safeI : sortValue;
+            if (defined(attrs.dx)) {
+              textPathElement.parentNode.setAttribute("dx", attrs.dx);
+              delete attrs.dx;
+            }
+            // Additional attributes
+            objectEach(attrs, function (val, key) {
+              textPathElement.setAttribute(attribsMap[key] || key, val);
             });
-            // Remove index from items
-            for (i = 0; i < length; i++) {
-                delete arr[i].safeI; // stable sort index
+            // Remove translation, text that follows path does not need that
+            elem.removeAttribute("transform");
+            // Remove shadows and text outlines
+            this.removeTextOutline.call(
+              textPathWrapper,
+              [].slice.call(elem.getElementsByTagName("tspan"))
+            );
+            // Remove background and border for label(), see #10545
+            // Alternatively, we can disable setting background rects in
+            // series.drawDataLabels()
+            if (this.text && !this.renderer.styledMode) {
+              this.attr({
+                fill: "none",
+                "stroke-width": 0,
+              });
+            }
+            // Disable some functions
+            this.updateTransform = noop;
+            this.applyTextOutline = noop;
+          } else if (textPathWrapper) {
+            // Reset to prototype
+            delete this.updateTransform;
+            delete this.applyTextOutline;
+            // Restore DOM structure:
+            this.destroyTextPath(elem, path);
+            // Bring attributes back
+            this.updateTransform();
+            // Set textOutline back for text()
+            if (this.options && this.options.rotation) {
+              this.applyTextOutline(this.options.style.textOutline);
             }
+          }
+          return this;
         };
         /**
-         * Non-recursive method to find the lowest member of an array. `Math.min` raises
-         * a maximum call stack size exceeded error in Chrome when trying to apply more
-         * than 150.000 points. This method is slightly slower, but safe.
+         * Add a shadow to the element. Must be called after the element is added to
+         * the DOM. In styled mode, this method is not used, instead use `defs` and
+         * filters.
          *
-         * @function Highcharts.arrayMin
+         * @example
+         * renderer.rect(10, 100, 100, 100)
+         *     .attr({ fill: 'red' })
+         *     .shadow(true);
          *
-         * @param {Array<*>} data
-         *        An array of numbers.
+         * @function Highcharts.SVGElement#shadow
          *
-         * @return {number}
-         *         The lowest number.
-         */
-        var arrayMin = H.arrayMin = function arrayMin(data) {
-                var i = data.length,
-            min = data[0];
-            while (i--) {
-                if (data[i] < min) {
-                    min = data[i];
-                }
-            }
-            return min;
-        };
-        /**
-         * Non-recursive method to find the lowest member of an array. `Math.max` raises
-         * a maximum call stack size exceeded error in Chrome when trying to apply more
-         * than 150.000 points. This method is slightly slower, but safe.
+         * @param {boolean|Highcharts.ShadowOptionsObject} [shadowOptions]
+         *        The shadow options. If `true`, the default options are applied. If
+         *        `false`, the current shadow will be removed.
          *
-         * @function Highcharts.arrayMax
+         * @param {Highcharts.SVGElement} [group]
+         *        The SVG group element where the shadows will be applied. The
+         *        default is to add it to the same parent as the current element.
+         *        Internally, this is ised for pie slices, where all the shadows are
+         *        added to an element behind all the slices.
          *
-         * @param {Array<*>} data
-         *        An array of numbers.
+         * @param {boolean} [cutOff]
+         *        Used internally for column shadows.
          *
-         * @return {number}
-         *         The highest number.
+         * @return {Highcharts.SVGElement}
+         *         Returns the SVGElement for chaining.
          */
-        var arrayMax = H.arrayMax = function arrayMax(data) {
-                var i = data.length,
-            max = data[0];
-            while (i--) {
-                if (data[i] > max) {
-                    max = data[i];
-                }
+        SVGElement.prototype.shadow = function (shadowOptions, group, cutOff) {
+          var shadows = [],
+            i,
+            shadow,
+            element = this.element,
+            strokeWidth,
+            shadowElementOpacity,
+            update = false,
+            oldShadowOptions = this.oldShadowOptions,
+            // compensate for inverted plot area
+            transform;
+          var defaultShadowOptions = {
+            color: "#000000",
+            offsetX: 1,
+            offsetY: 1,
+            opacity: 0.15,
+            width: 3,
+          };
+          var options;
+          if (shadowOptions === true) {
+            options = defaultShadowOptions;
+          } else if (typeof shadowOptions === "object") {
+            options = extend(defaultShadowOptions, shadowOptions);
+          }
+          // Update shadow when options change (#12091).
+          if (options) {
+            // Go over each key to look for change
+            if (options && oldShadowOptions) {
+              objectEach(options, function (value, key) {
+                if (value !== oldShadowOptions[key]) {
+                  update = true;
+                }
+              });
+            }
+            if (update) {
+              this.destroyShadows();
+            }
+            this.oldShadowOptions = options;
+          }
+          if (!options) {
+            this.destroyShadows();
+          } else if (!this.shadows) {
+            shadowElementOpacity = options.opacity / options.width;
+            transform = this.parentInverted
+              ? "translate(-1,-1)"
+              : "translate(" + options.offsetX + ", " + options.offsetY + ")";
+            for (i = 1; i <= options.width; i++) {
+              shadow = element.cloneNode(false);
+              strokeWidth = options.width * 2 + 1 - 2 * i;
+              attr(shadow, {
+                stroke: shadowOptions.color || "#000000",
+                "stroke-opacity": shadowElementOpacity * i,
+                "stroke-width": strokeWidth,
+                transform: transform,
+                fill: "none",
+              });
+              shadow.setAttribute(
+                "class",
+                (shadow.getAttribute("class") || "") + " highcharts-shadow"
+              );
+              if (cutOff) {
+                attr(
+                  shadow,
+                  "height",
+                  Math.max(attr(shadow, "height") - strokeWidth, 0)
+                );
+                shadow.cutHeight = strokeWidth;
+              }
+              if (group) {
+                group.element.appendChild(shadow);
+              } else if (element.parentNode) {
+                element.parentNode.insertBefore(shadow, element);
+              }
+              shadows.push(shadow);
             }
-            return max;
+            this.shadows = shadows;
+          }
+          return this;
         };
         /**
-         * Utility method that destroys any SVGElement instances that are properties on
-         * the given object. It loops all properties and invokes destroy if there is a
-         * destroy method. The property is then delete.
+         * Show the element after it has been hidden.
          *
-         * @function Highcharts.destroyObjectProperties
+         * @function Highcharts.SVGElement#show
          *
-         * @param {*} obj
-         *        The object to destroy properties on.
+         * @param {boolean} [inherit=false]
+         *        Set the visibility attribute to `inherit` rather than `visible`.
+         *        The difference is that an element with `visibility="visible"`
+         *        will be visible even if the parent is hidden.
          *
-         * @param {*} [except]
-         *        Exception, do not destroy this property, only delete it.
+         * @return {Highcharts.SVGElement}
+         *         Returns the SVGElement for chaining.
          */
-        var destroyObjectProperties = H.destroyObjectProperties =
-                function destroyObjectProperties(obj,
-            except) {
-                    objectEach(obj,
-            function (val,
-            n) {
-                        // If the object is non-null and destroy is defined
-                        if (val && val !== except && val.destroy) {
-                            // Invoke the destroy
-                            val.destroy();
-                    }
-                    // Delete the property from the object.
-                    delete obj[n];
-                });
-            };
+        SVGElement.prototype.show = function (inherit) {
+          return this.attr({ visibility: inherit ? "inherit" : "visible" });
+        };
         /**
-         * Discard a HTML element by moving it to the bin and delete.
+         * WebKit and Batik have problems with a stroke-width of zero, so in this
+         * case we remove the stroke attribute altogether. #1270, #1369, #3065,
+         * #3072.
          *
-         * @function Highcharts.discardElement
-         *
-         * @param {Highcharts.HTMLDOMElement} element
-         *        The HTML node to discard.
-         */
-        var discardElement = H.discardElement = function discardElement(element) {
-                var garbageBin = H.garbageBin;
-            // create a garbage bin element, not part of the DOM
-            if (!garbageBin) {
-                garbageBin = createElement('div');
-            }
-            // move the node and empty bin
-            if (element) {
-                garbageBin.appendChild(element);
-            }
-            garbageBin.innerHTML = '';
+         * @private
+         * @function Highcharts.SVGElement#strokeSetter
+         * @param {number|string} value
+         * @param {string} key
+         * @param {Highcharts.SVGDOMElement} element
+         */
+        SVGElement.prototype.strokeSetter = function (value, key, element) {
+          this[key] = value;
+          // Only apply the stroke attribute if the stroke width is defined and
+          // larger than 0
+          if (this.stroke && this["stroke-width"]) {
+            // Use prototype as instance may be overridden
+            SVGElement.prototype.fillSetter.call(
+              this,
+              this.stroke,
+              "stroke",
+              element
+            );
+            element.setAttribute("stroke-width", this["stroke-width"]);
+            this.hasStroke = true;
+          } else if (key === "stroke-width" && value === 0 && this.hasStroke) {
+            element.removeAttribute("stroke");
+            this.hasStroke = false;
+          } else if (this.renderer.styledMode && this["stroke-width"]) {
+            element.setAttribute("stroke-width", this["stroke-width"]);
+            this.hasStroke = true;
+          }
         };
         /**
-         * Fix JS round off float errors.
+         * Get the computed stroke width in pixel values. This is used extensively
+         * when drawing shapes to ensure the shapes are rendered crisp and
+         * positioned correctly relative to each other. Using
+         * `shape-rendering: crispEdges` leaves us less control over positioning,
+         * for example when we want to stack columns next to each other, or position
+         * things pixel-perfectly within the plot box.
          *
-         * @function Highcharts.correctFloat
+         * The common pattern when placing a shape is:
+         * - Create the SVGElement and add it to the DOM. In styled mode, it will
+         *   now receive a stroke width from the style sheet. In classic mode we
+         *   will add the `stroke-width` attribute.
+         * - Read the computed `elem.strokeWidth()`.
+         * - Place it based on the stroke width.
          *
-         * @param {number} num
-         *        A float number to fix.
-         *
-         * @param {number} [prec=14]
-         *        The precision.
+         * @function Highcharts.SVGElement#strokeWidth
          *
          * @return {number}
-         *         The corrected float number.
-         */
-        var correctFloat = H.correctFloat = function correctFloat(num,
-            prec) {
-                return parseFloat(num.toPrecision(prec || 14));
+         * The stroke width in pixels. Even if the given stroke widtch (in CSS or by
+         * attributes) is based on `em` or other units, the pixel size is returned.
+         */
+        SVGElement.prototype.strokeWidth = function () {
+          // In non-styled mode, read the stroke width as set by .attr
+          if (!this.renderer.styledMode) {
+            return this["stroke-width"] || 0;
+          }
+          // In styled mode, read computed stroke width
+          var val = this.getStyle("stroke-width"),
+            ret = 0,
+            dummy;
+          // Read pixel values directly
+          if (val.indexOf("px") === val.length - 2) {
+            ret = pInt(val);
+            // Other values like em, pt etc need to be measured
+          } else if (val !== "") {
+            dummy = doc.createElementNS(SVG_NS, "rect");
+            attr(dummy, {
+              width: val,
+              "stroke-width": 0,
+            });
+            this.element.parentNode.appendChild(dummy);
+            ret = dummy.getBBox().width;
+            dummy.parentNode.removeChild(dummy);
+          }
+          return ret;
         };
         /**
-         * The time unit lookup
+         * If one of the symbol size affecting parameters are changed,
+         * check all the others only once for each call to an element's
+         * .attr() method
          *
-         * @ignore
-         */
-        var timeUnits = H.timeUnits = {
-                millisecond: 1,
-                second: 1000,
-                minute: 60000,
-                hour: 3600000,
-                day: 24 * 3600000,
-                week: 7 * 24 * 3600000,
-                month: 28 * 24 * 3600000,
-                year: 364 * 24 * 3600000
-            };
+         * @private
+         * @function Highcharts.SVGElement#symbolAttr
+         *
+         * @param {Highcharts.SVGAttributes} hash
+         * The attributes to set.
+         */
+        SVGElement.prototype.symbolAttr = function (hash) {
+          var wrapper = this;
+          [
+            "x",
+            "y",
+            "r",
+            "start",
+            "end",
+            "width",
+            "height",
+            "innerR",
+            "anchorX",
+            "anchorY",
+            "clockwise",
+          ].forEach(function (key) {
+            wrapper[key] = pick(hash[key], wrapper[key]);
+          });
+          wrapper.attr({
+            d: wrapper.renderer.symbols[wrapper.symbolName](
+              wrapper.x,
+              wrapper.y,
+              wrapper.width,
+              wrapper.height,
+              wrapper
+            ),
+          });
+        };
         /**
-         * Format a number and return a string based on input settings.
-         *
-         * @sample highcharts/members/highcharts-numberformat/
-         *         Custom number format
-         *
-         * @function Highcharts.numberFormat
-         *
-         * @param {number} number
-         *        The input number to format.
-         *
-         * @param {number} decimals
-         *        The amount of decimals. A value of -1 preserves the amount in the
-         *        input number.
-         *
-         * @param {string} [decimalPoint]
-         *        The decimal point, defaults to the one given in the lang options, or
-         *        a dot.
-         *
-         * @param {string} [thousandsSep]
-         *        The thousands separator, defaults to the one given in the lang
-         *        options, or a space character.
-         *
-         * @return {string}
-         *         The formatted number.
-         */
-        var numberFormat = H.numberFormat = function numberFormat(number,
-            decimals,
-            decimalPoint,
-            thousandsSep) {
-                number = +number || 0;
-            decimals = +decimals;
-            var lang = H.defaultOptions.lang, origDec = (number.toString().split('.')[1] || '').split('e')[0].length, strinteger, thousands, ret, roundedNumber, exponent = number.toString().split('e'), fractionDigits;
-            if (decimals === -1) {
-                // Preserve decimals. Not huge numbers (#3793).
-                decimals = Math.min(origDec, 20);
-            }
-            else if (!isNumber(decimals)) {
-                decimals = 2;
-            }
-            else if (decimals && exponent[1] && exponent[1] < 0) {
-                // Expose decimals from exponential notation (#7042)
-                fractionDigits = decimals + +exponent[1];
-                if (fractionDigits >= 0) {
-                    // remove too small part of the number while keeping the notation
-                    exponent[0] = (+exponent[0]).toExponential(fractionDigits)
-                        .split('e')[0];
-                    decimals = fractionDigits;
-                }
-                else {
-                    // fractionDigits < 0
-                    exponent[0] = exponent[0].split('.')[0] || 0;
-                    if (decimals < 20) {
-                        // use number instead of exponential notation (#7405)
-                        number = (exponent[0] * Math.pow(10, exponent[1]))
-                            .toFixed(decimals);
-                    }
-                    else {
-                        // or zero
-                        number = 0;
-                    }
-                    exponent[1] = 0;
-                }
-            }
-            // Add another decimal to avoid rounding errors of float numbers. (#4573)
-            // Then use toFixed to handle rounding.
-            roundedNumber = (Math.abs(exponent[1] ? exponent[0] : number) +
-                Math.pow(10, -Math.max(decimals, origDec) - 1)).toFixed(decimals);
-            // A string containing the positive integer component of the number
-            strinteger = String(pInt(roundedNumber));
-            // Leftover after grouping into thousands. Can be 0, 1 or 2.
-            thousands = strinteger.length > 3 ? strinteger.length % 3 : 0;
-            // Language
-            decimalPoint = pick(decimalPoint, lang.decimalPoint);
-            thousandsSep = pick(thousandsSep, lang.thousandsSep);
-            // Start building the return
-            ret = number < 0 ? '-' : '';
-            // Add the leftover after grouping into thousands. For example, in the
-            // number 42 000 000, this line adds 42.
-            ret += thousands ? strinteger.substr(0, thousands) + thousandsSep : '';
-            // Add the remaining thousands groups, joined by the thousands separator
-            ret += strinteger
-                .substr(thousands)
-                .replace(/(\d{3})(?=\d)/g, '$1' + thousandsSep);
-            // Add the decimal point and the decimal component
-            if (decimals) {
-                // Get the decimal component
-                ret += decimalPoint + roundedNumber.slice(-decimals);
-            }
-            if (exponent[1] && +ret !== 0) {
-                ret += 'e' + exponent[1];
+         * @private
+         * @function Highcharts.SVGElement#textSetter
+         * @param {string} value
+         */
+        SVGElement.prototype.textSetter = function (value) {
+          if (value !== this.textStr) {
+            // Delete size caches when the text changes
+            // delete this.bBox; // old code in series-label
+            delete this.textPxLength;
+            this.textStr = value;
+            if (this.added) {
+              this.renderer.buildText(this);
             }
-            return ret;
+          }
         };
         /**
-         * Easing definition
-         *
          * @private
-         * @function Math.easeInOutSine
+         * @function Highcharts.SVGElement#titleSetter
+         * @param {string} value
+         */
+        SVGElement.prototype.titleSetter = function (value) {
+          var titleNode = this.element.getElementsByTagName("title")[0];
+          if (!titleNode) {
+            titleNode = doc.createElementNS(this.SVG_NS, "title");
+            this.element.appendChild(titleNode);
+          }
+          // Remove text content if it exists
+          if (titleNode.firstChild) {
+            titleNode.removeChild(titleNode.firstChild);
+          }
+          titleNode.appendChild(
+            doc.createTextNode(
+              // #3276, #3895
+              String(pick(value, ""))
+                .replace(/<[^>]*>/g, "")
+                .replace(/&lt;/g, "<")
+                .replace(/&gt;/g, ">")
+            )
+          );
+        };
+        /**
+         * Bring the element to the front. Alternatively, a new zIndex can be set.
          *
-         * @param {number} pos
-         *        Current position, ranging from 0 to 1.
+         * @sample highcharts/members/element-tofront/
+         *         Click an element to bring it to front
          *
-         * @return {number}
-         *         Ease result
+         * @function Highcharts.SVGElement#toFront
+         *
+         * @return {Highcharts.SVGElement}
+         * Returns the SVGElement for chaining.
          */
-        Math.easeInOutSine = function (pos) {
-            return -0.5 * (Math.cos(Math.PI * pos) - 1);
+        SVGElement.prototype.toFront = function () {
+          var element = this.element;
+          element.parentNode.appendChild(element);
+          return this;
         };
         /**
-         * Returns the value of a property path on a given object.
+         * Move an object and its children by x and y values.
          *
-         * @private
-         * @function getNestedProperty
+         * @function Highcharts.SVGElement#translate
          *
-         * @param {string} path
-         * Path to the property, for example `custom.myValue`.
+         * @param {number} x
+         *        The x value.
          *
-         * @param {unknown} obj
-         * Instance containing the property on the specific path.
+         * @param {number} y
+         *        The y value.
          *
-         * @return {unknown}
-         * The unknown property value.
+         * @return {Highcharts.SVGElement}
          */
-        function getNestedProperty(path, obj) {
-            if (!path) {
-                return obj;
-            }
-            var pathElements = path.split('.').reverse();
-            var subProperty = obj;
-            if (pathElements.length === 1) {
-                return subProperty[path];
-            }
-            var pathElement = pathElements.pop();
-            while (typeof pathElement !== 'undefined' &&
-                typeof subProperty !== 'undefined' &&
-                subProperty !== null) {
-                subProperty = subProperty[pathElement];
-                pathElement = pathElements.pop();
-            }
-            return subProperty;
-        }
+        SVGElement.prototype.translate = function (x, y) {
+          return this.attr({
+            translateX: x,
+            translateY: y,
+          });
+        };
         /**
-         * Get the computed CSS value for given element and property, only for numerical
-         * properties. For width and height, the dimension of the inner box (excluding
-         * padding) is returned. Used for fitting the chart within the container.
+         * Update the shadow elements with new attributes.
          *
-         * @function Highcharts.getStyle
-         *
-         * @param {Highcharts.HTMLDOMElement} el
-         *        An HTML element.
+         * @private
+         * @function Highcharts.SVGElement#updateShadows
          *
-         * @param {string} prop
-         *        The property name.
+         * @param {string} key
+         * The attribute name.
          *
-         * @param {boolean} [toInt=true]
-         *        Parse to integer.
+         * @param {number} value
+         * The value of the attribute.
          *
-         * @return {number|string}
-         *         The numeric value.
+         * @param {Function} setter
+         * The setter function, inherited from the parent wrapper.
          */
-        var getStyle = H.getStyle = function (el,
-            prop,
-            toInt) {
-                var style;
-            // For width and height, return the actual inner pixel size (#4913)
-            if (prop === 'width') {
-                var offsetWidth = Math.min(el.offsetWidth,
-                    el.scrollWidth);
-                // In flex boxes, we need to use getBoundingClientRect and floor it,
-                // because scrollWidth doesn't support subpixel precision (#6427) ...
-                var boundingClientRectWidth = el.getBoundingClientRect &&
-                        el.getBoundingClientRect().width;
-                // ...unless if the containing div or its parents are transform-scaled
-                // down, in which case the boundingClientRect can't be used as it is
-                // also scaled down (#9871, #10498).
-                if (boundingClientRectWidth < offsetWidth &&
-                    boundingClientRectWidth >= offsetWidth - 1) {
-                    offsetWidth = Math.floor(boundingClientRectWidth);
-                }
-                return Math.max(0, // #8377
-                (offsetWidth -
-                    H.getStyle(el, 'padding-left') -
-                    H.getStyle(el, 'padding-right')));
-            }
-            if (prop === 'height') {
-                return Math.max(0, // #8377
-                Math.min(el.offsetHeight, el.scrollHeight) -
-                    H.getStyle(el, 'padding-top') -
-                    H.getStyle(el, 'padding-bottom'));
-            }
-            if (!win.getComputedStyle) {
-                // SVG not supported, forgot to load oldie.js?
-                error(27, true);
-            }
-            // Otherwise, get the computed style
-            style = win.getComputedStyle(el, undefined); // eslint-disable-line no-undefined
-            if (style) {
-                style = style.getPropertyValue(prop);
-                if (pick(toInt, prop !== 'opacity')) {
-                    style = pInt(style);
-                }
+        SVGElement.prototype.updateShadows = function (key, value, setter) {
+          var shadows = this.shadows;
+          if (shadows) {
+            var i = shadows.length;
+            while (i--) {
+              setter.call(
+                shadows[i],
+                key === "height"
+                  ? Math.max(value - (shadows[i].cutHeight || 0), 0)
+                  : key === "d"
+                  ? this.d
+                  : value,
+                key,
+                shadows[i]
+              );
             }
-            return style;
+          }
         };
         /**
-         * Search for an item in an array.
+         * Update the transform attribute based on internal properties. Deals with
+         * the custom `translateX`, `translateY`, `rotation`, `scaleX` and `scaleY`
+         * attributes and updates the SVG `transform` attribute.
          *
-         * @function Highcharts.inArray
-         *
-         * @deprecated
+         * @private
+         * @function Highcharts.SVGElement#updateTransform
+         */
+        SVGElement.prototype.updateTransform = function () {
+          var wrapper = this,
+            translateX = wrapper.translateX || 0,
+            translateY = wrapper.translateY || 0,
+            scaleX = wrapper.scaleX,
+            scaleY = wrapper.scaleY,
+            inverted = wrapper.inverted,
+            rotation = wrapper.rotation,
+            matrix = wrapper.matrix,
+            element = wrapper.element,
+            transform;
+          // Flipping affects translate as adjustment for flipping around the
+          // group's axis
+          if (inverted) {
+            translateX += wrapper.width;
+            translateY += wrapper.height;
+          }
+          // Apply translate. Nearly all transformed elements have translation,
+          // so instead of checking for translate = 0, do it always (#1767,
+          // #1846).
+          transform = ["translate(" + translateX + "," + translateY + ")"];
+          // apply matrix
+          if (defined(matrix)) {
+            transform.push("matrix(" + matrix.join(",") + ")");
+          }
+          // apply rotation
+          if (inverted) {
+            transform.push("rotate(90) scale(-1,1)");
+          } else if (rotation) {
+            // text rotation
+            transform.push(
+              "rotate(" +
+                rotation +
+                " " +
+                pick(this.rotationOriginX, element.getAttribute("x"), 0) +
+                " " +
+                pick(this.rotationOriginY, element.getAttribute("y") || 0) +
+                ")"
+            );
+          }
+          // apply scale
+          if (defined(scaleX) || defined(scaleY)) {
+            transform.push(
+              "scale(" + pick(scaleX, 1) + " " + pick(scaleY, 1) + ")"
+            );
+          }
+          if (transform.length) {
+            element.setAttribute("transform", transform.join(" "));
+          }
+        };
+        /**
+         * @private
+         * @function Highcharts.SVGElement#visibilitySetter
          *
-         * @param {*} item
-         *        The item to search for.
+         * @param {string} value
          *
-         * @param {Array<*>} arr
-         *        The array or node collection to search in.
+         * @param {string} key
          *
-         * @param {number} [fromIndex=0]
-         *        The index to start searching from.
+         * @param {Highcharts.SVGDOMElement} element
          *
-         * @return {number}
-         *         The index within the array, or -1 if not found.
+         * @return {void}
          */
-        var inArray = H.inArray = function (item,
-            arr,
-            fromIndex) {
-                error(32,
-            false,
-            void 0, { 'Highcharts.inArray': 'use Array.indexOf' });
-            return arr.indexOf(item, fromIndex);
+        SVGElement.prototype.visibilitySetter = function (value, key, element) {
+          // IE9-11 doesn't handle visibilty:inherit well, so we remove the
+          // attribute instead (#2881, #3909)
+          if (value === "inherit") {
+            element.removeAttribute(key);
+          } else if (this[key] !== value) {
+            // #6747
+            element.setAttribute(key, value);
+          }
+          this[key] = value;
         };
-        /* eslint-disable valid-jsdoc */
-        /**
-         * Return the value of the first element in the array that satisfies the
-         * provided testing function.
-         *
-         * @function Highcharts.find<T>
-         *
-         * @param {Array<T>} arr
-         *        The array to test.
-         *
-         * @param {Function} callback
-         *        The callback function. The function receives the item as the first
-         *        argument. Return `true` if this item satisfies the condition.
-         *
-         * @return {T|undefined}
-         *         The value of the element.
-         */
-        var find = H.find = Array.prototype.find ?
-                /* eslint-enable valid-jsdoc */
-                function (arr,
-            callback) {
-                    return arr.find(callback);
-            } :
-            // Legacy implementation. PhantomJS, IE <= 11 etc. #7223.
-            function (arr, callback) {
-                var i,
-                    length = arr.length;
-                for (i = 0; i < length; i++) {
-                    if (callback(arr[i], i)) { // eslint-disable-line callback-return
-                        return arr[i];
-                    }
-                }
-            };
         /**
-         * Returns an array of a given object's own properties.
-         *
-         * @function Highcharts.keys
-         * @deprecated
+         * @private
+         * @function Highcharts.SVGElement#xGetter
          *
-         * @param {*} obj
-         *        The object of which the properties are to be returned.
+         * @param {string} key
          *
-         * @return {Array<string>}
-         *         An array of strings that represents all the properties.
+         * @return {number|string|null}
          */
-        H.keys = function (obj) {
-            error(32, false, void 0, { 'Highcharts.keys': 'use Object.keys' });
-            return Object.keys(obj);
+        SVGElement.prototype.xGetter = function (key) {
+          if (this.element.nodeName === "circle") {
+            if (key === "x") {
+              key = "cx";
+            } else if (key === "y") {
+              key = "cy";
+            }
+          }
+          return this._defaultGetter(key);
         };
         /**
-         * Get the element's offset position, corrected for `overflow: auto`.
-         *
-         * @function Highcharts.offset
-         *
-         * @param {global.Element} el
-         *        The DOM element.
-         *
-         * @return {Highcharts.OffsetObject}
-         *         An object containing `left` and `top` properties for the position in
-         *         the page.
-         */
-        var offset = H.offset = function offset(el) {
-                var docElem = doc.documentElement,
-            box = (el.parentElement || el.parentNode) ?
-                    el.getBoundingClientRect() :
-                    { top: 0,
-            left: 0 };
-            return {
-                top: box.top + (win.pageYOffset || docElem.scrollTop) -
-                    (docElem.clientTop || 0),
-                left: box.left + (win.pageXOffset || docElem.scrollLeft) -
-                    (docElem.clientLeft || 0)
-            };
+         * @private
+         * @function Highcharts.SVGElement#zIndexSetter
+         * @param {number} [value]
+         * @param {string} [key]
+         * @return {boolean}
+         */
+        SVGElement.prototype.zIndexSetter = function (value, key) {
+          var renderer = this.renderer,
+            parentGroup = this.parentGroup,
+            parentWrapper = parentGroup || renderer,
+            parentNode = parentWrapper.element || renderer.box,
+            childNodes,
+            otherElement,
+            otherZIndex,
+            element = this.element,
+            inserted = false,
+            undefinedOtherZIndex,
+            svgParent = parentNode === renderer.box,
+            run = this.added,
+            i;
+          if (defined(value)) {
+            // So we can read it for other elements in the group
+            element.setAttribute("data-z-index", value);
+            value = +value;
+            if (this[key] === value) {
+              // Only update when needed (#3865)
+              run = false;
+            }
+          } else if (defined(this[key])) {
+            element.removeAttribute("data-z-index");
+          }
+          this[key] = value;
+          // Insert according to this and other elements' zIndex. Before .add() is
+          // called, nothing is done. Then on add, or by later calls to
+          // zIndexSetter, the node is placed on the right place in the DOM.
+          if (run) {
+            value = this.zIndex;
+            if (value && parentGroup) {
+              parentGroup.handleZ = true;
+            }
+            childNodes = parentNode.childNodes;
+            for (i = childNodes.length - 1; i >= 0 && !inserted; i--) {
+              otherElement = childNodes[i];
+              otherZIndex = otherElement.getAttribute("data-z-index");
+              undefinedOtherZIndex = !defined(otherZIndex);
+              if (otherElement !== element) {
+                if (
+                  // Negative zIndex versus no zIndex:
+                  // On all levels except the highest. If the parent is
+                  // <svg>, then we don't want to put items before <desc>
+                  // or <defs>
+                  value < 0 &&
+                  undefinedOtherZIndex &&
+                  !svgParent &&
+                  !i
+                ) {
+                  parentNode.insertBefore(element, childNodes[i]);
+                  inserted = true;
+                } else if (
+                  // Insert after the first element with a lower zIndex
+                  pInt(otherZIndex) <= value ||
+                  // If negative zIndex, add this before first undefined
+                  // zIndex element
+                  (undefinedOtherZIndex && (!defined(value) || value >= 0))
+                ) {
+                  parentNode.insertBefore(
+                    element,
+                    childNodes[i + 1] || null // null for oldIE export
+                  );
+                  inserted = true;
+                }
+              }
+            }
+            if (!inserted) {
+              parentNode.insertBefore(
+                element,
+                childNodes[svgParent ? 3 : 0] || null // null for oldIE
+              );
+              inserted = true;
+            }
+          }
+          return inserted;
         };
-        /* eslint-disable valid-jsdoc */
-        /**
-         * Iterate over object key pairs in an object.
-         *
-         * @function Highcharts.objectEach<T>
+        return SVGElement;
+      })();
+      // Some shared setters and getters
+      SVGElement.prototype["stroke-widthSetter"] =
+        SVGElement.prototype.strokeSetter;
+      SVGElement.prototype.yGetter = SVGElement.prototype.xGetter;
+      SVGElement.prototype.matrixSetter =
+        SVGElement.prototype.rotationOriginXSetter =
+        SVGElement.prototype.rotationOriginYSetter =
+        SVGElement.prototype.rotationSetter =
+        SVGElement.prototype.scaleXSetter =
+        SVGElement.prototype.scaleYSetter =
+        SVGElement.prototype.translateXSetter =
+        SVGElement.prototype.translateYSetter =
+        SVGElement.prototype.verticalAlignSetter =
+          function (value, key) {
+            this[key] = value;
+            this.doTransform = true;
+          };
+      H.SVGElement = SVGElement;
+
+      return H.SVGElement;
+    }
+  );
+  _registerModule(
+    _modules,
+    "Core/Renderer/SVG/SVGLabel.js",
+    [
+      _modules["Core/Renderer/SVG/SVGElement.js"],
+      _modules["Core/Utilities.js"],
+    ],
+    function (SVGElement, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      var __extends =
+        (this && this.__extends) ||
+        (function () {
+          var extendStatics = function (d, b) {
+            extendStatics =
+              Object.setPrototypeOf ||
+              ({ __proto__: [] } instanceof Array &&
+                function (d, b) {
+                  d.__proto__ = b;
+                }) ||
+              function (d, b) {
+                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+              };
+            return extendStatics(d, b);
+          };
+          return function (d, b) {
+            extendStatics(d, b);
+            function __() {
+              this.constructor = d;
+            }
+            d.prototype =
+              b === null
+                ? Object.create(b)
+                : ((__.prototype = b.prototype), new __());
+          };
+        })();
+      var defined = U.defined,
+        extend = U.extend,
+        isNumber = U.isNumber,
+        merge = U.merge,
+        removeEvent = U.removeEvent;
+      /**
+       * SVG label to render text.
+       * @private
+       * @class
+       * @name Highcharts.SVGLabel
+       * @augments Highcharts.SVGElement
+       */
+      var SVGLabel = /** @class */ (function (_super) {
+        __extends(SVGLabel, _super);
+        /* *
          *
-         * @param {*} obj
-         *        The object to iterate over.
+         *  Constructors
          *
-         * @param {Highcharts.ObjectEachCallbackFunction<T>} fn
-         *        The iterator callback. It passes three arguments:
-         *        * value - The property value.
-         *        * key - The property key.
-         *        * obj - The object that objectEach is being applied to.
+         * */
+        function SVGLabel(
+          renderer,
+          str,
+          x,
+          y,
+          shape,
+          anchorX,
+          anchorY,
+          useHTML,
+          baseline,
+          className
+        ) {
+          var _this = _super.call(this) || this;
+          _this.init(renderer, "g");
+          _this.textStr = str;
+          _this.x = x;
+          _this.y = y;
+          _this.anchorX = anchorX;
+          _this.anchorY = anchorY;
+          _this.baseline = baseline;
+          _this.className = className;
+          if (className !== "button") {
+            _this.addClass("highcharts-label");
+          }
+          if (className) {
+            _this.addClass("highcharts-" + className);
+          }
+          _this.text = renderer.text("", 0, 0, useHTML).attr({
+            zIndex: 1,
+          });
+          // Validate the shape argument
+          var hasBGImage;
+          if (typeof shape === "string") {
+            hasBGImage = /^url\((.*?)\)$/.test(shape);
+            if (_this.renderer.symbols[shape] || hasBGImage) {
+              _this.symbolKey = shape;
+            }
+          }
+          _this.bBox = SVGLabel.emptyBBox;
+          _this.padding = 3;
+          _this.paddingLeft = 0;
+          _this.baselineOffset = 0;
+          _this.needsBox = renderer.styledMode || hasBGImage;
+          _this.deferredAttr = {};
+          _this.alignFactor = 0;
+          return _this;
+        }
+        /* *
          *
-         * @param {T} [ctx]
-         *        The context.
+         *  Functions
          *
-         * @return {void}
-         */
-        var objectEach = H.objectEach = function objectEach(obj,
-            fn,
-            ctx) {
-                /* eslint-enable valid-jsdoc */
-                for (var key in obj) {
-                    if (Object.hasOwnProperty.call(obj,
-            key)) {
-                        fn.call(ctx || obj[key],
-            obj[key],
+         * */
+        SVGLabel.prototype.alignSetter = function (value) {
+          var alignFactor = {
+            left: 0,
+            center: 0.5,
+            right: 1,
+          }[value];
+          if (alignFactor !== this.alignFactor) {
+            this.alignFactor = alignFactor;
+            // Bounding box exists, means we're dynamically changing
+            if (this.bBox && isNumber(this.xSetting)) {
+              this.attr({ x: this.xSetting }); // #5134
+            }
+          }
+        };
+        SVGLabel.prototype.anchorXSetter = function (value, key) {
+          this.anchorX = value;
+          this.boxAttr(
             key,
-            obj);
-                }
+            Math.round(value) - this.getCrispAdjust() - this.xSetting
+          );
+        };
+        SVGLabel.prototype.anchorYSetter = function (value, key) {
+          this.anchorY = value;
+          this.boxAttr(key, value - this.ySetting);
+        };
+        /*
+         * Set a box attribute, or defer it if the box is not yet created
+         */
+        SVGLabel.prototype.boxAttr = function (key, value) {
+          if (this.box) {
+            this.box.attr(key, value);
+          } else {
+            this.deferredAttr[key] = value;
+          }
+        };
+        /*
+         * Pick up some properties and apply them to the text instead of the
+         * wrapper.
+         */
+        SVGLabel.prototype.css = function (styles) {
+          if (styles) {
+            var textStyles = {},
+              isWidth,
+              isFontStyle;
+            // Create a copy to avoid altering the original object
+            // (#537)
+            styles = merge(styles);
+            SVGLabel.textProps.forEach(function (prop) {
+              if (typeof styles[prop] !== "undefined") {
+                textStyles[prop] = styles[prop];
+                delete styles[prop];
+              }
+            });
+            this.text.css(textStyles);
+            isWidth = "width" in textStyles;
+            isFontStyle =
+              "fontSize" in textStyles || "fontWeight" in textStyles;
+            // Update existing text, box (#9400, #12163)
+            if (isWidth || isFontStyle) {
+              this.updateBoxSize();
+              // Keep updated (#9400, #12163)
+              if (isFontStyle) {
+                this.updateTextPadding();
+              }
             }
+          }
+          return SVGElement.prototype.css.call(this, styles);
         };
-        /**
-         * Iterate over an array.
-         *
-         * @deprecated
-         * @function Highcharts.each
+        /*
+         * Destroy and release memory.
+         */
+        SVGLabel.prototype.destroy = function () {
+          // Added by button implementation
+          removeEvent(this.element, "mouseenter");
+          removeEvent(this.element, "mouseleave");
+          if (this.text) {
+            this.text.destroy();
+          }
+          if (this.box) {
+            this.box = this.box.destroy();
+          }
+          // Call base implementation to destroy the rest
+          SVGElement.prototype.destroy.call(this);
+          return void 0;
+        };
+        SVGLabel.prototype.fillSetter = function (value, key) {
+          if (value) {
+            this.needsBox = true;
+          }
+          // for animation getter (#6776)
+          this.fill = value;
+          this.boxAttr(key, value);
+        };
+        /*
+         * Return the bounding box of the box, not the group.
+         */
+        SVGLabel.prototype.getBBox = function () {
+          var bBox = this.bBox;
+          var padding = this.padding;
+          return {
+            width: bBox.width + 2 * padding,
+            height: bBox.height + 2 * padding,
+            x: bBox.x - padding,
+            y: bBox.y - padding,
+          };
+        };
+        SVGLabel.prototype.getCrispAdjust = function () {
+          return this.renderer.styledMode && this.box
+            ? (this.box.strokeWidth() % 2) / 2
+            : ((this["stroke-width"] ? parseInt(this["stroke-width"], 10) : 0) %
+                2) /
+                2;
+        };
+        SVGLabel.prototype.heightSetter = function (value) {
+          this.heightSetting = value;
+        };
+        // Event handling. In case of useHTML, we need to make sure that events
+        // are captured on the span as well, and that mouseenter/mouseleave
+        // between the SVG group and the HTML span are not treated as real
+        // enter/leave events. #13310.
+        SVGLabel.prototype.on = function (eventType, handler) {
+          var label = this;
+          var text = label.text;
+          var span = text && text.element.tagName === "SPAN" ? text : void 0;
+          var selectiveHandler;
+          if (span) {
+            selectiveHandler = function (e) {
+              if (
+                (eventType === "mouseenter" || eventType === "mouseleave") &&
+                e.relatedTarget instanceof Element &&
+                (label.element.contains(e.relatedTarget) ||
+                  span.element.contains(e.relatedTarget))
+              ) {
+                return;
+              }
+              handler.call(label.element, e);
+            };
+            span.on(eventType, selectiveHandler);
+          }
+          SVGElement.prototype.on.call(
+            label,
+            eventType,
+            selectiveHandler || handler
+          );
+          return label;
+        };
+        /*
+         * After the text element is added, get the desired size of the border
+         * box and add it before the text in the DOM.
+         */
+        SVGLabel.prototype.onAdd = function () {
+          var str = this.textStr;
+          this.text.add(this);
+          this.attr({
+            // Alignment is available now  (#3295, 0 not rendered if given
+            // as a value)
+            text: defined(str) ? str : "",
+            x: this.x,
+            y: this.y,
+          });
+          if (this.box && defined(this.anchorX)) {
+            this.attr({
+              anchorX: this.anchorX,
+              anchorY: this.anchorY,
+            });
+          }
+        };
+        SVGLabel.prototype.paddingSetter = function (value) {
+          if (defined(value) && value !== this.padding) {
+            this.padding = value;
+            this.updateTextPadding();
+          }
+        };
+        SVGLabel.prototype.paddingLeftSetter = function (value) {
+          if (defined(value) && value !== this.paddingLeft) {
+            this.paddingLeft = value;
+            this.updateTextPadding();
+          }
+        };
+        SVGLabel.prototype.rSetter = function (value, key) {
+          this.boxAttr(key, value);
+        };
+        SVGLabel.prototype.shadow = function (b) {
+          if (b && !this.renderer.styledMode) {
+            this.updateBoxSize();
+            if (this.box) {
+              this.box.shadow(b);
+            }
+          }
+          return this;
+        };
+        SVGLabel.prototype.strokeSetter = function (value, key) {
+          // for animation getter (#6776)
+          this.stroke = value;
+          this.boxAttr(key, value);
+        };
+        SVGLabel.prototype["stroke-widthSetter"] = function (value, key) {
+          if (value) {
+            this.needsBox = true;
+          }
+          this["stroke-width"] = value;
+          this.boxAttr(key, value);
+        };
+        SVGLabel.prototype["text-alignSetter"] = function (value) {
+          this.textAlign = value;
+        };
+        SVGLabel.prototype.textSetter = function (text) {
+          if (typeof text !== "undefined") {
+            // Must use .attr to ensure transforms are done (#10009)
+            this.text.attr({ text: text });
+          }
+          this.updateBoxSize();
+          this.updateTextPadding();
+        };
+        /*
+         * This function runs after the label is added to the DOM (when the bounding
+         * box is available), and after the text of the label is updated to detect
+         * the new bounding box and reflect it in the border box.
+         */
+        SVGLabel.prototype.updateBoxSize = function () {
+          var style = this.text.element.style,
+            crispAdjust,
+            attribs = {};
+          var padding = this.padding;
+          var paddingLeft = this.paddingLeft;
+          // #12165 error when width is null (auto)
+          // #12163 when fontweight: bold, recalculate bBox withot cache
+          // #3295 && 3514 box failure when string equals 0
+          var bBox =
+            (!isNumber(this.widthSetting) ||
+              !isNumber(this.heightSetting) ||
+              this.textAlign) &&
+            defined(this.text.textStr)
+              ? this.text.getBBox()
+              : SVGLabel.emptyBBox;
+          this.width =
+            (this.widthSetting || bBox.width || 0) + 2 * padding + paddingLeft;
+          this.height = (this.heightSetting || bBox.height || 0) + 2 * padding;
+          // Update the label-scoped y offset. Math.min because of inline
+          // style (#9400)
+          this.baselineOffset =
+            padding +
+            Math.min(
+              this.renderer.fontMetrics(style && style.fontSize, this.text).b,
+              // When the height is 0, there is no bBox, so go with the font
+              // metrics. Highmaps CSS demos.
+              bBox.height || Infinity
+            );
+          if (this.needsBox) {
+            // Create the border box if it is not already present
+            if (!this.box) {
+              // Symbol definition exists (#5324)
+              var box = (this.box = this.symbolKey
+                ? this.renderer.symbol(this.symbolKey)
+                : this.renderer.rect());
+              box.addClass(
+                // Don't use label className for buttons
+                (this.className === "button" ? "" : "highcharts-label-box") +
+                  (this.className
+                    ? " highcharts-" + this.className + "-box"
+                    : "")
+              );
+              box.add(this);
+              crispAdjust = this.getCrispAdjust();
+              attribs.x = crispAdjust;
+              attribs.y =
+                (this.baseline ? -this.baselineOffset : 0) + crispAdjust;
+            }
+            // Apply the box attributes
+            attribs.width = Math.round(this.width);
+            attribs.height = Math.round(this.height);
+            this.box.attr(extend(attribs, this.deferredAttr));
+            this.deferredAttr = {};
+          }
+          this.bBox = bBox;
+        };
+        /*
+         * This function runs after setting text or padding, but only if padding
+         * is changed.
+         */
+        SVGLabel.prototype.updateTextPadding = function () {
+          var text = this.text;
+          // Determine y based on the baseline
+          var textY = this.baseline ? 0 : this.baselineOffset;
+          var textX = this.paddingLeft + this.padding;
+          // compensate for alignment
+          if (
+            defined(this.widthSetting) &&
+            this.bBox &&
+            (this.textAlign === "center" || this.textAlign === "right")
+          ) {
+            textX +=
+              { center: 0.5, right: 1 }[this.textAlign] *
+              (this.widthSetting - this.bBox.width);
+          }
+          // update if anything changed
+          if (textX !== text.x || textY !== text.y) {
+            text.attr("x", textX);
+            // #8159 - prevent misplaced data labels in treemap
+            // (useHTML: true)
+            if (text.hasBoxWidthChanged) {
+              this.bBox = text.getBBox(true);
+              this.updateBoxSize();
+            }
+            if (typeof textY !== "undefined") {
+              text.attr("y", textY);
+            }
+          }
+          // record current values
+          text.x = textX;
+          text.y = textY;
+        };
+        SVGLabel.prototype.widthSetter = function (value) {
+          // width:auto => null
+          this.widthSetting = isNumber(value) ? value : void 0;
+        };
+        SVGLabel.prototype.xSetter = function (value) {
+          this.x = value; // for animation getter
+          if (this.alignFactor) {
+            value -=
+              this.alignFactor *
+              ((this.widthSetting || this.bBox.width) + 2 * this.padding);
+            // Force animation even when setting to the same value (#7898)
+            this["forceAnimate:x"] = true;
+          }
+          this.xSetting = Math.round(value);
+          this.attr("translateX", this.xSetting);
+        };
+        SVGLabel.prototype.ySetter = function (value) {
+          this.ySetting = this.y = Math.round(value);
+          this.attr("translateY", this.ySetting);
+        };
+        /* *
          *
-         * @param {Array<*>} arr
-         *        The array to iterate over.
+         *  Static Properties
          *
-         * @param {Function} fn
-         *        The iterator callback. It passes three arguments:
-         *        - `item`: The array item.
-         *        - `index`: The item's index in the array.
-         *        - `arr`: The array that each is being applied to.
+         * */
+        SVGLabel.emptyBBox = { width: 0, height: 0, x: 0, y: 0 };
+        /* *
          *
-         * @param {*} [ctx]
-         *        The context.
+         *  Properties
          *
-         * @return {void}
-         */
+         * */
         /**
-         * Filter an array by a callback.
+         * For labels, these CSS properties are applied to the `text` node directly.
          *
-         * @deprecated
-         * @function Highcharts.grep
+         * @private
+         * @name Highcharts.SVGLabel#textProps
+         * @type {Array<string>}
+         */
+        SVGLabel.textProps = [
+          "color",
+          "cursor",
+          "direction",
+          "fontFamily",
+          "fontSize",
+          "fontStyle",
+          "fontWeight",
+          "lineHeight",
+          "textAlign",
+          "textDecoration",
+          "textOutline",
+          "textOverflow",
+          "width",
+        ];
+        return SVGLabel;
+      })(SVGElement);
+
+      return SVGLabel;
+    }
+  );
+  _registerModule(
+    _modules,
+    "Core/Renderer/SVG/SVGRenderer.js",
+    [
+      _modules["Core/Color/Color.js"],
+      _modules["Core/Globals.js"],
+      _modules["Core/Renderer/SVG/SVGElement.js"],
+      _modules["Core/Renderer/SVG/SVGLabel.js"],
+      _modules["Core/Utilities.js"],
+    ],
+    function (Color, H, SVGElement, SVGLabel, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      var addEvent = U.addEvent,
+        attr = U.attr,
+        createElement = U.createElement,
+        css = U.css,
+        defined = U.defined,
+        destroyObjectProperties = U.destroyObjectProperties,
+        extend = U.extend,
+        isArray = U.isArray,
+        isNumber = U.isNumber,
+        isObject = U.isObject,
+        isString = U.isString,
+        merge = U.merge,
+        objectEach = U.objectEach,
+        pick = U.pick,
+        pInt = U.pInt,
+        splat = U.splat,
+        uniqueKey = U.uniqueKey;
+      /**
+       * A clipping rectangle that can be applied to one or more {@link SVGElement}
+       * instances. It is instanciated with the {@link SVGRenderer#clipRect} function
+       * and applied with the {@link SVGElement#clip} function.
+       *
+       * @example
+       * var circle = renderer.circle(100, 100, 100)
+       *     .attr({ fill: 'red' })
+       *     .add();
+       * var clipRect = renderer.clipRect(100, 100, 100, 100);
+       *
+       * // Leave only the lower right quarter visible
+       * circle.clip(clipRect);
+       *
+       * @typedef {Highcharts.SVGElement} Highcharts.ClipRectElement
+       */
+      /**
+       * The font metrics.
+       *
+       * @interface Highcharts.FontMetricsObject
+       */ /**
+       * The baseline relative to the top of the box.
+       *
+       * @name Highcharts.FontMetricsObject#b
+       * @type {number}
+       */ /**
+       * The font size.
+       *
+       * @name Highcharts.FontMetricsObject#f
+       * @type {number}
+       */ /**
+       * The line height.
+       *
+       * @name Highcharts.FontMetricsObject#h
+       * @type {number}
+       */
+      /**
+       * An object containing `x` and `y` properties for the position of an element.
+       *
+       * @interface Highcharts.PositionObject
+       */ /**
+       * X position of the element.
+       * @name Highcharts.PositionObject#x
+       * @type {number}
+       */ /**
+       * Y position of the element.
+       * @name Highcharts.PositionObject#y
+       * @type {number}
+       */
+      /**
+       * A rectangle.
+       *
+       * @interface Highcharts.RectangleObject
+       */ /**
+       * Height of the rectangle.
+       * @name Highcharts.RectangleObject#height
+       * @type {number}
+       */ /**
+       * Width of the rectangle.
+       * @name Highcharts.RectangleObject#width
+       * @type {number}
+       */ /**
+       * Horizontal position of the rectangle.
+       * @name Highcharts.RectangleObject#x
+       * @type {number}
+       */ /**
+       * Vertical position of the rectangle.
+       * @name Highcharts.RectangleObject#y
+       * @type {number}
+       */
+      /**
+       * The shadow options.
+       *
+       * @interface Highcharts.ShadowOptionsObject
+       */ /**
+       * The shadow color.
+       * @name    Highcharts.ShadowOptionsObject#color
+       * @type    {Highcharts.ColorString|undefined}
+       * @default #000000
+       */ /**
+       * The horizontal offset from the element.
+       *
+       * @name    Highcharts.ShadowOptionsObject#offsetX
+       * @type    {number|undefined}
+       * @default 1
+       */ /**
+       * The vertical offset from the element.
+       * @name    Highcharts.ShadowOptionsObject#offsetY
+       * @type    {number|undefined}
+       * @default 1
+       */ /**
+       * The shadow opacity.
+       *
+       * @name    Highcharts.ShadowOptionsObject#opacity
+       * @type    {number|undefined}
+       * @default 0.15
+       */ /**
+       * The shadow width or distance from the element.
+       * @name    Highcharts.ShadowOptionsObject#width
+       * @type    {number|undefined}
+       * @default 3
+       */
+      /**
+       * @interface Highcharts.SizeObject
+       */ /**
+       * @name Highcharts.SizeObject#height
+       * @type {number}
+       */ /**
+       * @name Highcharts.SizeObject#width
+       * @type {number}
+       */
+      /**
+       * Serialized form of an SVG definition, including children. Some key
+       * property names are reserved: tagName, textContent, and children.
+       *
+       * @interface Highcharts.SVGDefinitionObject
+       */ /**
+       * @name Highcharts.SVGDefinitionObject#[key:string]
+       * @type {boolean|number|string|Array<Highcharts.SVGDefinitionObject>|undefined}
+       */ /**
+       * @name Highcharts.SVGDefinitionObject#children
+       * @type {Array<Highcharts.SVGDefinitionObject>|undefined}
+       */ /**
+       * @name Highcharts.SVGDefinitionObject#tagName
+       * @type {string|undefined}
+       */ /**
+       * @name Highcharts.SVGDefinitionObject#textContent
+       * @type {string|undefined}
+       */
+      /**
+       * Array of path commands, that will go into the `d` attribute of an SVG
+       * element.
+       *
+       * @typedef {Array<(Array<Highcharts.SVGPathCommand>|Array<Highcharts.SVGPathCommand,number>|Array<Highcharts.SVGPathCommand,number,number>|Array<Highcharts.SVGPathCommand,number,number,number,number>|Array<Highcharts.SVGPathCommand,number,number,number,number,number,number>|Array<Highcharts.SVGPathCommand,number,number,number,number,number,number,number>)>} Highcharts.SVGPathArray
+       */
+      /**
+       * Possible path commands in an SVG path array. Valid values are `A`, `C`, `H`,
+       * `L`, `M`, `Q`, `S`, `T`, `V`, `Z`.
+       *
+       * @typedef {string} Highcharts.SVGPathCommand
+       * @validvalue ["a","c","h","l","m","q","s","t","v","z","A","C","H","L","M","Q","S","T","V","Z"]
+       */
+      /**
+       * An extendable collection of functions for defining symbol paths. Symbols are
+       * used internally for point markers, button and label borders and backgrounds,
+       * or custom shapes. Extendable by adding to {@link SVGRenderer#symbols}.
+       *
+       * @interface Highcharts.SymbolDictionary
+       */ /**
+       * @name Highcharts.SymbolDictionary#[key:string]
+       * @type {Function|undefined}
+       */ /**
+       * @name Highcharts.SymbolDictionary#arc
+       * @type {Function|undefined}
+       */ /**
+       * @name Highcharts.SymbolDictionary#callout
+       * @type {Function|undefined}
+       */ /**
+       * @name Highcharts.SymbolDictionary#circle
+       * @type {Function|undefined}
+       */ /**
+       * @name Highcharts.SymbolDictionary#diamond
+       * @type {Function|undefined}
+       */ /**
+       * @name Highcharts.SymbolDictionary#square
+       * @type {Function|undefined}
+       */ /**
+       * @name Highcharts.SymbolDictionary#triangle
+       * @type {Function|undefined}
+       */
+      /**
+       * Can be one of `arc`, `callout`, `circle`, `diamond`, `square`, `triangle`,
+       * and `triangle-down`. Symbols are used internally for point markers, button
+       * and label borders and backgrounds, or custom shapes. Extendable by adding to
+       * {@link SVGRenderer#symbols}.
+       *
+       * @typedef {"arc"|"callout"|"circle"|"diamond"|"square"|"triangle"|"triangle-down"} Highcharts.SymbolKeyValue
+       */
+      /**
+       * Additional options, depending on the actual symbol drawn.
+       *
+       * @interface Highcharts.SymbolOptionsObject
+       */ /**
+       * The anchor X position for the `callout` symbol. This is where the chevron
+       * points to.
+       *
+       * @name Highcharts.SymbolOptionsObject#anchorX
+       * @type {number|undefined}
+       */ /**
+       * The anchor Y position for the `callout` symbol. This is where the chevron
+       * points to.
+       *
+       * @name Highcharts.SymbolOptionsObject#anchorY
+       * @type {number|undefined}
+       */ /**
+       * The end angle of an `arc` symbol.
+       *
+       * @name Highcharts.SymbolOptionsObject#end
+       * @type {number|undefined}
+       */ /**
+       * Whether to draw `arc` symbol open or closed.
+       *
+       * @name Highcharts.SymbolOptionsObject#open
+       * @type {boolean|undefined}
+       */ /**
+       * The radius of an `arc` symbol, or the border radius for the `callout` symbol.
+       *
+       * @name Highcharts.SymbolOptionsObject#r
+       * @type {number|undefined}
+       */ /**
+       * The start angle of an `arc` symbol.
+       *
+       * @name Highcharts.SymbolOptionsObject#start
+       * @type {number|undefined}
+       */
+      /* eslint-disable no-invalid-this, valid-jsdoc */
+      var charts = H.charts,
+        deg2rad = H.deg2rad,
+        doc = H.doc,
+        isFirefox = H.isFirefox,
+        isMS = H.isMS,
+        isWebKit = H.isWebKit,
+        noop = H.noop,
+        svg = H.svg,
+        SVG_NS = H.SVG_NS,
+        symbolSizes = H.symbolSizes,
+        win = H.win;
+      /**
+       * Allows direct access to the Highcharts rendering layer in order to draw
+       * primitive shapes like circles, rectangles, paths or text directly on a chart,
+       * or independent from any chart. The SVGRenderer represents a wrapper object
+       * for SVG in modern browsers. Through the VMLRenderer, part of the `oldie.js`
+       * module, it also brings vector graphics to IE <= 8.
+       *
+       * An existing chart's renderer can be accessed through {@link Chart.renderer}.
+       * The renderer can also be used completely decoupled from a chart.
+       *
+       * @sample highcharts/members/renderer-on-chart
+       *         Annotating a chart programmatically.
+       * @sample highcharts/members/renderer-basic
+       *         Independent SVG drawing.
+       *
+       * @example
+       * // Use directly without a chart object.
+       * var renderer = new Highcharts.Renderer(parentNode, 600, 400);
+       *
+       * @class
+       * @name Highcharts.SVGRenderer
+       *
+       * @param {Highcharts.HTMLDOMElement} container
+       *        Where to put the SVG in the web page.
+       *
+       * @param {number} width
+       *        The width of the SVG.
+       *
+       * @param {number} height
+       *        The height of the SVG.
+       *
+       * @param {Highcharts.CSSObject} [style]
+       *        The box style, if not in styleMode
+       *
+       * @param {boolean} [forExport=false]
+       *        Whether the rendered content is intended for export.
+       *
+       * @param {boolean} [allowHTML=true]
+       *        Whether the renderer is allowed to include HTML text, which will be
+       *        projected on top of the SVG.
+       *
+       * @param {boolean} [styledMode=false]
+       *        Whether the renderer belongs to a chart that is in styled mode.
+       *        If it does, it will avoid setting presentational attributes in
+       *        some cases, but not when set explicitly through `.attr` and `.css`
+       *        etc.
+       */
+      var SVGRenderer = /** @class */ (function () {
+        /* *
          *
-         * @param {Array<*>} arr
-         *        The array to filter.
+         *  Constructors
+         *
+         * */
+        function SVGRenderer(
+          container,
+          width,
+          height,
+          style,
+          forExport,
+          allowHTML,
+          styledMode
+        ) {
+          /* *
+           *
+           *  Properties
+           *
+           * */
+          this.alignedObjects = void 0;
+          /**
+           * The root `svg` node of the renderer.
+           *
+           * @name Highcharts.SVGRenderer#box
+           * @type {Highcharts.SVGDOMElement}
+           */
+          this.box = void 0;
+          /**
+           * The wrapper for the root `svg` node of the renderer.
+           *
+           * @name Highcharts.SVGRenderer#boxWrapper
+           * @type {Highcharts.SVGElement}
+           */
+          this.boxWrapper = void 0;
+          this.cache = void 0;
+          this.cacheKeys = void 0;
+          this.chartIndex = void 0;
+          /**
+           * A pointer to the `defs` node of the root SVG.
+           *
+           * @name Highcharts.SVGRenderer#defs
+           * @type {Highcharts.SVGElement}
+           */
+          this.defs = void 0;
+          this.globalAnimation = void 0;
+          this.gradients = void 0;
+          this.height = void 0;
+          this.imgCount = void 0;
+          this.isSVG = void 0;
+          this.style = void 0;
+          /**
+           * Page url used for internal references.
+           *
+           * @private
+           * @name Highcharts.SVGRenderer#url
+           * @type {string}
+           */
+          this.url = void 0;
+          this.width = void 0;
+          this.init(
+            container,
+            width,
+            height,
+            style,
+            forExport,
+            allowHTML,
+            styledMode
+          );
+        }
+        /* *
          *
-         * @param {Function} callback
-         *        The callback function. The function receives the item as the first
-         *        argument. Return `true` if the item is to be preserved.
+         *  Functions
          *
-         * @return {Array<*>}
-         *         A new, filtered array.
-         */
+         * */
         /**
-         * Map an array by a callback.
+         * Initialize the SVGRenderer. Overridable initializer function that takes
+         * the same parameters as the constructor.
          *
-         * @deprecated
-         * @function Highcharts.map
-         *
-         * @param {Array<*>} arr
-         *        The array to map.
+         * @function Highcharts.SVGRenderer#init
          *
-         * @param {Function} fn
-         *        The callback function. Return the new value for the new array.
+         * @param {Highcharts.HTMLDOMElement} container
+         * Where to put the SVG in the web page.
          *
-         * @return {Array<*>}
-         *         A new array item with modified items.
-         */
-        /**
-         * Reduce an array to a single value.
+         * @param {number} width
+         * The width of the SVG.
          *
-         * @deprecated
-         * @function Highcharts.reduce
+         * @param {number} height
+         * The height of the SVG.
          *
-         * @param {Array<*>} arr
-         *        The array to reduce.
+         * @param {Highcharts.CSSObject} [style]
+         * The box style, if not in styleMode
          *
-         * @param {Function} fn
-         *        The callback function. Return the reduced value. Receives 4
-         *        arguments: Accumulated/reduced value, current value, current array
-         *        index, and the array.
+         * @param {boolean} [forExport=false]
+         * Whether the rendered content is intended for export.
          *
-         * @param {*} initialValue
-         *        The initial value of the accumulator.
+         * @param {boolean} [allowHTML=true]
+         * Whether the renderer is allowed to include HTML text, which will be
+         * projected on top of the SVG.
          *
-         * @return {*}
-         *         The reduced value.
-         */
+         * @param {boolean} [styledMode=false]
+         * Whether the renderer belongs to a chart that is in styled mode. If it
+         * does, it will avoid setting presentational attributes in some cases, but
+         * not when set explicitly through `.attr` and `.css` etc.
+         */
+        SVGRenderer.prototype.init = function (
+          container,
+          width,
+          height,
+          style,
+          forExport,
+          allowHTML,
+          styledMode
+        ) {
+          var renderer = this,
+            boxWrapper,
+            element,
+            desc;
+          boxWrapper = renderer.createElement("svg").attr({
+            version: "1.1",
+            class: "highcharts-root",
+          });
+          if (!styledMode) {
+            boxWrapper.css(this.getStyle(style));
+          }
+          element = boxWrapper.element;
+          container.appendChild(element);
+          // Always use ltr on the container, otherwise text-anchor will be
+          // flipped and text appear outside labels, buttons, tooltip etc (#3482)
+          attr(container, "dir", "ltr");
+          // For browsers other than IE, add the namespace attribute (#1978)
+          if (container.innerHTML.indexOf("xmlns") === -1) {
+            attr(element, "xmlns", this.SVG_NS);
+          }
+          // object properties
+          renderer.isSVG = true;
+          this.box = element;
+          this.boxWrapper = boxWrapper;
+          renderer.alignedObjects = [];
+          // #24, #672, #1070
+          this.url =
+            (isFirefox || isWebKit) && doc.getElementsByTagName("base").length
+              ? win.location.href
+                  .split("#")[0] // remove the hash
+                  .replace(/<[^>]*>/g, "") // wing cut HTML
+                  // escape parantheses and quotes
+                  .replace(/([\('\)])/g, "\\$1")
+                  // replace spaces (needed for Safari only)
+                  .replace(/ /g, "%20")
+              : "";
+          // Add description
+          desc = this.createElement("desc").add();
+          desc.element.appendChild(
+            doc.createTextNode("Created with Highcharts 8.2.2")
+          );
+          renderer.defs = this.createElement("defs").add();
+          renderer.allowHTML = allowHTML;
+          renderer.forExport = forExport;
+          renderer.styledMode = styledMode;
+          renderer.gradients = {}; // Object where gradient SvgElements are stored
+          renderer.cache = {}; // Cache for numerical bounding boxes
+          renderer.cacheKeys = [];
+          renderer.imgCount = 0;
+          renderer.setSize(width, height, false);
+          // Issue 110 workaround:
+          // In Firefox, if a div is positioned by percentage, its pixel position
+          // may land between pixels. The container itself doesn't display this,
+          // but an SVG element inside this container will be drawn at subpixel
+          // precision. In order to draw sharp lines, this must be compensated
+          // for. This doesn't seem to work inside iframes though (like in
+          // jsFiddle).
+          var subPixelFix, rect;
+          if (isFirefox && container.getBoundingClientRect) {
+            subPixelFix = function () {
+              css(container, { left: 0, top: 0 });
+              rect = container.getBoundingClientRect();
+              css(container, {
+                left: Math.ceil(rect.left) - rect.left + "px",
+                top: Math.ceil(rect.top) - rect.top + "px",
+              });
+            };
+            // run the fix now
+            subPixelFix();
+            // run it on resize
+            renderer.unSubPixelFix = addEvent(win, "resize", subPixelFix);
+          }
+        };
+        /**
+         * General method for adding a definition to the SVG `defs` tag. Can be used
+         * for gradients, fills, filters etc. Styled mode only. A hook for adding
+         * general definitions to the SVG's defs tag. Definitions can be referenced
+         * from the CSS by its `id`. Read more in
+         * [gradients, shadows and patterns](https://www.highcharts.com/docs/chart-design-and-style/gradients-shadows-and-patterns).
+         * Styled mode only.
+         *
+         * @function Highcharts.SVGRenderer#definition
+         *
+         * @param {Highcharts.SVGDefinitionObject} def
+         * A serialized form of an SVG definition, including children.
+         *
+         * @return {Highcharts.SVGElement}
+         * The inserted node.
+         */
+        SVGRenderer.prototype.definition = function (def) {
+          var ren = this;
+          /**
+           * @private
+           * @param {Highcharts.SVGDefinitionObject} config - SVG definition
+           * @param {Highcharts.SVGElement} [parent] - parent node
+           */
+          function recurse(config, parent) {
+            var ret;
+            splat(config).forEach(function (item) {
+              var node = ren.createElement(item.tagName),
+                attr = {};
+              // Set attributes
+              objectEach(item, function (val, key) {
+                if (
+                  key !== "tagName" &&
+                  key !== "children" &&
+                  key !== "textContent"
+                ) {
+                  attr[key] = val;
+                }
+              });
+              node.attr(attr);
+              // Add to the tree
+              node.add(parent || ren.defs);
+              // Add text content
+              if (item.textContent) {
+                node.element.appendChild(doc.createTextNode(item.textContent));
+              }
+              // Recurse
+              recurse(item.children || [], node);
+              ret = node;
+            });
+            // Return last node added (on top level it's the only one)
+            return ret;
+          }
+          return recurse(def);
+        };
         /**
-         * Test whether at least one element in the array passes the test implemented by
-         * the provided function.
+         * Get the global style setting for the renderer.
          *
-         * @deprecated
-         * @function Highcharts.some
+         * @private
+         * @function Highcharts.SVGRenderer#getStyle
          *
-         * @param {Array<*>} arr
-         *        The array to test
+         * @param {Highcharts.CSSObject} style
+         * Style settings.
          *
-         * @param {Function} fn
-         *        The function to run on each item. Return truty to pass the test.
-         *        Receives arguments `currentValue`, `index` and `array`.
+         * @return {Highcharts.CSSObject}
+         * The style settings mixed with defaults.
+         */
+        SVGRenderer.prototype.getStyle = function (style) {
+          this.style = extend(
+            {
+              fontFamily:
+                '"Lucida Grande", "Lucida Sans Unicode", ' +
+                "Arial, Helvetica, sans-serif",
+              fontSize: "12px",
+            },
+            style
+          );
+          return this.style;
+        };
+        /**
+         * Apply the global style on the renderer, mixed with the default styles.
          *
-         * @param {*} ctx
-         *        The context.
+         * @function Highcharts.SVGRenderer#setStyle
          *
-         * @return {boolean}
+         * @param {Highcharts.CSSObject} style
+         * CSS to apply.
          */
-        objectEach({
-            map: 'map',
-            each: 'forEach',
-            grep: 'filter',
-            reduce: 'reduce',
-            some: 'some'
-        }, function (val, key) {
-            H[key] = function (arr) {
-                var _a;
-                error(32, false, void 0, (_a = {}, _a["Highcharts." + key] = "use Array." + val, _a));
-                return Array.prototype[val].apply(arr, [].slice.call(arguments, 1));
-            };
-        });
-        /* eslint-disable valid-jsdoc */
+        SVGRenderer.prototype.setStyle = function (style) {
+          this.boxWrapper.css(this.getStyle(style));
+        };
         /**
-         * Add an event listener.
+         * Detect whether the renderer is hidden. This happens when one of the
+         * parent elements has `display: none`. Used internally to detect when we
+         * needto render preliminarily in another div to get the text bounding boxes
+         * right.
          *
-         * @function Highcharts.addEvent<T>
+         * @function Highcharts.SVGRenderer#isHidden
          *
-         * @param {Highcharts.Class<T>|T} el
-         *        The element or object to add a listener to. It can be a
-         *        {@link HTMLDOMElement}, an {@link SVGElement} or any other object.
-         *
-         * @param {string} type
-         *        The event type.
+         * @return {boolean}
+         * True if it is hidden.
+         */
+        SVGRenderer.prototype.isHidden = function () {
+          return !this.boxWrapper.getBBox().width;
+        };
+        /**
+         * Destroys the renderer and its allocated members.
+         *
+         * @function Highcharts.SVGRenderer#destroy
+         *
+         * @return {null}
+         */
+        SVGRenderer.prototype.destroy = function () {
+          var renderer = this,
+            rendererDefs = renderer.defs;
+          renderer.box = null;
+          renderer.boxWrapper = renderer.boxWrapper.destroy();
+          // Call destroy on all gradient elements
+          destroyObjectProperties(renderer.gradients || {});
+          renderer.gradients = null;
+          // Defs are null in VMLRenderer
+          // Otherwise, destroy them here.
+          if (rendererDefs) {
+            renderer.defs = rendererDefs.destroy();
+          }
+          // Remove sub pixel fix handler (#982)
+          if (renderer.unSubPixelFix) {
+            renderer.unSubPixelFix();
+          }
+          renderer.alignedObjects = null;
+          return null;
+        };
+        /**
+         * Create a wrapper for an SVG element. Serves as a factory for
+         * {@link SVGElement}, but this function is itself mostly called from
+         * primitive factories like {@link SVGRenderer#path}, {@link
+         * SVGRenderer#rect} or {@link SVGRenderer#text}.
          *
-         * @param {Highcharts.EventCallbackFunction<T>|Function} fn
-         *        The function callback to execute when the event is fired.
+         * @function Highcharts.SVGRenderer#createElement
          *
-         * @param {Highcharts.EventOptionsObject} [options]
-         *        Options for adding the event.
+         * @param {string} nodeName
+         * The node name, for example `rect`, `g` etc.
          *
-         * @return {Function}
-         *         A callback function to remove the added event.
+         * @return {Highcharts.SVGElement}
+         * The generated SVGElement.
          */
-        var addEvent = H.addEvent = function (el,
-            type,
-            fn,
-            options) {
-                if (options === void 0) { options = {}; }
-                /* eslint-enable valid-jsdoc */
-                var events,
-            addEventListener = (el.addEventListener || H.addEventListenerPolyfill);
-            // If we're setting events directly on the constructor, use a separate
-            // collection, `protoEvents` to distinguish it from the item events in
-            // `hcEvents`.
-            if (typeof el === 'function' && el.prototype) {
-                events = el.prototype.protoEvents = el.prototype.protoEvents || {};
-            }
-            else {
-                events = el.hcEvents = el.hcEvents || {};
-            }
-            // Allow click events added to points, otherwise they will be prevented by
-            // the TouchPointer.pinch function after a pinch zoom operation (#7091).
-            if (H.Point &&
-                el instanceof H.Point &&
-                el.series &&
-                el.series.chart) {
-                el.series.chart.runTrackerClick = true;
-            }
-            // Handle DOM events
-            if (addEventListener) {
-                addEventListener.call(el, type, fn, false);
-            }
-            if (!events[type]) {
-                events[type] = [];
-            }
-            var eventObject = {
-                    fn: fn,
-                    order: typeof options.order === 'number' ? options.order : Infinity
-                };
-            events[type].push(eventObject);
-            // Order the calls
-            events[type].sort(function (a, b) {
-                return a.order - b.order;
-            });
-            // Return a function that can be called to remove this event.
-            return function () {
-                removeEvent(el, type, fn);
-            };
+        SVGRenderer.prototype.createElement = function (nodeName) {
+          var wrapper = new this.Element();
+          wrapper.init(this, nodeName);
+          return wrapper;
         };
-        /* eslint-disable valid-jsdoc */
         /**
-         * Remove an event that was added with {@link Highcharts#addEvent}.
-         *
-         * @function Highcharts.removeEvent<T>
+         * Get converted radial gradient attributes according to the radial
+         * reference. Used internally from the {@link SVGElement#colorGradient}
+         * function.
          *
-         * @param {Highcharts.Class<T>|T} el
-         *        The element to remove events on.
+         * @private
+         * @function Highcharts.SVGRenderer#getRadialAttr
+         */
+        SVGRenderer.prototype.getRadialAttr = function (
+          radialReference,
+          gradAttr
+        ) {
+          return {
+            cx:
+              radialReference[0] -
+              radialReference[2] / 2 +
+              gradAttr.cx * radialReference[2],
+            cy:
+              radialReference[1] -
+              radialReference[2] / 2 +
+              gradAttr.cy * radialReference[2],
+            r: gradAttr.r * radialReference[2],
+          };
+        };
+        /**
+         * Truncate the text node contents to a given length. Used when the css
+         * width is set. If the `textOverflow` is `ellipsis`, the text is truncated
+         * character by character to the given length. If not, the text is
+         * word-wrapped line by line.
          *
-         * @param {string} [type]
-         *        The type of events to remove. If undefined, all events are removed
-         *        from the element.
+         * @private
+         * @function Highcharts.SVGRenderer#truncate
          *
-         * @param {Highcharts.EventCallbackFunction<T>} [fn]
-         *        The specific callback to remove. If undefined, all events that match
-         *        the element and optionally the type are removed.
+         * @return {boolean}
+         * True if tspan is too long.
+         */
+        SVGRenderer.prototype.truncate = function (
+          wrapper,
+          tspan,
+          text,
+          words,
+          startAt,
+          width,
+          getString
+        ) {
+          var renderer = this,
+            rotation = wrapper.rotation,
+            str,
+            // Word wrap can not be truncated to shorter than one word, ellipsis
+            // text can be completely blank.
+            minIndex = words ? 1 : 0,
+            maxIndex = (text || words).length,
+            currentIndex = maxIndex,
+            // Cache the lengths to avoid checking the same twice
+            lengths = [],
+            updateTSpan = function (s) {
+              if (tspan.firstChild) {
+                tspan.removeChild(tspan.firstChild);
+              }
+              if (s) {
+                tspan.appendChild(doc.createTextNode(s));
+              }
+            },
+            getSubStringLength = function (charEnd, concatenatedEnd) {
+              // charEnd is useed when finding the character-by-character
+              // break for ellipsis, concatenatedEnd is used for word-by-word
+              // break for word wrapping.
+              var end = concatenatedEnd || charEnd;
+              if (typeof lengths[end] === "undefined") {
+                // Modern browsers
+                if (tspan.getSubStringLength) {
+                  // Fails with DOM exception on unit-tests/legend/members
+                  // of unknown reason. Desired width is 0, text content
+                  // is "5" and end is 1.
+                  try {
+                    lengths[end] =
+                      startAt +
+                      tspan.getSubStringLength(0, words ? end + 1 : end);
+                  } catch (e) {
+                    ("");
+                  }
+                  // Legacy
+                } else if (renderer.getSpanWidth) {
+                  // #9058 jsdom
+                  updateTSpan(getString(text || words, charEnd));
+                  lengths[end] =
+                    startAt + renderer.getSpanWidth(wrapper, tspan);
+                }
+              }
+              return lengths[end];
+            },
+            actualWidth,
+            truncated;
+          wrapper.rotation = 0; // discard rotation when computing box
+          actualWidth = getSubStringLength(tspan.textContent.length);
+          truncated = startAt + actualWidth > width;
+          if (truncated) {
+            // Do a binary search for the index where to truncate the text
+            while (minIndex <= maxIndex) {
+              currentIndex = Math.ceil((minIndex + maxIndex) / 2);
+              // When checking words for word-wrap, we need to build the
+              // string and measure the subStringLength at the concatenated
+              // word length.
+              if (words) {
+                str = getString(words, currentIndex);
+              }
+              actualWidth = getSubStringLength(
+                currentIndex,
+                str && str.length - 1
+              );
+              if (minIndex === maxIndex) {
+                // Complete
+                minIndex = maxIndex + 1;
+              } else if (actualWidth > width) {
+                // Too large. Set max index to current.
+                maxIndex = currentIndex - 1;
+              } else {
+                // Within width. Set min index to current.
+                minIndex = currentIndex;
+              }
+            }
+            // If max index was 0 it means the shortest possible text was also
+            // too large. For ellipsis that means only the ellipsis, while for
+            // word wrap it means the whole first word.
+            if (maxIndex === 0) {
+              // Remove ellipsis
+              updateTSpan("");
+              // If the new text length is one less than the original, we don't
+              // need the ellipsis
+            } else if (!(text && maxIndex === text.length - 1)) {
+              updateTSpan(str || getString(text || words, currentIndex));
+            }
+          }
+          // When doing line wrapping, prepare for the next line by removing the
+          // items from this line.
+          if (words) {
+            words.splice(0, currentIndex);
+          }
+          wrapper.actualWidth = actualWidth;
+          wrapper.rotation = rotation; // Apply rotation again.
+          return truncated;
+        };
+        /**
+         * Parse a simple HTML string into SVG tspans. Called internally when text
+         * is set on an SVGElement. The function supports a subset of HTML tags, CSS
+         * text features like `width`, `text-overflow`, `white-space`, and also
+         * attributes like `href` and `style`.
          *
-         * @return {void}
-         */
-        var removeEvent = H.removeEvent = function removeEvent(el,
-            type,
-            fn) {
-                /* eslint-enable valid-jsdoc */
-                var events;
-            /**
-             * @private
-             * @param {string} type - event type
-             * @param {Highcharts.EventCallbackFunction<T>} fn - callback
-             * @return {void}
-             */
-            function removeOneEvent(type, fn) {
-                var removeEventListener = (el.removeEventListener || H.removeEventListenerPolyfill);
-                if (removeEventListener) {
-                    removeEventListener.call(el, type, fn, false);
-                }
+         * @private
+         * @function Highcharts.SVGRenderer#buildText
+         *
+         * @param {Highcharts.SVGElement} wrapper
+         * The parent SVGElement.
+         */
+        SVGRenderer.prototype.buildText = function (wrapper) {
+          var textNode = wrapper.element,
+            renderer = this,
+            forExport = renderer.forExport,
+            textStr = pick(wrapper.textStr, "").toString(),
+            hasMarkup = textStr.indexOf("<") !== -1,
+            lines,
+            childNodes = textNode.childNodes,
+            truncated,
+            parentX = attr(textNode, "x"),
+            textStyles = wrapper.styles,
+            width = wrapper.textWidth,
+            textLineHeight = textStyles && textStyles.lineHeight,
+            textOutline = textStyles && textStyles.textOutline,
+            ellipsis = textStyles && textStyles.textOverflow === "ellipsis",
+            noWrap = textStyles && textStyles.whiteSpace === "nowrap",
+            fontSize = textStyles && textStyles.fontSize,
+            textCache,
+            isSubsequentLine,
+            i = childNodes.length,
+            tempParent = width && !wrapper.added && this.box,
+            getLineHeight = function (tspan) {
+              var fontSizeStyle;
+              if (!renderer.styledMode) {
+                fontSizeStyle = /(px|em)$/.test(tspan && tspan.style.fontSize)
+                  ? tspan.style.fontSize
+                  : fontSize || renderer.style.fontSize || 12;
+              }
+              return textLineHeight
+                ? pInt(textLineHeight)
+                : renderer.fontMetrics(
+                    fontSizeStyle,
+                    // Get the computed size from parent if not explicit
+                    tspan.getAttribute("style") ? tspan : textNode
+                  ).h;
+            },
+            unescapeEntities = function (inputStr, except) {
+              objectEach(renderer.escapes, function (value, key) {
+                if (!except || except.indexOf(value) === -1) {
+                  inputStr = inputStr
+                    .toString()
+                    .replace(new RegExp(value, "g"), key);
+                }
+              });
+              return inputStr;
+            },
+            parseAttribute = function (s, attr) {
+              var start, delimiter;
+              start = s.indexOf("<");
+              s = s.substring(start, s.indexOf(">") - start);
+              start = s.indexOf(attr + "=");
+              if (start !== -1) {
+                start = start + attr.length + 1;
+                delimiter = s.charAt(start);
+                if (delimiter === '"' || delimiter === "'") {
+                  // eslint-disable-line quotes
+                  s = s.substring(start + 1);
+                  return s.substring(0, s.indexOf(delimiter));
+                }
+              }
+            };
+          var regexMatchBreaks = /<br.*?>/g;
+          // The buildText code is quite heavy, so if we're not changing something
+          // that affects the text, skip it (#6113).
+          textCache = [
+            textStr,
+            ellipsis,
+            noWrap,
+            textLineHeight,
+            textOutline,
+            fontSize,
+            width,
+          ].join(",");
+          if (textCache === wrapper.textCache) {
+            return;
+          }
+          wrapper.textCache = textCache;
+          // Remove old text
+          while (i--) {
+            textNode.removeChild(childNodes[i]);
+          }
+          // Skip tspans, add text directly to text node. The forceTSpan is a hook
+          // used in text outline hack.
+          if (
+            !hasMarkup &&
+            !textOutline &&
+            !ellipsis &&
+            !width &&
+            (textStr.indexOf(" ") === -1 ||
+              (noWrap && !regexMatchBreaks.test(textStr)))
+          ) {
+            textNode.appendChild(doc.createTextNode(unescapeEntities(textStr)));
+            // Complex strings, add more logic
+          } else {
+            if (tempParent) {
+              // attach it to the DOM to read offset width
+              tempParent.appendChild(textNode);
             }
-            /**
-             * @private
-             * @param {any} eventCollection - collection
-             * @return {void}
-             */
-            function removeAllEvents(eventCollection) {
-                var types,
-                    len;
-                if (!el.nodeName) {
-                    return; // break on non-DOM events
-                }
-                if (type) {
-                    types = {};
-                    types[type] = true;
-                }
-                else {
-                    types = eventCollection;
-                }
-                objectEach(types, function (_val, n) {
-                    if (eventCollection[n]) {
-                        len = eventCollection[n].length;
-                        while (len--) {
-                            removeOneEvent(n, eventCollection[n][len].fn);
-                        }
-                    }
-                });
+            if (hasMarkup) {
+              lines = renderer.styledMode
+                ? textStr
+                    .replace(
+                      /<(b|strong)>/g,
+                      '<span class="highcharts-strong">'
+                    )
+                    .replace(
+                      /<(i|em)>/g,
+                      '<span class="highcharts-emphasized">'
+                    )
+                : textStr
+                    .replace(/<(b|strong)>/g, '<span style="font-weight:bold">')
+                    .replace(/<(i|em)>/g, '<span style="font-style:italic">');
+              lines = lines
+                .replace(/<a/g, "<span")
+                .replace(/<\/(b|strong|i|em|a)>/g, "</span>")
+                .split(regexMatchBreaks);
+            } else {
+              lines = [textStr];
             }
-            ['protoEvents', 'hcEvents'].forEach(function (coll, i) {
-                var eventElem = i ? el : el.prototype;
-                var eventCollection = eventElem && eventElem[coll];
-                if (eventCollection) {
-                    if (type) {
-                        events = (eventCollection[type] || []);
-                        if (fn) {
-                            eventCollection[type] = events.filter(function (obj) {
-                                return fn !== obj.fn;
+            // Trim empty lines (#5261)
+            lines = lines.filter(function (line) {
+              return line !== "";
+            });
+            // build the lines
+            lines.forEach(function (line, lineNo) {
+              var spans,
+                spanNo = 0,
+                lineLength = 0;
+              line = line
+                // Trim to prevent useless/costly process on the spaces
+                // (#5258)
+                .replace(/^\s+|\s+$/g, "")
+                .replace(/<span/g, "|||<span")
+                .replace(/<\/span>/g, "</span>|||");
+              spans = line.split("|||");
+              spans.forEach(function buildTextSpans(span) {
+                if (span !== "" || spans.length === 1) {
+                  var attributes = {},
+                    tspan = doc.createElementNS(renderer.SVG_NS, "tspan"),
+                    a,
+                    classAttribute,
+                    styleAttribute, // #390
+                    hrefAttribute;
+                  classAttribute = parseAttribute(span, "class");
+                  if (classAttribute) {
+                    attr(tspan, "class", classAttribute);
+                  }
+                  styleAttribute = parseAttribute(span, "style");
+                  if (styleAttribute) {
+                    styleAttribute = styleAttribute.replace(
+                      /(;| |^)color([ :])/,
+                      "$1fill$2"
+                    );
+                    attr(tspan, "style", styleAttribute);
+                  }
+                  // For anchors, wrap the tspan in an <a> tag and apply
+                  // the href attribute as is (#13559). Not for export
+                  // (#1529)
+                  hrefAttribute = parseAttribute(span, "href");
+                  if (hrefAttribute && !forExport) {
+                    if (
+                      // Stop JavaScript links, vulnerable to XSS
+                      hrefAttribute
+                        .split(":")[0]
+                        .toLowerCase()
+                        .indexOf("javascript") === -1
+                    ) {
+                      a = doc.createElementNS(renderer.SVG_NS, "a");
+                      attr(a, "href", hrefAttribute);
+                      attr(tspan, "class", "highcharts-anchor");
+                      a.appendChild(tspan);
+                      if (!renderer.styledMode) {
+                        css(tspan, { cursor: "pointer" });
+                      }
+                    }
+                  }
+                  // Strip away unsupported HTML tags (#7126)
+                  span = unescapeEntities(
+                    span.replace(/<[a-zA-Z\/](.|\n)*?>/g, "") || " "
+                  );
+                  // Nested tags aren't supported, and cause crash in
+                  // Safari (#1596)
+                  if (span !== " ") {
+                    // add the text node
+                    tspan.appendChild(doc.createTextNode(span));
+                    // First span in a line, align it to the left
+                    if (!spanNo) {
+                      if (lineNo && parentX !== null) {
+                        attributes.x = parentX;
+                      }
+                    } else {
+                      attributes.dx = 0; // #16
+                    }
+                    // add attributes
+                    attr(tspan, attributes);
+                    // Append it
+                    textNode.appendChild(a || tspan);
+                    // first span on subsequent line, add the line
+                    // height
+                    if (!spanNo && isSubsequentLine) {
+                      // allow getting the right offset height in
+                      // exporting in IE
+                      if (!svg && forExport) {
+                        css(tspan, { display: "block" });
+                      }
+                      // Set the line height based on the font size of
+                      // either the text element or the tspan element
+                      attr(tspan, "dy", getLineHeight(tspan));
+                    }
+                    // Check width and apply soft breaks or ellipsis
+                    if (width) {
+                      var words = span.replace(/([^\^])-/g, "$1- ").split(" "), // #1273
+                        hasWhiteSpace =
+                          !noWrap &&
+                          (spans.length > 1 || lineNo || words.length > 1),
+                        wrapLineNo = 0,
+                        dy = getLineHeight(tspan);
+                      if (ellipsis) {
+                        truncated = renderer.truncate(
+                          wrapper,
+                          tspan,
+                          span,
+                          void 0,
+                          0,
+                          // Target width
+                          Math.max(
+                            0,
+                            // Substract the font face to make
+                            // room for the ellipsis itself
+                            width - parseInt(fontSize || 12, 10)
+                          ),
+                          // Build the text to test for
+                          function (text, currentIndex) {
+                            return text.substring(0, currentIndex) + "\u2026";
+                          }
+                        );
+                      } else if (hasWhiteSpace) {
+                        while (words.length) {
+                          // For subsequent lines, create tspans
+                          // with the same style attributes as the
+                          // parent text node.
+                          if (words.length && !noWrap && wrapLineNo > 0) {
+                            tspan = doc.createElementNS(SVG_NS, "tspan");
+                            attr(tspan, {
+                              dy: dy,
+                              x: parentX,
                             });
-                            removeOneEvent(type, fn);
-                        }
-                        else {
-                            removeAllEvents(eventCollection);
-                            eventCollection[type] = [];
+                            if (styleAttribute) {
+                              // #390
+                              attr(tspan, "style", styleAttribute);
+                            }
+                            // Start by appending the full
+                            // remaining text
+                            tspan.appendChild(
+                              doc.createTextNode(
+                                words.join(" ").replace(/- /g, "-")
+                              )
+                            );
+                            textNode.appendChild(tspan);
+                          }
+                          // For each line, truncate the remaining
+                          // words into the line length.
+                          renderer.truncate(
+                            wrapper,
+                            tspan,
+                            null,
+                            words,
+                            wrapLineNo === 0 ? lineLength : 0,
+                            width,
+                            // Build the text to test for
+                            function (text, currentIndex) {
+                              return words
+                                .slice(0, currentIndex)
+                                .join(" ")
+                                .replace(/- /g, "-");
+                            }
+                          );
+                          lineLength = wrapper.actualWidth;
+                          wrapLineNo++;
                         }
+                      }
                     }
-                    else {
-                        removeAllEvents(eventCollection);
-                        eventElem[coll] = {};
-                    }
+                    spanNo++;
+                  }
                 }
+              });
+              // To avoid beginning lines that doesn't add to the textNode
+              // (#6144)
+              isSubsequentLine = isSubsequentLine || textNode.childNodes.length;
             });
+            if (ellipsis && truncated) {
+              wrapper.attr(
+                "title",
+                unescapeEntities(wrapper.textStr || "", ["&lt;", "&gt;"]) // #7179
+              );
+            }
+            if (tempParent) {
+              tempParent.removeChild(textNode);
+            }
+            // Apply the text outline
+            if (isString(textOutline) && wrapper.applyTextOutline) {
+              wrapper.applyTextOutline(textOutline);
+            }
+          }
         };
-        /* eslint-disable valid-jsdoc */
         /**
-         * Fire an event that was registered with {@link Highcharts#addEvent}.
+         * Returns white for dark colors and black for bright colors.
          *
-         * @function Highcharts.fireEvent<T>
+         * @function Highcharts.SVGRenderer#getContrast
          *
-         * @param {T} el
-         *        The object to fire the event on. It can be a {@link HTMLDOMElement},
-         *        an {@link SVGElement} or any other object.
+         * @param {Highcharts.ColorString} rgba
+         * The color to get the contrast for.
          *
-         * @param {string} type
-         *        The type of event.
+         * @return {Highcharts.ColorString}
+         * The contrast color, either `#000000` or `#FFFFFF`.
+         */
+        SVGRenderer.prototype.getContrast = function (rgba) {
+          rgba = Color.parse(rgba).rgba;
+          // The threshold may be discussed. Here's a proposal for adding
+          // different weight to the color channels (#6216)
+          rgba[0] *= 1; // red
+          rgba[1] *= 1.2; // green
+          rgba[2] *= 0.5; // blue
+          return rgba[0] + rgba[1] + rgba[2] > 1.8 * 255
+            ? "#000000"
+            : "#FFFFFF";
+        };
+        /**
+         * Create a button with preset states.
          *
-         * @param {Highcharts.Dictionary<*>|Event} [eventArguments]
-         *        Custom event arguments that are passed on as an argument to the event
-         *        handler.
+         * @function Highcharts.SVGRenderer#button
          *
-         * @param {Highcharts.EventCallbackFunction<T>|Function} [defaultFunction]
-         *        The default function to execute if the other listeners haven't
-         *        returned false.
+         * @param {string} text
+         * The text or HTML to draw.
          *
-         * @return {void}
-         */
-        var fireEvent = H.fireEvent = function (el,
-            type,
-            eventArguments,
-            defaultFunction) {
-                /* eslint-enable valid-jsdoc */
-                var e,
-            i;
-            eventArguments = eventArguments || {};
-            if (doc.createEvent &&
-                (el.dispatchEvent || el.fireEvent)) {
-                e = doc.createEvent('Events');
-                e.initEvent(type, true, true);
-                extend(e, eventArguments);
-                if (el.dispatchEvent) {
-                    el.dispatchEvent(e);
-                }
-                else {
-                    el.fireEvent(type, e);
-                }
+         * @param {number} x
+         * The x position of the button's left side.
+         *
+         * @param {number} y
+         * The y position of the button's top side.
+         *
+         * @param {Highcharts.EventCallbackFunction<Highcharts.SVGElement>} callback
+         * The function to execute on button click or touch.
+         *
+         * @param {Highcharts.SVGAttributes} [normalState]
+         * SVG attributes for the normal state.
+         *
+         * @param {Highcharts.SVGAttributes} [hoverState]
+         * SVG attributes for the hover state.
+         *
+         * @param {Highcharts.SVGAttributes} [pressedState]
+         * SVG attributes for the pressed state.
+         *
+         * @param {Highcharts.SVGAttributes} [disabledState]
+         * SVG attributes for the disabled state.
+         *
+         * @param {Highcharts.SymbolKeyValue} [shape=rect]
+         * The shape type.
+         *
+         * @param {boolean} [useHTML=false]
+         * Wether to use HTML to render the label.
+         *
+         * @return {Highcharts.SVGElement}
+         * The button element.
+         */
+        SVGRenderer.prototype.button = function (
+          text,
+          x,
+          y,
+          callback,
+          normalState,
+          hoverState,
+          pressedState,
+          disabledState,
+          shape,
+          useHTML
+        ) {
+          var label = this.label(
+              text,
+              x,
+              y,
+              shape,
+              void 0,
+              void 0,
+              useHTML,
+              void 0,
+              "button"
+            ),
+            curState = 0,
+            styledMode = this.styledMode,
+            // Make a copy of normalState (#13798)
+            // (reference to options.rangeSelector.buttonTheme)
+            normalState = normalState ? merge(normalState) : normalState,
+            userNormalStyle = (normalState && normalState.style) || {};
+          // Remove stylable attributes
+          if (normalState && normalState.style) {
+            delete normalState.style;
+          }
+          // Default, non-stylable attributes
+          label.attr(merge({ padding: 8, r: 2 }, normalState));
+          if (!styledMode) {
+            // Presentational
+            var normalStyle, hoverStyle, pressedStyle, disabledStyle;
+            // Normal state - prepare the attributes
+            normalState = merge(
+              {
+                fill: "#f7f7f7",
+                stroke: "#cccccc",
+                "stroke-width": 1,
+                style: {
+                  color: "#333333",
+                  cursor: "pointer",
+                  fontWeight: "normal",
+                },
+              },
+              {
+                style: userNormalStyle,
+              },
+              normalState
+            );
+            normalStyle = normalState.style;
+            delete normalState.style;
+            // Hover state
+            hoverState = merge(
+              normalState,
+              {
+                fill: "#e6e6e6",
+              },
+              hoverState
+            );
+            hoverStyle = hoverState.style;
+            delete hoverState.style;
+            // Pressed state
+            pressedState = merge(
+              normalState,
+              {
+                fill: "#e6ebf5",
+                style: {
+                  color: "#000000",
+                  fontWeight: "bold",
+                },
+              },
+              pressedState
+            );
+            pressedStyle = pressedState.style;
+            delete pressedState.style;
+            // Disabled state
+            disabledState = merge(
+              normalState,
+              {
+                style: {
+                  color: "#cccccc",
+                },
+              },
+              disabledState
+            );
+            disabledStyle = disabledState.style;
+            delete disabledState.style;
+          }
+          // Add the events. IE9 and IE10 need mouseover and mouseout to funciton
+          // (#667).
+          addEvent(
+            label.element,
+            isMS ? "mouseover" : "mouseenter",
+            function () {
+              if (curState !== 3) {
+                label.setState(1);
+              }
             }
-            else {
-                if (!eventArguments.target) {
-                    // We're running a custom event
-                    extend(eventArguments, {
-                        // Attach a simple preventDefault function to skip
-                        // default handler if called. The built-in
-                        // defaultPrevented property is not overwritable (#5112)
-                        preventDefault: function () {
-                            eventArguments.defaultPrevented = true;
-                        },
-                        // Setting target to native events fails with clicking
-                        // the zoom-out button in Chrome.
-                        target: el,
-                        // If the type is not set, we're running a custom event
-                        // (#2297). If it is set, we're running a browser event,
-                        // and setting it will cause en error in IE8 (#2465).
-                        type: type
-                    });
-                }
-                var fireInOrder = function (protoEvents,
-                    hcEvents) {
-                        if (protoEvents === void 0) { protoEvents = []; }
-                        if (hcEvents === void 0) { hcEvents = []; }
-                        var iA = 0;
-                    var iB = 0;
-                    var length = protoEvents.length + hcEvents.length;
-                    for (i = 0; i < length; i++) {
-                        var obj = (!protoEvents[iA] ?
-                                hcEvents[iB++] :
-                                !hcEvents[iB] ?
-                                    protoEvents[iA++] :
-                                    protoEvents[iA].order <= hcEvents[iB].order ?
-                                        protoEvents[iA++] :
-                                        hcEvents[iB++]);
-                        // If the event handler return false, prevent the default
-                        // handler from executing
-                        if (obj.fn.call(el, eventArguments) === false) {
-                            eventArguments.preventDefault();
-                        }
-                    }
-                };
-                fireInOrder(el.protoEvents && el.protoEvents[type], el.hcEvents && el.hcEvents[type]);
+          );
+          addEvent(
+            label.element,
+            isMS ? "mouseout" : "mouseleave",
+            function () {
+              if (curState !== 3) {
+                label.setState(curState);
+              }
+            }
+          );
+          label.setState = function (state) {
+            // Hover state is temporary, don't record it
+            if (state !== 1) {
+              label.state = curState = state;
+            }
+            // Update visuals
+            label
+              .removeClass(/highcharts-button-(normal|hover|pressed|disabled)/)
+              .addClass(
+                "highcharts-button-" +
+                  ["normal", "hover", "pressed", "disabled"][state || 0]
+              );
+            if (!styledMode) {
+              label
+                .attr(
+                  [normalState, hoverState, pressedState, disabledState][
+                    state || 0
+                  ]
+                )
+                .css(
+                  [normalStyle, hoverStyle, pressedStyle, disabledStyle][
+                    state || 0
+                  ]
+                );
             }
-            // Run the default if not prevented
-            if (defaultFunction && !eventArguments.defaultPrevented) {
-                defaultFunction.call(el, eventArguments);
+          };
+          // Presentational attributes
+          if (!styledMode) {
+            label
+              .attr(normalState)
+              .css(extend({ cursor: "default" }, normalStyle));
+          }
+          return label.on("click", function (e) {
+            if (curState !== 3) {
+              callback.call(label, e);
             }
+          });
         };
-        var serialMode;
         /**
-         * Get a unique key for using in internal element id's and pointers. The key is
-         * composed of a random hash specific to this Highcharts instance, and a
-         * counter.
+         * Make a straight line crisper by not spilling out to neighbour pixels.
          *
-         * @example
-         * var id = uniqueKey(); // => 'highcharts-x45f6hp-0'
+         * @function Highcharts.SVGRenderer#crispLine
          *
-         * @function Highcharts.uniqueKey
+         * @param {Highcharts.SVGPathArray} points
+         *        The original points on the format `[['M', 0, 0], ['L', 100, 0]]`.
          *
-         * @return {string}
-         * A unique key.
-         */
-        var uniqueKey = H.uniqueKey = (function () {
-                var hash = Math.random().toString(36).substring(2, 9) + '-';
-            var id = 0;
-            return function () {
-                return 'highcharts-' + (serialMode ? '' : hash) + id++;
-            };
-        }());
+         * @param {number} width
+         *        The width of the line.
+         *
+         * @param {string} roundingFunction
+         *        The rounding function name on the `Math` object, can be one of
+         *        `round`, `floor` or `ceil`.
+         *
+         * @return {Highcharts.SVGPathArray}
+         *         The original points array, but modified to render crisply.
+         */
+        SVGRenderer.prototype.crispLine = function (
+          points,
+          width,
+          roundingFunction
+        ) {
+          if (roundingFunction === void 0) {
+            roundingFunction = "round";
+          }
+          var start = points[0];
+          var end = points[1];
+          // Normalize to a crisp line
+          if (start[1] === end[1]) {
+            // Substract due to #1129. Now bottom and left axis gridlines behave
+            // the same.
+            start[1] = end[1] =
+              Math[roundingFunction](start[1]) - (width % 2) / 2;
+          }
+          if (start[2] === end[2]) {
+            start[2] = end[2] =
+              Math[roundingFunction](start[2]) + (width % 2) / 2;
+          }
+          return points;
+        };
         /**
-         * Activates a serial mode for element IDs provided by
-         * {@link Highcharts.uniqueKey}. This mode can be used in automated tests, where
-         * a simple comparison of two rendered SVG graphics is needed.
+         * Draw a path, wraps the SVG `path` element.
          *
-         * **Note:** This is only for testing purposes and will break functionality in
-         * webpages with multiple charts.
+         * @sample highcharts/members/renderer-path-on-chart/
+         *         Draw a path in a chart
+         * @sample highcharts/members/renderer-path/
+         *         Draw a path independent from a chart
          *
          * @example
-         * if (
-         *   process &&
-         *   process.env.NODE_ENV === 'development'
-         * ) {
-         *   Highcharts.useSerialIds(true);
-         * }
+         * var path = renderer.path(['M', 10, 10, 'L', 30, 30, 'z'])
+         *     .attr({ stroke: '#ff00ff' })
+         *     .add();
          *
-         * @function Highcharts.useSerialIds
+         * @function Highcharts.SVGRenderer#path
          *
-         * @param {boolean} [mode]
-         * Changes the state of serial mode.
+         * @param {Highcharts.SVGPathArray} [path]
+         * An SVG path definition in array form.
          *
-         * @return {boolean|undefined}
-         * State of the serial mode.
-         */
-        var useSerialIds = H.useSerialIds = function (mode) {
-                return (serialMode = pick(mode,
-            serialMode));
-        };
-        var isFunction = H.isFunction = function (obj) {
-                return typeof obj === 'function';
+         * @return {Highcharts.SVGElement}
+         * The generated wrapper element.
+         *
+         */ /**
+         * Draw a path, wraps the SVG `path` element.
+         *
+         * @function Highcharts.SVGRenderer#path
+         *
+         * @param {Highcharts.SVGAttributes} [attribs]
+         * The initial attributes.
+         *
+         * @return {Highcharts.SVGElement}
+         * The generated wrapper element.
+         */
+        SVGRenderer.prototype.path = function (path) {
+          var attribs = this.styledMode
+            ? {}
+            : {
+                fill: "none",
+              };
+          if (isArray(path)) {
+            attribs.d = path;
+          } else if (isObject(path)) {
+            // attributes
+            extend(attribs, path);
+          }
+          return this.createElement("path").attr(attribs);
         };
         /**
-         * Get the updated default options. Until 3.0.7, merely exposing defaultOptions
-         * for outside modules wasn't enough because the setOptions method created a new
-         * object.
+         * Draw a circle, wraps the SVG `circle` element.
          *
-         * @function Highcharts.getOptions
+         * @sample highcharts/members/renderer-circle/
+         *         Drawing a circle
          *
-         * @return {Highcharts.Options}
-         */
-        var getOptions = H.getOptions = function () {
-                return H.defaultOptions;
-        };
-        /**
-         * Merge the default options with custom options and return the new options
-         * structure. Commonly used for defining reusable templates.
+         * @function Highcharts.SVGRenderer#circle
          *
-         * @sample highcharts/global/useutc-false Setting a global option
-         * @sample highcharts/members/setoptions Applying a global theme
+         * @param {number} [x]
+         * The center x position.
          *
-         * @function Highcharts.setOptions
+         * @param {number} [y]
+         * The center y position.
          *
-         * @param {Highcharts.Options} options
-         *        The new custom chart options.
+         * @param {number} [r]
+         * The radius.
          *
-         * @return {Highcharts.Options}
-         *         Updated options.
-         */
-        var setOptions = H.setOptions = function (options) {
-                // Copy in the default options
-                H.defaultOptions = merge(true,
-            H.defaultOptions,
-            options);
-            // Update the time object
-            if (options.time || options.global) {
-                H.time.update(merge(H.defaultOptions.global, H.defaultOptions.time, options.global, options.time));
-            }
-            return H.defaultOptions;
+         * @return {Highcharts.SVGElement}
+         * The generated wrapper element.
+         */ /**
+         * Draw a circle, wraps the SVG `circle` element.
+         *
+         * @function Highcharts.SVGRenderer#circle
+         *
+         * @param {Highcharts.SVGAttributes} [attribs]
+         * The initial attributes.
+         *
+         * @return {Highcharts.SVGElement}
+         * The generated wrapper element.
+         */
+        SVGRenderer.prototype.circle = function (x, y, r) {
+          var attribs = isObject(x)
+              ? x
+              : typeof x === "undefined"
+              ? {}
+              : { x: x, y: y, r: r },
+            wrapper = this.createElement("circle");
+          // Setting x or y translates to cx and cy
+          wrapper.xSetter = wrapper.ySetter = function (value, key, element) {
+            element.setAttribute("c" + key, value);
+          };
+          return wrapper.attr(attribs);
         };
-        // Register Highcharts as a plugin in jQuery
-        if (win.jQuery) {
-            /**
-             * Highcharts-extended JQuery.
-             *
-             * @external JQuery
-             */
-            /**
-             * Helper function to return the chart of the current JQuery selector
-             * element.
-             *
-             * @function external:JQuery#highcharts
-             *
-             * @return {Highcharts.Chart}
-             *         The chart that is linked to the JQuery selector element.
-             */ /**
-            * Factory function to create a chart in the current JQuery selector
-            * element.
-            *
-            * @function external:JQuery#highcharts
-            *
-            * @param {'Chart'|'Map'|'StockChart'|string} [className]
-            *        Name of the factory class in the Highcharts namespace.
-            *
-            * @param {Highcharts.Options} [options]
-            *        The chart options structure.
-            *
-            * @param {Highcharts.ChartCallbackFunction} [callback]
-            *        Function to run when the chart has loaded and and all external
-            *        images are loaded. Defining a
-            *        [chart.events.load](https://api.highcharts.com/highcharts/chart.events.load)
-            *        handler is equivalent.
-            *
-            * @return {JQuery}
-            *         The current JQuery selector.
-            */
-            win.jQuery.fn.highcharts = function () {
-                var args = [].slice.call(arguments);
-                if (this[0]) { // this[0] is the renderTo div
-                    // Create the chart
-                    if (args[0]) {
-                        new H[ // eslint-disable-line computed-property-spacing, no-new
-                        // Constructor defaults to Chart
-                        isString(args[0]) ? args.shift() : 'Chart'](this[0], args[0], args[1]);
-                        return this;
-                    }
-                    // When called without parameters or with the return argument,
-                    // return an existing chart
-                    return charts[attr(this[0], 'data-highcharts-chart')];
-                }
-            };
-        }
-        // TODO use named exports when supported.
-        var utilitiesModule = {
-                addEvent: addEvent,
-                arrayMax: arrayMax,
-                arrayMin: arrayMin,
-                attr: attr,
-                clamp: clamp,
-                clearTimeout: internalClearTimeout,
-                correctFloat: correctFloat,
-                createElement: createElement,
-                css: css,
-                defined: defined,
-                destroyObjectProperties: destroyObjectProperties,
-                discardElement: discardElement,
-                erase: erase,
-                error: error,
-                extend: extend,
-                extendClass: extendClass,
-                find: find,
-                fireEvent: fireEvent,
-                format: format,
-                getMagnitude: getMagnitude,
-                getNestedProperty: getNestedProperty,
-                getOptions: getOptions,
-                getStyle: getStyle,
-                inArray: inArray,
-                isArray: isArray,
-                isClass: isClass,
-                isDOMElement: isDOMElement,
-                isFunction: isFunction,
-                isNumber: isNumber,
-                isObject: isObject,
-                isString: isString,
-                merge: merge,
-                normalizeTickInterval: normalizeTickInterval,
-                numberFormat: numberFormat,
-                objectEach: objectEach,
-                offset: offset,
-                pad: pad,
-                pick: pick,
-                pInt: pInt,
-                relativeLength: relativeLength,
-                removeEvent: removeEvent,
-                setOptions: setOptions,
-                splat: splat,
-                stableSort: stableSort,
-                syncTimeout: syncTimeout,
-                timeUnits: timeUnits,
-                uniqueKey: uniqueKey,
-                useSerialIds: useSerialIds,
-                wrap: wrap
-            };
-
-        return utilitiesModule;
-    });
-    _registerModule(_modules, 'Core/Color/Color.js', [_modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (H, U) {
-        /* *
+        /**
+         * Draw and return an arc.
          *
-         *  (c) 2010-2020 Torstein Honsi
+         * @sample highcharts/members/renderer-arc/
+         *         Drawing an arc
          *
-         *  License: www.highcharts.com/license
+         * @function Highcharts.SVGRenderer#arc
          *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+         * @param {number} [x=0]
+         * Center X position.
          *
-         * */
-        var isNumber = U.isNumber,
-            merge = U.merge,
-            pInt = U.pInt;
-        /**
-         * A valid color to be parsed and handled by Highcharts. Highcharts internally
-         * supports hex colors like `#ffffff`, rgb colors like `rgb(255,255,255)` and
-         * rgba colors like `rgba(255,255,255,1)`. Other colors may be supported by the
-         * browsers and displayed correctly, but Highcharts is not able to process them
-         * and apply concepts like opacity and brightening.
+         * @param {number} [y=0]
+         * Center Y position.
          *
-         * @typedef {string} Highcharts.ColorString
-         */
-        /**
-         * A valid color type than can be parsed and handled by Highcharts. It can be a
-         * color string, a gradient object, or a pattern object.
+         * @param {number} [r=0]
+         * The outer radius' of the arc.
          *
-         * @typedef {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} Highcharts.ColorType
-         */
-        /**
-         * Gradient options instead of a solid color.
+         * @param {number} [innerR=0]
+         * Inner radius like used in donut charts.
          *
-         * @example
-         * // Linear gradient used as a color option
-         * color: {
-         *     linearGradient: { x1: 0, x2: 0, y1: 0, y2: 1 },
-         *     stops: [
-         *         [0, '#003399'], // start
-         *         [0.5, '#ffffff'], // middle
-         *         [1, '#3366AA'] // end
-         *     ]
-         * }
-         *
-         * @interface Highcharts.GradientColorObject
-         */ /**
-        * Holds an object that defines the start position and the end position relative
-        * to the shape.
-        * @name Highcharts.GradientColorObject#linearGradient
-        * @type {Highcharts.LinearGradientColorObject|undefined}
-        */ /**
-        * Holds an object that defines the center position and the radius.
-        * @name Highcharts.GradientColorObject#radialGradient
-        * @type {Highcharts.RadialGradientColorObject|undefined}
-        */ /**
-        * The first item in each tuple is the position in the gradient, where 0 is the
-        * start of the gradient and 1 is the end of the gradient. Multiple stops can be
-        * applied. The second item is the color for each stop. This color can also be
-        * given in the rgba format.
-        * @name Highcharts.GradientColorObject#stops
-        * @type {Array<Highcharts.GradientColorStopObject>}
-        */
-        /**
-         * Color stop tuple.
-         *
-         * @see Highcharts.GradientColorObject
-         *
-         * @interface Highcharts.GradientColorStopObject
-         */ /**
-        * @name Highcharts.GradientColorStopObject#0
-        * @type {number}
-        */ /**
-        * @name Highcharts.GradientColorStopObject#1
-        * @type {Highcharts.ColorString}
-        */ /**
-        * @name Highcharts.GradientColorStopObject#color
-        * @type {Highcharts.Color|undefined}
-        */
-        /**
-         * Defines the start position and the end position for a gradient relative
-         * to the shape. Start position (x1, y1) and end position (x2, y2) are relative
-         * to the shape, where 0 means top/left and 1 is bottom/right.
-         *
-         * @interface Highcharts.LinearGradientColorObject
-         */ /**
-        * Start horizontal position of the gradient. Float ranges 0-1.
-        * @name Highcharts.LinearGradientColorObject#x1
-        * @type {number}
-        */ /**
-        * End horizontal position of the gradient. Float ranges 0-1.
-        * @name Highcharts.LinearGradientColorObject#x2
-        * @type {number}
-        */ /**
-        * Start vertical position of the gradient. Float ranges 0-1.
-        * @name Highcharts.LinearGradientColorObject#y1
-        * @type {number}
-        */ /**
-        * End vertical position of the gradient. Float ranges 0-1.
-        * @name Highcharts.LinearGradientColorObject#y2
-        * @type {number}
-        */
-        /**
-         * Defines the center position and the radius for a gradient.
-         *
-         * @interface Highcharts.RadialGradientColorObject
-         */ /**
-        * Center horizontal position relative to the shape. Float ranges 0-1.
-        * @name Highcharts.RadialGradientColorObject#cx
-        * @type {number}
-        */ /**
-        * Center vertical position relative to the shape. Float ranges 0-1.
-        * @name Highcharts.RadialGradientColorObject#cy
-        * @type {number}
-        */ /**
-        * Radius relative to the shape. Float ranges 0-1.
-        * @name Highcharts.RadialGradientColorObject#r
-        * @type {number}
-        */
-        ''; // detach doclets above
-        /* *
+         * @param {number} [start=0]
+         * The starting angle of the arc in radians, where 0 is to the right and
+         * `-Math.PI/2` is up.
          *
-         *  Class
+         * @param {number} [end=0]
+         * The ending angle of the arc in radians, where 0 is to the right and
+         * `-Math.PI/2` is up.
          *
-         * */
-        /* eslint-disable no-invalid-this, valid-jsdoc */
+         * @return {Highcharts.SVGElement}
+         * The generated wrapper element.
+         */ /**
+         * Draw and return an arc. Overloaded function that takes arguments object.
+         *
+         * @function Highcharts.SVGRenderer#arc
+         *
+         * @param {Highcharts.SVGAttributes} attribs
+         * Initial SVG attributes.
+         *
+         * @return {Highcharts.SVGElement}
+         * The generated wrapper element.
+         */
+        SVGRenderer.prototype.arc = function (x, y, r, innerR, start, end) {
+          var arc, options;
+          if (isObject(x)) {
+            options = x;
+            y = options.y;
+            r = options.r;
+            innerR = options.innerR;
+            start = options.start;
+            end = options.end;
+            x = options.x;
+          } else {
+            options = {
+              innerR: innerR,
+              start: start,
+              end: end,
+            };
+          }
+          // Arcs are defined as symbols for the ability to set
+          // attributes in attr and animate
+          arc = this.symbol("arc", x, y, r, r, options);
+          arc.r = r; // #959
+          return arc;
+        };
         /**
-         * Handle color operations. Some object methods are chainable.
+         * Draw and return a rectangle.
          *
-         * @class
-         * @name Highcharts.Color
+         * @function Highcharts.SVGRenderer#rect
          *
-         * @param {Highcharts.ColorType} input
-         * The input color in either rbga or hex format
-         */
-        var Color = /** @class */ (function () {
-                /* *
-                 *
-                 *  Constructors
-                 *
-                 * */
-                function Color(input) {
-                    // Collection of parsers. This can be extended from the outside by pushing
-                    // parsers to Highcharts.Color.prototype.parsers.
-                    this.parsers = [{
-                            // RGBA color
-                            // eslint-disable-next-line max-len
-                            regex: /rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]?(?:\.[0-9]+)?)\s*\)/,
-                            parse: function (result) {
-                                return [
-                                    pInt(result[1]),
-                                    pInt(result[2]),
-                                    pInt(result[3]),
-                                    parseFloat(result[4], 10)
-                                ];
-                        }
-                    }, {
-                        // RGB color
-                        regex: /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/,
-                        parse: function (result) {
-                            return [pInt(result[1]), pInt(result[2]), pInt(result[3]), 1];
-                        }
-                    }];
-                this.rgba = [];
-                // Backwards compatibility, allow class overwrite
-                if (H.Color !== Color) {
-                    return new H.Color(input);
-                }
-                // Backwards compatibility, allow instanciation without new (#13053)
-                if (!(this instanceof Color)) {
-                    return new Color(input);
-                }
-                this.init(input);
-            }
-            /* *
-             *
-             *  Static Functions
-             *
-             * */
-            /**
-             * Creates a color instance out of a color string or object.
-             *
-             * @function Highcharts.Color.parse
-             *
-             * @param {Highcharts.ColorType} input
-             * The input color in either rbga or hex format.
-             *
-             * @return {Highcharts.Color}
-             * Color instance.
-             */
-            Color.parse = function (input) {
-                return new Color(input);
-            };
-            /* *
-             *
-             *  Functions
-             *
-             * */
-            /**
-             * Parse the input color to rgba array
-             *
-             * @private
-             * @function Highcharts.Color#init
-             *
-             * @param {Highcharts.ColorType} input
-             *        The input color in either rbga or hex format
-             *
-             * @return {void}
-             */
-            Color.prototype.init = function (input) {
-                var result,
-                    rgba,
-                    i,
-                    parser,
-                    len;
-                this.input = input = Color.names[input && input.toLowerCase ?
-                    input.toLowerCase() :
-                    ''] || input;
-                // Gradients
-                if (input && input.stops) {
-                    this.stops = input.stops.map(function (stop) {
-                        return new Color(stop[1]);
-                    });
-                    // Solid colors
-                }
-                else {
-                    // Bitmasking as input[0] is not working for legacy IE.
-                    if (input &&
-                        input.charAt &&
-                        input.charAt() === '#') {
-                        len = input.length;
-                        input = parseInt(input.substr(1), 16);
-                        // Handle long-form, e.g. #AABBCC
-                        if (len === 7) {
-                            rgba = [
-                                (input & 0xFF0000) >> 16,
-                                (input & 0xFF00) >> 8,
-                                (input & 0xFF),
-                                1
-                            ];
-                            // Handle short-form, e.g. #ABC
-                            // In short form, the value is assumed to be the same
-                            // for both nibbles for each component. e.g. #ABC = #AABBCC
-                        }
-                        else if (len === 4) {
-                            rgba = [
-                                (((input & 0xF00) >> 4) |
-                                    (input & 0xF00) >> 8),
-                                (((input & 0xF0) >> 4) |
-                                    (input & 0xF0)),
-                                ((input & 0xF) << 4) | (input & 0xF),
-                                1
-                            ];
-                        }
-                    }
-                    // Otherwise, check regex parsers
-                    if (!rgba) {
-                        i = this.parsers.length;
-                        while (i-- && !rgba) {
-                            parser = this.parsers[i];
-                            result = parser.regex.exec(input);
-                            if (result) {
-                                rgba = parser.parse(result);
-                            }
-                        }
-                    }
-                }
-                this.rgba = rgba || [];
-            };
-            /**
-             * Return the color or gradient stops in the specified format
-             *
-             * @function Highcharts.Color#get
-             *
-             * @param {string} [format]
-             *        Possible values are 'a', 'rgb', 'rgba' (default).
-             *
-             * @return {Highcharts.ColorType}
-             *         This color as a string or gradient stops.
-             */
-            Color.prototype.get = function (format) {
-                var input = this.input,
-                    rgba = this.rgba,
-                    ret;
-                if (typeof this.stops !== 'undefined') {
-                    ret = merge(input);
-                    ret.stops = [].concat(ret.stops);
-                    this.stops.forEach(function (stop, i) {
-                        ret.stops[i] = [
-                            ret.stops[i][0],
-                            stop.get(format)
-                        ];
-                    });
-                    // it's NaN if gradient colors on a column chart
-                }
-                else if (rgba && isNumber(rgba[0])) {
-                    if (format === 'rgb' || (!format && rgba[3] === 1)) {
-                        ret = 'rgb(' + rgba[0] + ',' + rgba[1] + ',' + rgba[2] + ')';
-                    }
-                    else if (format === 'a') {
-                        ret = rgba[3];
-                    }
-                    else {
-                        ret = 'rgba(' + rgba.join(',') + ')';
-                    }
-                }
-                else {
-                    ret = input;
-                }
-                return ret;
-            };
-            /**
-             * Brighten the color instance.
-             *
-             * @function Highcharts.Color#brighten
-             *
-             * @param {number} alpha
-             *        The alpha value.
-             *
-             * @return {Highcharts.Color}
-             *         This color with modifications.
-             */
-            Color.prototype.brighten = function (alpha) {
-                var i,
-                    rgba = this.rgba;
-                if (this.stops) {
-                    this.stops.forEach(function (stop) {
-                        stop.brighten(alpha);
-                    });
-                }
-                else if (isNumber(alpha) && alpha !== 0) {
-                    for (i = 0; i < 3; i++) {
-                        rgba[i] += pInt(alpha * 255);
-                        if (rgba[i] < 0) {
-                            rgba[i] = 0;
-                        }
-                        if (rgba[i] > 255) {
-                            rgba[i] = 255;
-                        }
-                    }
-                }
-                return this;
-            };
-            /**
-             * Set the color's opacity to a given alpha value.
-             *
-             * @function Highcharts.Color#setOpacity
-             *
-             * @param {number} alpha
-             *        Opacity between 0 and 1.
-             *
-             * @return {Highcharts.Color}
-             *         Color with modifications.
-             */
-            Color.prototype.setOpacity = function (alpha) {
-                this.rgba[3] = alpha;
-                return this;
-            };
-            /**
-             * Return an intermediate color between two colors.
-             *
-             * @function Highcharts.Color#tweenTo
-             *
-             * @param {Highcharts.Color} to
-             *        The color object to tween to.
-             *
-             * @param {number} pos
-             *        The intermediate position, where 0 is the from color (current
-             *        color item), and 1 is the `to` color.
-             *
-             * @return {Highcharts.ColorString}
-             *         The intermediate color in rgba notation.
-             */
-            Color.prototype.tweenTo = function (to, pos) {
-                // Check for has alpha, because rgba colors perform worse due to lack of
-                // support in WebKit.
-                var fromRgba = this.rgba,
-                    toRgba = to.rgba,
-                    hasAlpha,
-                    ret;
-                // Unsupported color, return to-color (#3920, #7034)
-                if (!toRgba.length || !fromRgba || !fromRgba.length) {
-                    ret = to.input || 'none';
-                    // Interpolate
-                }
-                else {
-                    hasAlpha = (toRgba[3] !== 1 || fromRgba[3] !== 1);
-                    ret = (hasAlpha ? 'rgba(' : 'rgb(') +
-                        Math.round(toRgba[0] + (fromRgba[0] - toRgba[0]) * (1 - pos)) +
-                        ',' +
-                        Math.round(toRgba[1] + (fromRgba[1] - toRgba[1]) * (1 - pos)) +
-                        ',' +
-                        Math.round(toRgba[2] + (fromRgba[2] - toRgba[2]) * (1 - pos)) +
-                        (hasAlpha ?
-                            (',' +
-                                (toRgba[3] + (fromRgba[3] - toRgba[3]) * (1 - pos))) :
-                            '') +
-                        ')';
-                }
-                return ret;
-            };
-            /* *
-             *
-             *  Static Properties
-             *
-             * */
-            // Collection of named colors. Can be extended from the outside by adding
-            // colors to Highcharts.Color.names.
-            Color.names = {
-                white: '#ffffff',
-                black: '#000000'
-            };
-            return Color;
-        }());
-        H.Color = Color;
-        /**
-         * Creates a color instance out of a color string.
+         * @param {number} [x]
+         * Left position.
          *
-         * @function Highcharts.color
+         * @param {number} [y]
+         * Top position.
          *
-         * @param {Highcharts.ColorType} input
-         *        The input color in either rbga or hex format
+         * @param {number} [width]
+         * Width of the rectangle.
          *
-         * @return {Highcharts.Color}
-         *         Color instance
-         */
-        H.color = Color.parse;
-        /* *
+         * @param {number} [height]
+         * Height of the rectangle.
          *
-         *  Export
+         * @param {number} [r]
+         * Border corner radius.
          *
-         * */
-
-        return Color;
-    });
-    _registerModule(_modules, 'Core/Animation/Fx.js', [_modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (H, U) {
-        /* *
+         * @param {number} [strokeWidth]
+         * A stroke width can be supplied to allow crisp drawing.
          *
-         *  (c) 2010-2020 Torstein Honsi
+         * @return {Highcharts.SVGElement}
+         * The generated wrapper element.
+         */ /**
+         * Draw and return a rectangle.
+         *
+         * @sample highcharts/members/renderer-rect-on-chart/
+         *         Draw a rectangle in a chart
+         * @sample highcharts/members/renderer-rect/
+         *         Draw a rectangle independent from a chart
+         *
+         * @function Highcharts.SVGRenderer#rect
+         *
+         * @param {Highcharts.SVGAttributes} [attributes]
+         * General SVG attributes for the rectangle.
+         *
+         * @return {Highcharts.SVGElement}
+         * The generated wrapper element.
+         */
+        SVGRenderer.prototype.rect = function (
+          x,
+          y,
+          width,
+          height,
+          r,
+          strokeWidth
+        ) {
+          r = isObject(x) ? x.r : r;
+          var wrapper = this.createElement("rect"),
+            attribs = isObject(x)
+              ? x
+              : typeof x === "undefined"
+              ? {}
+              : {
+                  x: x,
+                  y: y,
+                  width: Math.max(width, 0),
+                  height: Math.max(height, 0),
+                };
+          if (!this.styledMode) {
+            if (typeof strokeWidth !== "undefined") {
+              attribs.strokeWidth = strokeWidth;
+              attribs = wrapper.crisp(attribs);
+            }
+            attribs.fill = "none";
+          }
+          if (r) {
+            attribs.r = r;
+          }
+          wrapper.rSetter = function (value, key, element) {
+            wrapper.r = value;
+            attr(element, {
+              rx: value,
+              ry: value,
+            });
+          };
+          wrapper.rGetter = function () {
+            return wrapper.r;
+          };
+          return wrapper.attr(attribs);
+        };
+        /**
+         * Resize the {@link SVGRenderer#box} and re-align all aligned child
+         * elements.
          *
-         *  License: www.highcharts.com/license
+         * @sample highcharts/members/renderer-g/
+         *         Show and hide grouped objects
          *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+         * @function Highcharts.SVGRenderer#setSize
          *
-         * */
-        var win = H.win;
-        var isNumber = U.isNumber,
-            objectEach = U.objectEach;
-        /* eslint-disable no-invalid-this, valid-jsdoc */
+         * @param {number} width
+         * The new pixel width.
+         *
+         * @param {number} height
+         * The new pixel height.
+         *
+         * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animate=true]
+         * Whether and how to animate.
+         */
+        SVGRenderer.prototype.setSize = function (width, height, animate) {
+          var renderer = this,
+            alignedObjects = renderer.alignedObjects,
+            i = alignedObjects.length;
+          renderer.width = width;
+          renderer.height = height;
+          renderer.boxWrapper.animate(
+            {
+              width: width,
+              height: height,
+            },
+            {
+              step: function () {
+                this.attr({
+                  viewBox:
+                    "0 0 " + this.attr("width") + " " + this.attr("height"),
+                });
+              },
+              duration: pick(animate, true) ? void 0 : 0,
+            }
+          );
+          while (i--) {
+            alignedObjects[i].align();
+          }
+        };
         /**
-         * An animator object used internally. One instance applies to one property
-         * (attribute or style prop) on one element. Animation is always initiated
-         * through {@link SVGElement#animate}.
+         * Create and return an svg group element. Child
+         * {@link Highcharts.SVGElement} objects are added to the group by using the
+         * group as the first parameter in {@link Highcharts.SVGElement#add|add()}.
          *
-         * @example
-         * var rect = renderer.rect(0, 0, 10, 10).add();
-         * rect.animate({ width: 100 });
+         * @function Highcharts.SVGRenderer#g
          *
-         * @private
-         * @class
-         * @name Highcharts.Fx
+         * @param {string} [name]
+         *        The group will be given a class name of `highcharts-{name}`. This
+         *        can be used for styling and scripting.
+         *
+         * @return {Highcharts.SVGElement}
+         *         The generated wrapper element.
          */
-        var Fx = /** @class */ (function () {
-                /* *
-                 *
-                 *  Constructors
-                 *
-                 * */
-                /**
-                 *
-                 * @param {Highcharts.HTMLDOMElement|Highcharts.SVGElement} elem
-                 *        The element to animate.
-                 *
-                 * @param {Partial<Highcharts.AnimationOptionsObject>} options
-                 *        Animation options.
-                 *
-                 * @param {string} prop
-                 *        The single attribute or CSS property to animate.
-                 */
-                function Fx(elem, options, prop) {
-                    this.pos = NaN;
-                this.options = options;
-                this.elem = elem;
-                this.prop = prop;
+        SVGRenderer.prototype.g = function (name) {
+          var elem = this.createElement("g");
+          return name ? elem.attr({ class: "highcharts-" + name }) : elem;
+        };
+        /**
+         * Display an image.
+         *
+         * @sample highcharts/members/renderer-image-on-chart/
+         *         Add an image in a chart
+         * @sample highcharts/members/renderer-image/
+         *         Add an image independent of a chart
+         *
+         * @function Highcharts.SVGRenderer#image
+         *
+         * @param {string} src
+         *        The image source.
+         *
+         * @param {number} [x]
+         *        The X position.
+         *
+         * @param {number} [y]
+         *        The Y position.
+         *
+         * @param {number} [width]
+         *        The image width. If omitted, it defaults to the image file width.
+         *
+         * @param {number} [height]
+         *        The image height. If omitted it defaults to the image file
+         *        height.
+         *
+         * @param {Function} [onload]
+         *        Event handler for image load.
+         *
+         * @return {Highcharts.SVGElement}
+         *         The generated wrapper element.
+         */
+        SVGRenderer.prototype.image = function (
+          src,
+          x,
+          y,
+          width,
+          height,
+          onload
+        ) {
+          var attribs = { preserveAspectRatio: "none" },
+            elemWrapper,
+            dummy,
+            setSVGImageSource = function (el, src) {
+              // Set the href in the xlink namespace
+              if (el.setAttributeNS) {
+                el.setAttributeNS("http://www.w3.org/1999/xlink", "href", src);
+              } else {
+                // could be exporting in IE
+                // using href throws "not supported" in ie7 and under,
+                // requries regex shim to fix later
+                el.setAttribute("hc-svg-href", src);
+              }
+            },
+            onDummyLoad = function (e) {
+              setSVGImageSource(elemWrapper.element, src);
+              onload.call(elemWrapper, e);
+            };
+          // optional properties
+          if (arguments.length > 1) {
+            extend(attribs, {
+              x: x,
+              y: y,
+              width: width,
+              height: height,
+            });
+          }
+          elemWrapper = this.createElement("image").attr(attribs);
+          // Add load event if supplied
+          if (onload) {
+            // We have to use a dummy HTML image since IE support for SVG image
+            // load events is very buggy. First set a transparent src, wait for
+            // dummy to load, and then add the real src to the SVG image.
+            setSVGImageSource(
+              elemWrapper.element,
+              "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" /* eslint-disable-line */
+            );
+            dummy = new win.Image();
+            addEvent(dummy, "load", onDummyLoad);
+            dummy.src = src;
+            if (dummy.complete) {
+              onDummyLoad({});
             }
-            /* *
-             *
-             *  Functions
-             *
-             * */
-            /**
-             * Set the current step of a path definition on SVGElement.
-             *
-             * @function Highcharts.Fx#dSetter
-             *
-             * @return {void}
-             */
-            Fx.prototype.dSetter = function () {
-                var paths = this.paths,
-                    start = paths && paths[0],
-                    end = paths && paths[1],
-                    path = [],
-                    now = this.now || 0;
-                // Land on the final path without adjustment points appended in the ends
-                if (now === 1 || !start || !end) {
-                    path = this.toD || [];
-                }
-                else if (start.length === end.length && now < 1) {
-                    for (var i = 0; i < end.length; i++) {
-                        // Tween between the start segment and the end segment. Start
-                        // with a copy of the end segment and tween the appropriate
-                        // numerics
-                        var startSeg = start[i];
-                        var endSeg = end[i];
-                        var tweenSeg = [];
-                        for (var j = 0; j < endSeg.length; j++) {
-                            var startItem = startSeg[j];
-                            var endItem = endSeg[j];
-                            // Tween numbers
-                            if (typeof startItem === 'number' &&
-                                typeof endItem === 'number' &&
-                                // Arc boolean flags
-                                !(endSeg[0] === 'A' && (j === 4 || j === 5))) {
-                                tweenSeg[j] = startItem + now * (endItem - startItem);
-                                // Strings, take directly from the end segment
-                            }
-                            else {
-                                tweenSeg[j] = endItem;
-                            }
-                        }
-                        path.push(tweenSeg);
-                    }
-                    // If animation is finished or length not matching, land on right value
-                }
-                else {
-                    path = end;
-                }
-                this.elem.attr('d', path, void 0, true);
-            };
-            /**
-             * Update the element with the current animation step.
-             *
-             * @function Highcharts.Fx#update
-             *
-             * @return {void}
-             */
-            Fx.prototype.update = function () {
-                var elem = this.elem,
-                    prop = this.prop, // if destroyed, it is null
-                    now = this.now,
-                    step = this.options.step;
-                // Animation setter defined from outside
-                if (this[prop + 'Setter']) {
-                    this[prop + 'Setter']();
-                    // Other animations on SVGElement
-                }
-                else if (elem.attr) {
-                    if (elem.element) {
-                        elem.attr(prop, now, null, true);
-                    }
-                    // HTML styles, raw HTML content like container size
-                }
-                else {
-                    elem.style[prop] = now + this.unit;
-                }
-                if (step) {
-                    step.call(elem, now, this);
-                }
-            };
+          } else {
+            setSVGImageSource(elemWrapper.element, src);
+          }
+          return elemWrapper;
+        };
+        /**
+         * Draw a symbol out of pre-defined shape paths from
+         * {@link SVGRenderer#symbols}.
+         * It is used in Highcharts for point makers, which cake a `symbol` option,
+         * and label and button backgrounds like in the tooltip and stock flags.
+         *
+         * @function Highcharts.SVGRenderer#symbol
+         *
+         * @param {string} symbol
+         * The symbol name.
+         *
+         * @param {number} [x]
+         * The X coordinate for the top left position.
+         *
+         * @param {number} [y]
+         * The Y coordinate for the top left position.
+         *
+         * @param {number} [width]
+         * The pixel width.
+         *
+         * @param {number} [height]
+         * The pixel height.
+         *
+         * @param {Highcharts.SymbolOptionsObject} [options]
+         * Additional options, depending on the actual symbol drawn.
+         *
+         * @return {Highcharts.SVGElement}
+         */
+        SVGRenderer.prototype.symbol = function (
+          symbol,
+          x,
+          y,
+          width,
+          height,
+          options
+        ) {
+          var ren = this,
+            obj,
+            imageRegex = /^url\((.*?)\)$/,
+            isImage = imageRegex.test(symbol),
+            sym = !isImage && (this.symbols[symbol] ? symbol : "circle"),
+            // get the symbol definition function
+            symbolFn = sym && this.symbols[sym],
+            path,
+            imageSrc,
+            centerImage;
+          if (symbolFn) {
+            // Check if there's a path defined for this symbol
+            if (typeof x === "number") {
+              path = symbolFn.call(
+                this.symbols,
+                Math.round(x || 0),
+                Math.round(y || 0),
+                width || 0,
+                height || 0,
+                options
+              );
+            }
+            obj = this.path(path);
+            if (!ren.styledMode) {
+              obj.attr("fill", "none");
+            }
+            // expando properties for use in animate and attr
+            extend(obj, {
+              symbolName: sym,
+              x: x,
+              y: y,
+              width: width,
+              height: height,
+            });
+            if (options) {
+              extend(obj, options);
+            }
+            // Image symbols
+          } else if (isImage) {
+            imageSrc = symbol.match(imageRegex)[1];
+            // Create the image synchronously, add attribs async
+            obj = this.image(imageSrc);
+            // The image width is not always the same as the symbol width. The
+            // image may be centered within the symbol, as is the case when
+            // image shapes are used as label backgrounds, for example in flags.
+            obj.imgwidth = pick(
+              symbolSizes[imageSrc] && symbolSizes[imageSrc].width,
+              options && options.width
+            );
+            obj.imgheight = pick(
+              symbolSizes[imageSrc] && symbolSizes[imageSrc].height,
+              options && options.height
+            );
             /**
-             * Run an animation.
-             *
-             * @function Highcharts.Fx#run
-             *
-             * @param {number} from
-             *        The current value, value to start from.
-             *
-             * @param {number} to
-             *        The end value, value to land on.
-             *
-             * @param {string} unit
-             *        The property unit, for example `px`.
-             *
-             * @return {void}
+             * Set the size and position
              */
-            Fx.prototype.run = function (from, to, unit) {
-                var self = this,
-                    options = self.options,
-                    timer = function (gotoEnd) {
-                        return timer.stopped ? false : self.step(gotoEnd);
-                }, requestAnimationFrame = win.requestAnimationFrame ||
-                    function (step) {
-                        setTimeout(step, 13);
-                    }, step = function () {
-                    for (var i = 0; i < H.timers.length; i++) {
-                        if (!H.timers[i]()) {
-                            H.timers.splice(i--, 1);
-                        }
-                    }
-                    if (H.timers.length) {
-                        requestAnimationFrame(step);
-                    }
-                };
-                if (from === to && !this.elem['forceAnimate:' + this.prop]) {
-                    delete options.curAnim[this.prop];
-                    if (options.complete && Object.keys(options.curAnim).length === 0) {
-                        options.complete.call(this.elem);
-                    }
-                }
-                else { // #7166
-                    this.startTime = +new Date();
-                    this.start = from;
-                    this.end = to;
-                    this.unit = unit;
-                    this.now = this.start;
-                    this.pos = 0;
-                    timer.elem = this.elem;
-                    timer.prop = this.prop;
-                    if (timer() && H.timers.push(timer) === 1) {
-                        requestAnimationFrame(step);
-                    }
-                }
+            centerImage = function () {
+              obj.attr({
+                width: obj.width,
+                height: obj.height,
+              });
             };
             /**
-             * Run a single step in the animation.
-             *
-             * @function Highcharts.Fx#step
-             *
-             * @param {boolean} [gotoEnd]
-             *        Whether to go to the endpoint of the animation after abort.
-             *
-             * @return {boolean}
-             *         Returns `true` if animation continues.
+             * Width and height setters that take both the image's physical size
+             * and the label size into consideration, and translates the image
+             * to center within the label.
              */
-            Fx.prototype.step = function (gotoEnd) {
-                var t = +new Date(),
-                    ret,
-                    done,
-                    options = this.options,
-                    elem = this.elem,
-                    complete = options.complete,
-                    duration = options.duration,
-                    curAnim = options.curAnim;
-                if (elem.attr && !elem.element) { // #2616, element is destroyed
-                    ret = false;
-                }
-                else if (gotoEnd || t >= duration + this.startTime) {
-                    this.now = this.end;
-                    this.pos = 1;
-                    this.update();
-                    curAnim[this.prop] = true;
-                    done = true;
-                    objectEach(curAnim, function (val) {
-                        if (val !== true) {
-                            done = false;
-                        }
+            ["width", "height"].forEach(function (key) {
+              obj[key + "Setter"] = function (value, key) {
+                var attribs = {},
+                  imgSize = this["img" + key],
+                  trans = key === "width" ? "translateX" : "translateY";
+                this[key] = value;
+                if (defined(imgSize)) {
+                  // Scale and center the image within its container.
+                  // The name `backgroundSize` is taken from the CSS spec,
+                  // but the value `within` is made up. Other possible
+                  // values in the spec, `cover` and `contain`, can be
+                  // implemented if needed.
+                  if (
+                    options &&
+                    options.backgroundSize === "within" &&
+                    this.width &&
+                    this.height
+                  ) {
+                    imgSize = Math.round(
+                      imgSize *
+                        Math.min(
+                          this.width / this.imgwidth,
+                          this.height / this.imgheight
+                        )
+                    );
+                  }
+                  if (this.element) {
+                    this.element.setAttribute(key, imgSize);
+                  }
+                  if (!this.alignByTranslate) {
+                    attribs[trans] = ((this[key] || 0) - imgSize) / 2;
+                    this.attr(attribs);
+                  }
+                }
+              };
+            });
+            if (defined(x)) {
+              obj.attr({
+                x: x,
+                y: y,
+              });
+            }
+            obj.isImg = true;
+            if (defined(obj.imgwidth) && defined(obj.imgheight)) {
+              centerImage();
+            } else {
+              // Initialize image to be 0 size so export will still function
+              // if there's no cached sizes.
+              obj.attr({ width: 0, height: 0 });
+              // Create a dummy JavaScript image to get the width and height.
+              createElement("img", {
+                onload: function () {
+                  var chart = charts[ren.chartIndex];
+                  // Special case for SVGs on IE11, the width is not
+                  // accessible until the image is part of the DOM
+                  // (#2854).
+                  if (this.width === 0) {
+                    css(this, {
+                      position: "absolute",
+                      top: "-999em",
                     });
-                    if (done && complete) {
-                        complete.call(elem);
-                    }
-                    ret = false;
-                }
-                else {
-                    this.pos = options.easing((t - this.startTime) / duration);
-                    this.now = this.start + ((this.end - this.start) * this.pos);
-                    this.update();
-                    ret = true;
-                }
-                return ret;
-            };
-            /**
-             * Prepare start and end values so that the path can be animated one to one.
-             *
-             * @function Highcharts.Fx#initPath
-             *
-             * @param {Highcharts.SVGElement} elem
-             *        The SVGElement item.
-             *
-             * @param {Highcharts.SVGPathArray|undefined} fromD
-             *        Starting path definition.
-             *
-             * @param {Highcharts.SVGPathArray} toD
-             *        Ending path definition.
-             *
-             * @return {Array<Highcharts.SVGPathArray,Highcharts.SVGPathArray>}
-             *         An array containing start and end paths in array form so that
-             *         they can be animated in parallel.
-             */
-            Fx.prototype.initPath = function (elem, fromD, toD) {
-                var shift,
-                    startX = elem.startX,
-                    endX = elem.endX,
-                    fullLength,
-                    i,
-                    start = fromD && fromD.slice(), // copy
-                    end = toD.slice(), // copy
-                    isArea = elem.isArea,
-                    positionFactor = isArea ? 2 : 1,
-                    reverse;
-                if (!start) {
-                    return [end, end];
-                }
-                /**
-                 * If shifting points, prepend a dummy point to the end path.
-                 * @private
-                 * @param {Highcharts.SVGPathArray} arr - array
-                 * @param {Highcharts.SVGPathArray} other - array
-                 * @return {void}
-                 */
-                function prepend(arr, other) {
-                    while (arr.length < fullLength) {
-                        // Move to, line to or curve to?
-                        var moveSegment = arr[0],
-                            otherSegment = other[fullLength - arr.length];
-                        if (otherSegment && moveSegment[0] === 'M') {
-                            if (otherSegment[0] === 'C') {
-                                arr[0] = [
-                                    'C',
-                                    moveSegment[1],
-                                    moveSegment[2],
-                                    moveSegment[1],
-                                    moveSegment[2],
-                                    moveSegment[1],
-                                    moveSegment[2]
-                                ];
-                            }
-                            else {
-                                arr[0] = ['L', moveSegment[1], moveSegment[2]];
-                            }
-                        }
-                        // Prepend a copy of the first point
-                        arr.unshift(moveSegment);
-                        // For areas, the bottom path goes back again to the left, so we
-                        // need to append a copy of the last point.
-                        if (isArea) {
-                            arr.push(arr[arr.length - 1]);
-                        }
-                    }
-                }
-                /**
-                 * Copy and append last point until the length matches the end length.
-                 * @private
-                 * @param {Highcharts.SVGPathArray} arr - array
-                 * @param {Highcharts.SVGPathArray} other - array
-                 * @return {void}
-                 */
-                function append(arr, other) {
-                    while (arr.length < fullLength) {
-                        // Pull out the slice that is going to be appended or inserted.
-                        // In a line graph, the positionFactor is 1, and the last point
-                        // is sliced out. In an area graph, the positionFactor is 2,
-                        // causing the middle two points to be sliced out, since an area
-                        // path starts at left, follows the upper path then turns and
-                        // follows the bottom back.
-                        var segmentToAdd = arr[arr.length / positionFactor - 1].slice();
-                        // Disable the first control point of curve segments
-                        if (segmentToAdd[0] === 'C') {
-                            segmentToAdd[1] = segmentToAdd[5];
-                            segmentToAdd[2] = segmentToAdd[6];
-                        }
-                        if (!isArea) {
-                            arr.push(segmentToAdd);
-                        }
-                        else {
-                            var lowerSegmentToAdd = arr[arr.length / positionFactor].slice();
-                            arr.splice(arr.length / 2, 0, segmentToAdd, lowerSegmentToAdd);
-                        }
-                    }
-                }
-                // For sideways animation, find out how much we need to shift to get the
-                // start path Xs to match the end path Xs.
-                if (startX && endX) {
-                    for (i = 0; i < startX.length; i++) {
-                        // Moving left, new points coming in on right
-                        if (startX[i] === endX[0]) {
-                            shift = i;
-                            break;
-                            // Moving right
-                        }
-                        else if (startX[0] ===
-                            endX[endX.length - startX.length + i]) {
-                            shift = i;
-                            reverse = true;
-                            break;
-                            // Fixed from the right side, "scaling" left
-                        }
-                        else if (startX[startX.length - 1] ===
-                            endX[endX.length - startX.length + i]) {
-                            shift = startX.length - i;
-                            break;
-                        }
-                    }
-                    if (typeof shift === 'undefined') {
-                        start = [];
-                    }
-                }
-                if (start.length && isNumber(shift)) {
-                    // The common target length for the start and end array, where both
-                    // arrays are padded in opposite ends
-                    fullLength = end.length + shift * positionFactor;
-                    if (!reverse) {
-                        prepend(end, start);
-                        append(start, end);
-                    }
-                    else {
-                        prepend(start, end);
-                        append(end, start);
-                    }
-                }
-                return [start, end];
-            };
-            /**
-             * Handle animation of the color attributes directly.
-             *
-             * @function Highcharts.Fx#fillSetter
-             *
-             * @return {void}
-             */
-            Fx.prototype.fillSetter = function () {
-                Fx.prototype.strokeSetter.apply(this, arguments);
-            };
-            /**
-             * Handle animation of the color attributes directly.
-             *
-             * @function Highcharts.Fx#strokeSetter
-             *
-             * @return {void}
-             */
-            Fx.prototype.strokeSetter = function () {
-                this.elem.attr(this.prop, H.color(this.start).tweenTo(H.color(this.end), this.pos), null, true);
-            };
-            return Fx;
-        }());
-        H.Fx = Fx;
-
-        return Fx;
-    });
-    _registerModule(_modules, 'Core/Animation/AnimationUtilities.js', [_modules['Core/Animation/Fx.js'], _modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (Fx, H, U) {
-        /* *
+                    doc.body.appendChild(this);
+                  }
+                  // Center the image
+                  symbolSizes[imageSrc] = {
+                    width: this.width,
+                    height: this.height,
+                  };
+                  obj.imgwidth = this.width;
+                  obj.imgheight = this.height;
+                  if (obj.element) {
+                    centerImage();
+                  }
+                  // Clean up after #2854 workaround.
+                  if (this.parentNode) {
+                    this.parentNode.removeChild(this);
+                  }
+                  // Fire the load event when all external images are
+                  // loaded
+                  ren.imgCount--;
+                  if (!ren.imgCount && chart && !chart.hasLoaded) {
+                    chart.onload();
+                  }
+                },
+                src: imageSrc,
+              });
+              this.imgCount++;
+            }
+          }
+          return obj;
+        };
+        /**
+         * Define a clipping rectangle. The clipping rectangle is later applied
+         * to {@link SVGElement} objects through the {@link SVGElement#clip}
+         * function.
          *
-         *  (c) 2010-2020 Torstein Honsi
+         * @example
+         * var circle = renderer.circle(100, 100, 100)
+         *     .attr({ fill: 'red' })
+         *     .add();
+         * var clipRect = renderer.clipRect(100, 100, 100, 100);
          *
-         *  License: www.highcharts.com/license
+         * // Leave only the lower right quarter visible
+         * circle.clip(clipRect);
          *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+         * @function Highcharts.SVGRenderer#clipRect
          *
-         * */
-        var defined = U.defined,
-            getStyle = U.getStyle,
-            isArray = U.isArray,
-            isNumber = U.isNumber,
-            isObject = U.isObject,
-            merge = U.merge,
-            objectEach = U.objectEach,
-            pick = U.pick;
-        /**
-         * Set the global animation to either a given value, or fall back to the given
-         * chart's animation option.
+         * @param {number} [x]
          *
-         * @function Highcharts.setAnimation
+         * @param {number} [y]
          *
-         * @param {boolean|Partial<Highcharts.AnimationOptionsObject>|undefined} animation
-         *        The animation object.
+         * @param {number} [width]
          *
-         * @param {Highcharts.Chart} chart
-         *        The chart instance.
+         * @param {number} [height]
          *
-         * @todo
-         * This function always relates to a chart, and sets a property on the renderer,
-         * so it should be moved to the SVGRenderer.
+         * @return {Highcharts.ClipRectElement}
+         *         A clipping rectangle.
          */
-        var setAnimation = H.setAnimation = function setAnimation(animation,
-            chart) {
-                chart.renderer.globalAnimation = pick(animation,
-            chart.options.chart.animation,
-            true);
+        SVGRenderer.prototype.clipRect = function (x, y, width, height) {
+          var wrapper,
+            // Add a hyphen at the end to avoid confusion in testing indexes
+            // -1 and -10, -11 etc (#6550)
+            id = uniqueKey() + "-",
+            clipPath = this.createElement("clipPath")
+              .attr({
+                id: id,
+              })
+              .add(this.defs);
+          wrapper = this.rect(x, y, width, height, 0).add(clipPath);
+          wrapper.id = id;
+          wrapper.clipPath = clipPath;
+          wrapper.count = 0;
+          return wrapper;
         };
         /**
-         * Get the animation in object form, where a disabled animation is always
-         * returned as `{ duration: 0 }`.
+         * Draw text. The text can contain a subset of HTML, like spans and anchors
+         * and some basic text styling of these. For more advanced features like
+         * border and background, use {@link Highcharts.SVGRenderer#label} instead.
+         * To update the text after render, run `text.attr({ text: 'New text' })`.
          *
-         * @function Highcharts.animObject
-         *
-         * @param {boolean|Highcharts.AnimationOptionsObject} [animation=0]
-         *        An animation setting. Can be an object with duration, complete and
-         *        easing properties, or a boolean to enable or disable.
+         * @sample highcharts/members/renderer-text-on-chart/
+         *         Annotate the chart freely
+         * @sample highcharts/members/renderer-on-chart/
+         *         Annotate with a border and in response to the data
+         * @sample highcharts/members/renderer-text/
+         *         Formatted text
          *
-         * @return {Highcharts.AnimationOptionsObject}
-         *         An object with at least a duration property.
-         */
-        var animObject = H.animObject = function animObject(animation) {
-                return isObject(animation) ?
-                    H.merge({ duration: 500,
-            defer: 0 },
-            animation) :
-                    { duration: animation ? 500 : 0,
-            defer: 0 };
+         * @function Highcharts.SVGRenderer#text
+         *
+         * @param {string} [str]
+         * The text of (subset) HTML to draw.
+         *
+         * @param {number} [x]
+         * The x position of the text's lower left corner.
+         *
+         * @param {number} [y]
+         * The y position of the text's lower left corner.
+         *
+         * @param {boolean} [useHTML=false]
+         * Use HTML to render the text.
+         *
+         * @return {Highcharts.SVGElement}
+         * The text object.
+         */
+        SVGRenderer.prototype.text = function (str, x, y, useHTML) {
+          // declare variables
+          var renderer = this,
+            wrapper,
+            attribs = {};
+          if (useHTML && (renderer.allowHTML || !renderer.forExport)) {
+            return renderer.html(str, x, y);
+          }
+          attribs.x = Math.round(x || 0); // X always needed for line-wrap logic
+          if (y) {
+            attribs.y = Math.round(y);
+          }
+          if (defined(str)) {
+            attribs.text = str;
+          }
+          wrapper = renderer.createElement("text").attr(attribs);
+          if (!useHTML) {
+            wrapper.xSetter = function (value, key, element) {
+              var tspans = element.getElementsByTagName("tspan"),
+                tspan,
+                parentVal = element.getAttribute(key),
+                i;
+              for (i = 0; i < tspans.length; i++) {
+                tspan = tspans[i];
+                // If the x values are equal, the tspan represents a
+                // linebreak
+                if (tspan.getAttribute(key) === parentVal) {
+                  tspan.setAttribute(key, value);
+                }
+              }
+              element.setAttribute(key, value);
+            };
+          }
+          return wrapper;
         };
         /**
-         * Get the defer as a number value from series animation options.
-         *
-         * @function Highcharts.getDeferredAnimation
-         *
-         * @param {Highcharts.Chart} chart
-         *        The chart instance.
-         *
-         * @param {boolean|Highcharts.AnimationOptionsObject} animation
-         *        An animation setting. Can be an object with duration, complete and
-         *        easing properties, or a boolean to enable or disable.
-         *
-         * @param {Highcharts.Series} [series]
-         *        Series to defer animation.
-         *
-         * @return {number}
-         *        The numeric value.
-         */
-        var getDeferredAnimation = H.getDeferredAnimation = function (chart,
-            animation,
-            series) {
-                var labelAnimation = animObject(animation);
-            var s = series ? [series] : chart.series;
-            var defer = 0;
-            var duration = 0;
-            s.forEach(function (series) {
-                var seriesAnim = animObject(series.options.animation);
-                defer = animation && defined(animation.defer) ?
-                    labelAnimation.defer :
-                    Math.max(defer, seriesAnim.duration + seriesAnim.defer);
-                duration = Math.min(labelAnimation.duration, seriesAnim.duration);
-            });
-            // Disable defer for exporting
-            if (chart.renderer.forExport) {
-                defer = 0;
-            }
-            var anim = {
-                    defer: Math.max(0,
-                defer - duration),
-                    duration: Math.min(defer,
-                duration)
-                };
-            return anim;
+         * Utility to return the baseline offset and total line height from the font
+         * size.
+         *
+         * @function Highcharts.SVGRenderer#fontMetrics
+         *
+         * @param {number|string} [fontSize]
+         *        The current font size to inspect. If not given, the font size
+         *        will be found from the DOM element.
+         *
+         * @param {Highcharts.SVGElement|Highcharts.SVGDOMElement} [elem]
+         *        The element to inspect for a current font size.
+         *
+         * @return {Highcharts.FontMetricsObject}
+         *         The font metrics.
+         */
+        SVGRenderer.prototype.fontMetrics = function (fontSize, elem) {
+          var lineHeight, baseline;
+          if (
+            (this.styledMode || !/px/.test(fontSize)) &&
+            win.getComputedStyle // old IE doesn't support it
+          ) {
+            fontSize =
+              elem && SVGElement.prototype.getStyle.call(elem, "font-size");
+          } else {
+            fontSize =
+              fontSize ||
+              // When the elem is a DOM element (#5932)
+              (elem && elem.style && elem.style.fontSize) ||
+              // Fall back on the renderer style default
+              (this.style && this.style.fontSize);
+          }
+          // Handle different units
+          if (/px/.test(fontSize)) {
+            fontSize = pInt(fontSize);
+          } else {
+            fontSize = 12;
+          }
+          // Empirical values found by comparing font size and bounding box
+          // height. Applies to the default font family.
+          // https://jsfiddle.net/highcharts/7xvn7/
+          lineHeight =
+            fontSize < 24 ? fontSize + 3 : Math.round(fontSize * 1.2);
+          baseline = Math.round(lineHeight * 0.8);
+          return {
+            h: lineHeight,
+            b: baseline,
+            f: fontSize,
+          };
         };
         /**
-         * The global animate method, which uses Fx to create individual animators.
+         * Correct X and Y positioning of a label for rotation (#1764).
          *
-         * @function Highcharts.animate
+         * @private
+         * @function Highcharts.SVGRenderer#rotCorr
          *
-         * @param {Highcharts.HTMLDOMElement|Highcharts.SVGElement} el
-         *        The element to animate.
+         * @param {number} baseline
          *
-         * @param {Highcharts.CSSObject|Highcharts.SVGAttributes} params
-         *        An object containing key-value pairs of the properties to animate.
-         *        Supports numeric as pixel-based CSS properties for HTML objects and
-         *        attributes for SVGElements.
+         * @param {number} rotation
          *
-         * @param {Partial<Highcharts.AnimationOptionsObject>} [opt]
-         *        Animation options.
+         * @param {boolean} [alterY]
          *
-         * @return {void}
+         * @param {Highcharts.PositionObject}
          */
-        var animate = H.animate = function (el,
-            params,
-            opt) {
-                var start,
-            unit = '',
-            end,
-            fx,
-            args;
-            if (!isObject(opt)) { // Number or undefined/null
-                args = arguments;
-                opt = {
-                    duration: args[2],
-                    easing: args[3],
-                    complete: args[4]
-                };
-            }
-            if (!isNumber(opt.duration)) {
-                opt.duration = 400;
-            }
-            opt.easing = typeof opt.easing === 'function' ?
-                opt.easing :
-                (Math[opt.easing] || Math.easeInOutSine);
-            opt.curAnim = merge(params);
-            objectEach(params, function (val, prop) {
-                // Stop current running animation of this property
-                stop(el, prop);
-                fx = new Fx(el, opt, prop);
-                end = null;
-                if (prop === 'd' && isArray(params.d)) {
-                    fx.paths = fx.initPath(el, el.pathArray, params.d);
-                    fx.toD = params.d;
-                    start = 0;
-                    end = 1;
-                }
-                else if (el.attr) {
-                    start = el.attr(prop);
-                }
-                else {
-                    start = parseFloat(getStyle(el, prop)) || 0;
-                    if (prop !== 'opacity') {
-                        unit = 'px';
-                    }
-                }
-                if (!end) {
-                    end = val;
-                }
-                if (end && end.match && end.match('px')) {
-                    end = end.replace(/px/g, ''); // #4351
-                }
-                fx.run(start, end, unit);
-            });
+        SVGRenderer.prototype.rotCorr = function (baseline, rotation, alterY) {
+          var y = baseline;
+          if (rotation && alterY) {
+            y = Math.max(y * Math.cos(rotation * deg2rad), 4);
+          }
+          return {
+            x: (-baseline / 3) * Math.sin(rotation * deg2rad),
+            y: y,
+          };
         };
         /**
-         * Stop running animation.
+         * Compatibility function to convert the legacy one-dimensional path array
+         * into an array of segments.
          *
-         * @function Highcharts.stop
-         *
-         * @param {Highcharts.SVGElement} el
-         *        The SVGElement to stop animation on.
-         *
-         * @param {string} [prop]
-         *        The property to stop animating. If given, the stop method will stop a
-         *        single property from animating, while others continue.
-         *
-         * @return {void}
+         * It is used in maps to parse the `path` option, and in SVGRenderer.dSetter
+         * to support legacy paths from demos.
          *
-         * @todo
-         * A possible extension to this would be to stop a single property, when
-         * we want to continue animating others. Then assign the prop to the timer
-         * in the Fx.run method, and check for the prop here. This would be an
-         * improvement in all cases where we stop the animation from .attr. Instead of
-         * stopping everything, we can just stop the actual attributes we're setting.
-         */
-        var stop = H.stop = function (el,
-            prop) {
-                var i = H.timers.length;
-            // Remove timers related to this element (#4519)
-            while (i--) {
-                if (H.timers[i].elem === el && (!prop || prop === H.timers[i].prop)) {
-                    H.timers[i].stopped = true; // #4667
-                }
+         * @private
+         * @function Highcharts.SVGRenderer#pathToSegments
+         */
+        SVGRenderer.prototype.pathToSegments = function (path) {
+          var ret = [];
+          var segment = [];
+          var commandLength = {
+            A: 8,
+            C: 7,
+            H: 2,
+            L: 3,
+            M: 3,
+            Q: 5,
+            S: 5,
+            T: 3,
+            V: 2,
+          };
+          // Short, non-typesafe parsing of the one-dimensional array. It splits
+          // the path on any string. This is not type checked against the tuple
+          // types, but is shorter, and doesn't require specific checks for any
+          // command type in SVG.
+          for (var i = 0; i < path.length; i++) {
+            // Command skipped, repeat previous or insert L/l for M/m
+            if (
+              isString(segment[0]) &&
+              isNumber(path[i]) &&
+              segment.length === commandLength[segment[0].toUpperCase()]
+            ) {
+              path.splice(i, 0, segment[0].replace("M", "L").replace("m", "l"));
             }
-        };
-        var animationExports = {
-                animate: animate,
-                animObject: animObject,
-                getDeferredAnimation: getDeferredAnimation,
-                setAnimation: setAnimation,
-                stop: stop
-            };
-
-        return animationExports;
-    });
-    _registerModule(_modules, 'Core/Renderer/SVG/SVGElement.js', [_modules['Core/Animation/AnimationUtilities.js'], _modules['Core/Color/Color.js'], _modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (A, Color, H, U) {
-        /* *
-         *
-         *  (c) 2010-2020 Torstein Honsi
-         *
-         *  License: www.highcharts.com/license
-         *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
-         *
-         * */
-        var animate = A.animate,
-            animObject = A.animObject,
-            stop = A.stop;
-        var deg2rad = H.deg2rad,
-            doc = H.doc,
-            hasTouch = H.hasTouch,
-            isFirefox = H.isFirefox,
-            noop = H.noop,
-            svg = H.svg,
-            SVG_NS = H.SVG_NS,
-            win = H.win;
-        var attr = U.attr,
-            createElement = U.createElement,
-            css = U.css,
-            defined = U.defined,
-            erase = U.erase,
-            extend = U.extend,
-            fireEvent = U.fireEvent,
-            isArray = U.isArray,
-            isFunction = U.isFunction,
-            isNumber = U.isNumber,
-            isString = U.isString,
-            merge = U.merge,
-            objectEach = U.objectEach,
-            pick = U.pick,
-            pInt = U.pInt,
-            syncTimeout = U.syncTimeout,
-            uniqueKey = U.uniqueKey;
-        /**
-         * The horizontal alignment of an element.
-         *
-         * @typedef {"center"|"left"|"right"} Highcharts.AlignValue
-         */
-        /**
-         * Options to align the element relative to the chart or another box.
-         *
-         * @interface Highcharts.AlignObject
-         */ /**
-        * Horizontal alignment. Can be one of `left`, `center` and `right`.
-        *
-        * @name Highcharts.AlignObject#align
-        * @type {Highcharts.AlignValue|undefined}
-        *
-        * @default left
-        */ /**
-        * Vertical alignment. Can be one of `top`, `middle` and `bottom`.
-        *
-        * @name Highcharts.AlignObject#verticalAlign
-        * @type {Highcharts.VerticalAlignValue|undefined}
-        *
-        * @default top
-        */ /**
-        * Horizontal pixel offset from alignment.
-        *
-        * @name Highcharts.AlignObject#x
-        * @type {number|undefined}
-        *
-        * @default 0
-        */ /**
-        * Vertical pixel offset from alignment.
-        *
-        * @name Highcharts.AlignObject#y
-        * @type {number|undefined}
-        *
-        * @default 0
-        */ /**
-        * Use the `transform` attribute with translateX and translateY custom
-        * attributes to align this elements rather than `x` and `y` attributes.
-        *
-        * @name Highcharts.AlignObject#alignByTranslate
-        * @type {boolean|undefined}
-        *
-        * @default false
-        */
-        /**
-         * Bounding box of an element.
-         *
-         * @interface Highcharts.BBoxObject
-         * @extends Highcharts.PositionObject
-         */ /**
-        * Height of the bounding box.
-        *
-        * @name Highcharts.BBoxObject#height
-        * @type {number}
-        */ /**
-        * Width of the bounding box.
-        *
-        * @name Highcharts.BBoxObject#width
-        * @type {number}
-        */ /**
-        * Horizontal position of the bounding box.
-        *
-        * @name Highcharts.BBoxObject#x
-        * @type {number}
-        */ /**
-        * Vertical position of the bounding box.
-        *
-        * @name Highcharts.BBoxObject#y
-        * @type {number}
-        */
-        /**
-         * An object of key-value pairs for SVG attributes. Attributes in Highcharts
-         * elements for the most parts correspond to SVG, but some are specific to
-         * Highcharts, like `zIndex`, `rotation`, `rotationOriginX`,
-         * `rotationOriginY`, `translateX`, `translateY`, `scaleX` and `scaleY`. SVG
-         * attributes containing a hyphen are _not_ camel-cased, they should be
-         * quoted to preserve the hyphen.
-         *
-         * @example
-         * {
-         *     'stroke': '#ff0000', // basic
-         *     'stroke-width': 2, // hyphenated
-         *     'rotation': 45 // custom
-         *     'd': ['M', 10, 10, 'L', 30, 30, 'z'] // path definition, note format
-         * }
-         *
-         * @interface Highcharts.SVGAttributes
-         */ /**
-        * @name Highcharts.SVGAttributes#[key:string]
-        * @type {*}
-        */ /**
-        * @name Highcharts.SVGAttributes#d
-        * @type {string|Highcharts.SVGPathArray|undefined}
-        */ /**
-        * @name Highcharts.SVGAttributes#fill
-        * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject|undefined}
-        */ /**
-        * @name Highcharts.SVGAttributes#inverted
-        * @type {boolean|undefined}
-        */ /**
-        * @name Highcharts.SVGAttributes#matrix
-        * @type {Array<number>|undefined}
-        */ /**
-        * @name Highcharts.SVGAttributes#rotation
-        * @type {number|undefined}
-        */ /**
-        * @name Highcharts.SVGAttributes#rotationOriginX
-        * @type {number|undefined}
-        */ /**
-        * @name Highcharts.SVGAttributes#rotationOriginY
-        * @type {number|undefined}
-        */ /**
-        * @name Highcharts.SVGAttributes#scaleX
-        * @type {number|undefined}
-        */ /**
-        * @name Highcharts.SVGAttributes#scaleY
-        * @type {number|undefined}
-        */ /**
-        * @name Highcharts.SVGAttributes#stroke
-        * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject|undefined}
-        */ /**
-        * @name Highcharts.SVGAttributes#style
-        * @type {string|Highcharts.CSSObject|undefined}
-        */ /**
-        * @name Highcharts.SVGAttributes#translateX
-        * @type {number|undefined}
-        */ /**
-        * @name Highcharts.SVGAttributes#translateY
-        * @type {number|undefined}
-        */ /**
-        * @name Highcharts.SVGAttributes#zIndex
-        * @type {number|undefined}
-        */
-        /**
-         * An SVG DOM element. The type is a reference to the regular SVGElement in the
-         * global scope.
-         *
-         * @typedef {globals.GlobalSVGElement} Highcharts.SVGDOMElement
-         *
-         * @see https://developer.mozilla.org/en-US/docs/Web/API/SVGElement
-         */
-        /**
-         * The vertical alignment of an element.
-         *
-         * @typedef {"bottom"|"middle"|"top"} Highcharts.VerticalAlignValue
-         */
-        ''; // detach doclets above
-        /* eslint-disable no-invalid-this, valid-jsdoc */
-        /**
-         * The SVGElement prototype is a JavaScript wrapper for SVG elements used in the
-         * rendering layer of Highcharts. Combined with the
-         * {@link Highcharts.SVGRenderer}
-         * object, these prototypes allow freeform annotation in the charts or even in
-         * HTML pages without instanciating a chart. The SVGElement can also wrap HTML
-         * labels, when `text` or `label` elements are created with the `useHTML`
-         * parameter.
-         *
-         * The SVGElement instances are created through factory functions on the
-         * {@link Highcharts.SVGRenderer}
-         * object, like
-         * {@link Highcharts.SVGRenderer#rect|rect},
-         * {@link Highcharts.SVGRenderer#path|path},
-         * {@link Highcharts.SVGRenderer#text|text},
-         * {@link Highcharts.SVGRenderer#label|label},
-         * {@link Highcharts.SVGRenderer#g|g}
-         * and more.
-         *
-         * @class
-         * @name Highcharts.SVGElement
-         */
-        var SVGElement = /** @class */ (function () {
-                function SVGElement() {
-                    /* *
-                     *
-                     *  Properties
-                     *
-                     * */
-                    this.element = void 0;
-                this.height = void 0;
-                this.opacity = 1; // Default base for animation
-                this.renderer = void 0;
-                this.SVG_NS = SVG_NS;
-                // Custom attributes used for symbols, these should be filtered out when
-                // setting SVGElement attributes (#9375).
-                this.symbolCustomAttribs = [
-                    'x',
-                    'y',
-                    'width',
-                    'height',
-                    'r',
-                    'start',
-                    'end',
-                    'innerR',
-                    'anchorX',
-                    'anchorY',
-                    'rounded'
-                ];
-                this.width = void 0;
+            // Split on string
+            if (typeof path[i] === "string") {
+              if (segment.length) {
+                ret.push(segment.slice(0));
+              }
+              segment.length = 0;
             }
-            /* *
-             *
-             *  Functions
-             *
-             * */
-            /**
-             * Get the current value of an attribute or pseudo attribute,
-             * used mainly for animation. Called internally from
-             * the {@link Highcharts.SVGRenderer#attr} function.
-             *
-             * @private
-             * @function Highcharts.SVGElement#_defaultGetter
-             *
-             * @param {string} key
-             *        Property key.
-             *
-             * @return {number|string}
-             *         Property value.
-             */
-            SVGElement.prototype._defaultGetter = function (key) {
-                var ret = pick(this[key + 'Value'], // align getter
-                    this[key],
-                    this.element ? this.element.getAttribute(key) : null, 0);
-                if (/^[\-0-9\.]+$/.test(ret)) { // is numerical
-                    ret = parseFloat(ret);
-                }
-                return ret;
-            };
-            /**
-             * @private
-             * @function Highcharts.SVGElement#_defaultSetter
-             *
-             * @param {string} value
-             *
-             * @param {string} key
-             *
-             * @param {Highcharts.SVGDOMElement} element
-             *
-             * @return {void}
-             */
-            SVGElement.prototype._defaultSetter = function (value, key, element) {
-                element.setAttribute(key, value);
-            };
-            /**
-             * Add the element to the DOM. All elements must be added this way.
-             *
-             * @sample highcharts/members/renderer-g
-             *         Elements added to a group
-             *
-             * @function Highcharts.SVGElement#add
-             *
-             * @param {Highcharts.SVGElement} [parent]
-             *        The parent item to add it to. If undefined, the element is added
-             *        to the {@link Highcharts.SVGRenderer.box}.
-             *
-             * @return {Highcharts.SVGElement}
-             *         Returns the SVGElement for chaining.
-             */
-            SVGElement.prototype.add = function (parent) {
-                var renderer = this.renderer,
-                    element = this.element,
-                    inserted;
-                if (parent) {
-                    this.parentGroup = parent;
-                }
-                // Mark as inverted
-                this.parentInverted = parent && parent.inverted;
-                // Build formatted text
-                if (typeof this.textStr !== 'undefined' &&
-                    this.element.nodeName === 'text' // Not for SVGLabel instances
-                ) {
-                    renderer.buildText(this);
-                }
-                // Mark as added
-                this.added = true;
-                // If we're adding to renderer root, or other elements in the group
-                // have a z index, we need to handle it
-                if (!parent || parent.handleZ || this.zIndex) {
-                    inserted = this.zIndexSetter();
-                }
-                // If zIndex is not handled, append at the end
-                if (!inserted) {
-                    (parent ?
-                        parent.element :
-                        renderer.box).appendChild(element);
-                }
-                // fire an event for internal hooks
-                if (this.onAdd) {
-                    this.onAdd();
-                }
-                return this;
-            };
-            /**
-             * Add a class name to an element.
-             *
-             * @function Highcharts.SVGElement#addClass
-             *
-             * @param {string} className
-             * The new class name to add.
-             *
-             * @param {boolean} [replace=false]
-             * When true, the existing class name(s) will be overwritten with the new
-             * one. When false, the new one is added.
-             *
-             * @return {Highcharts.SVGElement}
-             * Return the SVG element for chainability.
-             */
-            SVGElement.prototype.addClass = function (className, replace) {
-                var currentClassName = replace ? '' : (this.attr('class') || '');
-                // Trim the string and remove duplicates
-                className = (className || '')
-                    .split(/ /g)
-                    .reduce(function (newClassName, name) {
-                    if (currentClassName.indexOf(name) === -1) {
-                        newClassName.push(name);
-                    }
-                    return newClassName;
-                }, (currentClassName ?
-                    [currentClassName] :
-                    []))
-                    .join(' ');
-                if (className !== currentClassName) {
-                    this.attr('class', className);
-                }
-                return this;
-            };
-            /**
-             * This method is executed in the end of `attr()`, after setting all
-             * attributes in the hash. In can be used to efficiently consolidate
-             * multiple attributes in one SVG property -- e.g., translate, rotate and
-             * scale are merged in one "transform" attribute in the SVG node.
-             *
-             * @private
-             * @function Highcharts.SVGElement#afterSetters
-             */
-            SVGElement.prototype.afterSetters = function () {
-                // Update transform. Do this outside the loop to prevent redundant
-                // updating for batch setting of attributes.
-                if (this.doTransform) {
-                    this.updateTransform();
-                    this.doTransform = false;
-                }
-            };
-            /**
-             * Align the element relative to the chart or another box.
-             *
-             * @function Highcharts.SVGElement#align
-             *
-             * @param {Highcharts.AlignObject} [alignOptions]
-             *        The alignment options. The function can be called without this
-             *        parameter in order to re-align an element after the box has been
-             *        updated.
-             *
-             * @param {boolean} [alignByTranslate]
-             *        Align element by translation.
-             *
-             * @param {string|Highcharts.BBoxObject} [box]
-             *        The box to align to, needs a width and height. When the box is a
-             *        string, it refers to an object in the Renderer. For example, when
-             *        box is `spacingBox`, it refers to `Renderer.spacingBox` which
-             *        holds `width`, `height`, `x` and `y` properties.
-             *
-             * @return {Highcharts.SVGElement} Returns the SVGElement for chaining.
-             */
-            SVGElement.prototype.align = function (alignOptions, alignByTranslate, box) {
-                var align,
-                    vAlign,
-                    x,
-                    y,
-                    attribs = {},
-                    alignTo,
-                    renderer = this.renderer,
-                    alignedObjects = renderer.alignedObjects,
-                    alignFactor,
-                    vAlignFactor;
-                // First call on instanciate
-                if (alignOptions) {
-                    this.alignOptions = alignOptions;
-                    this.alignByTranslate = alignByTranslate;
-                    if (!box || isString(box)) {
-                        this.alignTo = alignTo = box || 'renderer';
-                        // prevent duplicates, like legendGroup after resize
-                        erase(alignedObjects, this);
-                        alignedObjects.push(this);
-                        box = void 0; // reassign it below
+            segment.push(path[i]);
+          }
+          ret.push(segment.slice(0));
+          return ret;
+          /*
+                // Fully type-safe version where each tuple type is checked. The
+                // downside is filesize and a lack of flexibility for unsupported
+                // commands
+                const ret: SVGPath = [],
+                    commands = {
+                        A: 7,
+                        C: 6,
+                        H: 1,
+                        L: 2,
+                        M: 2,
+                        Q: 4,
+                        S: 4,
+                        T: 2,
+                        V: 1,
+                        Z: 0
+                    };
+
+                let i = 0,
+                    lastI = 0,
+                    lastCommand;
+
+                while (i < path.length) {
+                    const item = path[i];
+
+                    let command;
+
+                    if (typeof item === 'string') {
+                        command = item;
+                        i += 1;
+                    } else {
+                        command = lastCommand || 'M';
                     }
-                    // When called on resize, no arguments are supplied
-                }
-                else {
-                    alignOptions = this.alignOptions;
-                    alignByTranslate = this.alignByTranslate;
-                    alignTo = this.alignTo;
-                }
-                box = pick(box, renderer[alignTo], renderer);
-                // Assign variables
-                align = alignOptions.align;
-                vAlign = alignOptions.verticalAlign;
-                // default: left align
-                x = (box.x || 0) + (alignOptions.x || 0);
-                // default: top align
-                y = (box.y || 0) + (alignOptions.y || 0);
-                // Align
-                if (align === 'right') {
-                    alignFactor = 1;
-                }
-                else if (align === 'center') {
-                    alignFactor = 2;
-                }
-                if (alignFactor) {
-                    x += (box.width - (alignOptions.width || 0)) /
-                        alignFactor;
-                }
-                attribs[alignByTranslate ? 'translateX' : 'x'] = Math.round(x);
-                // Vertical align
-                if (vAlign === 'bottom') {
-                    vAlignFactor = 1;
-                }
-                else if (vAlign === 'middle') {
-                    vAlignFactor = 2;
-                }
-                if (vAlignFactor) {
-                    y += (box.height - (alignOptions.height || 0)) /
-                        vAlignFactor;
+
+                    // Upper case
+                    const commandUC = command.toUpperCase();
+
+                    if (commandUC in commands) {
+
+                        // No numeric parameters
+                        if (command === 'Z' || command === 'z') {
+                            ret.push([command]);
+
+                        // One numeric parameter
+                        } else {
+                            const val0 = path[i];
+                            if (typeof val0 === 'number') {
+
+                                // Horizontal line to
+                                if (command === 'H' || command === 'h') {
+                                    ret.push([command, val0]);
+                                    i += 1;
+
+                                // Vertical line to
+                                } else if (command === 'V' || command === 'v') {
+                                    ret.push([command, val0]);
+                                    i += 1;
+
+                                // Two numeric parameters
+                                } else {
+                                    const val1 = path[i + 1];
+                                    if (typeof val1 === 'number') {
+                                        // lineTo
+                                        if (command === 'L' || command === 'l') {
+                                            ret.push([command, val0, val1]);
+                                            i += 2;
+
+                                        // moveTo
+                                        } else if (command === 'M' || command === 'm') {
+                                            ret.push([command, val0, val1]);
+                                            i += 2;
+
+                                        // Smooth quadratic bezier
+                                        } else if (command === 'T' || command === 't') {
+                                            ret.push([command, val0, val1]);
+                                            i += 2;
+
+                                        // Four numeric parameters
+                                        } else {
+                                            const val2 = path[i + 2],
+                                                val3 = path[i + 3];
+                                            if (
+                                                typeof val2 === 'number' &&
+                                                typeof val3 === 'number'
+                                            ) {
+                                                // Quadratic bezier to
+                                                if (
+                                                    command === 'Q' ||
+                                                    command === 'q'
+                                                ) {
+                                                    ret.push([
+                                                        command,
+                                                        val0,
+                                                        val1,
+                                                        val2,
+                                                        val3
+                                                    ]);
+                                                    i += 4;
+
+                                                // Smooth cubic bezier to
+                                                } else if (
+                                                    command === 'S' ||
+                                                    command === 's'
+                                                ) {
+                                                    ret.push([
+                                                        command,
+                                                        val0,
+                                                        val1,
+                                                        val2,
+                                                        val3
+                                                    ]);
+                                                    i += 4;
+
+                                                // Six numeric parameters
+                                                } else {
+                                                    const val4 = path[i + 4],
+                                                        val5 = path[i + 5];
+
+                                                    if (
+                                                        typeof val4 === 'number' &&
+                                                        typeof val5 === 'number'
+                                                    ) {
+                                                        // Curve to
+                                                        if (
+                                                            command === 'C' ||
+                                                            command === 'c'
+                                                        ) {
+                                                            ret.push([
+                                                                command,
+                                                                val0,
+                                                                val1,
+                                                                val2,
+                                                                val3,
+                                                                val4,
+                                                                val5
+                                                            ]);
+                                                            i += 6;
+
+                                                        // Seven numeric parameters
+                                                        } else {
+                                                            const val6 = path[i + 6];
+
+                                                            // Arc to
+                                                            if (
+                                                                typeof val6 ===
+                                                                'number' &&
+                                                                (
+                                                                    command === 'A' ||
+                                                                    command === 'a'
+                                                                )
+                                                            ) {
+                                                                ret.push([
+                                                                    command,
+                                                                    val0,
+                                                                    val1,
+                                                                    val2,
+                                                                    val3,
+                                                                    val4,
+                                                                    val5,
+                                                                    val6
+                                                                ]);
+                                                                i += 7;
+
+                                                            }
+
+                                                        }
+                                                    }
+                                                }
+                                            }
+                                        }
+                                    }
+
+                                }
+                            }
+                        }
+                    }
+
+                    // An unmarked command following a moveTo is a lineTo
+                    lastCommand = command === 'M' ? 'L' : command;
+
+                    if (i === lastI) {
+                        break;
+                    }
+                    lastI = i;
                 }
-                attribs[alignByTranslate ? 'translateY' : 'y'] = Math.round(y);
-                // Animate only if already placed
-                this[this.placed ? 'animate' : 'attr'](attribs);
-                this.placed = true;
-                this.alignAttr = attribs;
-                return this;
-            };
+                return ret;
+                */
+        };
+        /**
+         * Draw a label, which is an extended text element with support for border
+         * and background. Highcharts creates a `g` element with a text and a `path`
+         * or `rect` inside, to make it behave somewhat like a HTML div. Border and
+         * background are set through `stroke`, `stroke-width` and `fill` attributes
+         * using the {@link Highcharts.SVGElement#attr|attr} method. To update the
+         * text after render, run `label.attr({ text: 'New text' })`.
+         *
+         * @sample highcharts/members/renderer-label-on-chart/
+         *         A label on the chart
+         *
+         * @function Highcharts.SVGRenderer#label
+         *
+         * @param {string} str
+         *        The initial text string or (subset) HTML to render.
+         *
+         * @param {number} x
+         *        The x position of the label's left side.
+         *
+         * @param {number} [y]
+         *        The y position of the label's top side or baseline, depending on
+         *        the `baseline` parameter.
+         *
+         * @param {string} [shape='rect']
+         *        The shape of the label's border/background, if any. Defaults to
+         *        `rect`. Other possible values are `callout` or other shapes
+         *        defined in {@link Highcharts.SVGRenderer#symbols}.
+         *
+         * @param {number} [anchorX]
+         *        In case the `shape` has a pointer, like a flag, this is the
+         *        coordinates it should be pinned to.
+         *
+         * @param {number} [anchorY]
+         *        In case the `shape` has a pointer, like a flag, this is the
+         *        coordinates it should be pinned to.
+         *
+         * @param {boolean} [useHTML=false]
+         *        Wether to use HTML to render the label.
+         *
+         * @param {boolean} [baseline=false]
+         *        Whether to position the label relative to the text baseline,
+         *        like {@link Highcharts.SVGRenderer#text|renderer.text}, or to the
+         *        upper border of the rectangle.
+         *
+         * @param {string} [className]
+         *        Class name for the group.
+         *
+         * @return {Highcharts.SVGElement}
+         *         The generated label.
+         */
+        SVGRenderer.prototype.label = function (
+          str,
+          x,
+          y,
+          shape,
+          anchorX,
+          anchorY,
+          useHTML,
+          baseline,
+          className
+        ) {
+          return new SVGLabel(
+            this,
+            str,
+            x,
+            y,
+            shape,
+            anchorX,
+            anchorY,
+            useHTML,
+            baseline,
+            className
+          );
+        };
+        return SVGRenderer;
+      })();
+      /**
+       * A pointer to the renderer's associated Element class. The VMLRenderer
+       * will have a pointer to VMLElement here.
+       *
+       * @name Highcharts.SVGRenderer#Element
+       * @type {Highcharts.SVGElement}
+       */
+      SVGRenderer.prototype.Element = SVGElement;
+      /**
+       * @private
+       */
+      SVGRenderer.prototype.SVG_NS = SVG_NS;
+      /**
+       * Dummy function for plugins, called every time the renderer is updated.
+       * Prior to Highcharts 5, this was used for the canvg renderer.
+       *
+       * @deprecated
+       * @function Highcharts.SVGRenderer#draw
+       */
+      SVGRenderer.prototype.draw = noop;
+      /**
+       * A collection of characters mapped to HTML entities. When `useHTML` on an
+       * element is true, these entities will be rendered correctly by HTML. In
+       * the SVG pseudo-HTML, they need to be unescaped back to simple characters,
+       * so for example `&lt;` will render as `<`.
+       *
+       * @example
+       * // Add support for unescaping quotes
+       * Highcharts.SVGRenderer.prototype.escapes['"'] = '&quot;';
+       *
+       * @name Highcharts.SVGRenderer#escapes
+       * @type {Highcharts.Dictionary<string>}
+       */
+      SVGRenderer.prototype.escapes = {
+        "&": "&amp;",
+        "<": "&lt;",
+        ">": "&gt;",
+        "'": "&#39;",
+        '"': "&quot;",
+      };
+      /**
+       * An extendable collection of functions for defining symbol paths.
+       *
+       * @name Highcharts.SVGRenderer#symbols
+       * @type {Highcharts.SymbolDictionary}
+       */
+      SVGRenderer.prototype.symbols = {
+        circle: function (x, y, w, h) {
+          // Return a full arc
+          return this.arc(x + w / 2, y + h / 2, w / 2, h / 2, {
+            start: Math.PI * 0.5,
+            end: Math.PI * 2.5,
+            open: false,
+          });
+        },
+        square: function (x, y, w, h) {
+          return [
+            ["M", x, y],
+            ["L", x + w, y],
+            ["L", x + w, y + h],
+            ["L", x, y + h],
+            ["Z"],
+          ];
+        },
+        triangle: function (x, y, w, h) {
+          return [
+            ["M", x + w / 2, y],
+            ["L", x + w, y + h],
+            ["L", x, y + h],
+            ["Z"],
+          ];
+        },
+        "triangle-down": function (x, y, w, h) {
+          return [["M", x, y], ["L", x + w, y], ["L", x + w / 2, y + h], ["Z"]];
+        },
+        diamond: function (x, y, w, h) {
+          return [
+            ["M", x + w / 2, y],
+            ["L", x + w, y + h / 2],
+            ["L", x + w / 2, y + h],
+            ["L", x, y + h / 2],
+            ["Z"],
+          ];
+        },
+        arc: function (x, y, w, h, options) {
+          var arc = [];
+          if (options) {
+            var start = options.start || 0,
+              end = options.end || 0,
+              rx = options.r || w,
+              ry = options.r || h || w,
+              proximity = 0.001,
+              fullCircle = Math.abs(end - start - 2 * Math.PI) < proximity,
+              // Substract a small number to prevent cos and sin of start and
+              // end from becoming equal on 360 arcs (related: #1561)
+              end = end - proximity,
+              innerRadius = options.innerR,
+              open = pick(options.open, fullCircle),
+              cosStart = Math.cos(start),
+              sinStart = Math.sin(start),
+              cosEnd = Math.cos(end),
+              sinEnd = Math.sin(end),
+              // Proximity takes care of rounding errors around PI (#6971)
+              longArc = pick(
+                options.longArc,
+                end - start - Math.PI < proximity ? 0 : 1
+              );
+            arc.push(
+              ["M", x + rx * cosStart, y + ry * sinStart],
+              [
+                "A",
+                rx,
+                ry,
+                0,
+                longArc,
+                pick(options.clockwise, 1),
+                x + rx * cosEnd,
+                y + ry * sinEnd,
+              ]
+            );
+            if (defined(innerRadius)) {
+              arc.push(
+                open
+                  ? ["M", x + innerRadius * cosEnd, y + innerRadius * sinEnd]
+                  : ["L", x + innerRadius * cosEnd, y + innerRadius * sinEnd],
+                [
+                  "A",
+                  innerRadius,
+                  innerRadius,
+                  0,
+                  longArc,
+                  // Clockwise - opposite to the outer arc clockwise
+                  defined(options.clockwise) ? 1 - options.clockwise : 0,
+                  x + innerRadius * cosStart,
+                  y + innerRadius * sinStart,
+                ]
+              );
+            }
+            if (!open) {
+              arc.push(["Z"]);
+            }
+          }
+          return arc;
+        },
+        /**
+         * Callout shape used for default tooltips, also used for rounded
+         * rectangles in VML
+         */
+        callout: function (x, y, w, h, options) {
+          var arrowLength = 6,
+            halfDistance = 6,
+            r = Math.min((options && options.r) || 0, w, h),
+            safeDistance = r + halfDistance,
+            anchorX = (options && options.anchorX) || 0,
+            anchorY = (options && options.anchorY) || 0,
+            path;
+          path = [
+            ["M", x + r, y],
+            ["L", x + w - r, y],
+            ["C", x + w, y, x + w, y, x + w, y + r],
+            ["L", x + w, y + h - r],
+            ["C", x + w, y + h, x + w, y + h, x + w - r, y + h],
+            ["L", x + r, y + h],
+            ["C", x, y + h, x, y + h, x, y + h - r],
+            ["L", x, y + r],
+            ["C", x, y, x, y, x + r, y], // top-left corner
+          ];
+          // Anchor on right side
+          if (anchorX && anchorX > w) {
+            // Chevron
+            if (anchorY > y + safeDistance && anchorY < y + h - safeDistance) {
+              path.splice(
+                3,
+                1,
+                ["L", x + w, anchorY - halfDistance],
+                ["L", x + w + arrowLength, anchorY],
+                ["L", x + w, anchorY + halfDistance],
+                ["L", x + w, y + h - r]
+              );
+              // Simple connector
+            } else {
+              path.splice(
+                3,
+                1,
+                ["L", x + w, h / 2],
+                ["L", anchorX, anchorY],
+                ["L", x + w, h / 2],
+                ["L", x + w, y + h - r]
+              );
+            }
+            // Anchor on left side
+          } else if (anchorX && anchorX < 0) {
+            // Chevron
+            if (anchorY > y + safeDistance && anchorY < y + h - safeDistance) {
+              path.splice(
+                7,
+                1,
+                ["L", x, anchorY + halfDistance],
+                ["L", x - arrowLength, anchorY],
+                ["L", x, anchorY - halfDistance],
+                ["L", x, y + r]
+              );
+              // Simple connector
+            } else {
+              path.splice(
+                7,
+                1,
+                ["L", x, h / 2],
+                ["L", anchorX, anchorY],
+                ["L", x, h / 2],
+                ["L", x, y + r]
+              );
+            }
+          } else if (
+            // replace bottom
+            anchorY &&
+            anchorY > h &&
+            anchorX > x + safeDistance &&
+            anchorX < x + w - safeDistance
+          ) {
+            path.splice(
+              5,
+              1,
+              ["L", anchorX + halfDistance, y + h],
+              ["L", anchorX, y + h + arrowLength],
+              ["L", anchorX - halfDistance, y + h],
+              ["L", x + r, y + h]
+            );
+          } else if (
+            // replace top
+            anchorY &&
+            anchorY < 0 &&
+            anchorX > x + safeDistance &&
+            anchorX < x + w - safeDistance
+          ) {
+            path.splice(
+              1,
+              1,
+              ["L", anchorX - halfDistance, y],
+              ["L", anchorX, y - arrowLength],
+              ["L", anchorX + halfDistance, y],
+              ["L", w - r, y]
+            );
+          }
+          return path;
+        },
+      };
+      H.SVGRenderer = SVGRenderer;
+      H.Renderer = H.SVGRenderer;
+
+      return H.Renderer;
+    }
+  );
+  _registerModule(
+    _modules,
+    "Core/Renderer/HTML/HTMLElement.js",
+    [
+      _modules["Core/Globals.js"],
+      _modules["Core/Renderer/SVG/SVGElement.js"],
+      _modules["Core/Utilities.js"],
+    ],
+    function (H, SVGElement, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      var css = U.css,
+        defined = U.defined,
+        extend = U.extend,
+        pick = U.pick,
+        pInt = U.pInt;
+      /**
+       * Element placebo
+       * @private
+       */
+      var HTMLElement = SVGElement;
+      var isFirefox = H.isFirefox;
+      /* eslint-disable valid-jsdoc */
+      // Extend SvgElement for useHTML option.
+      extend(
+        HTMLElement.prototype,
+        /** @lends SVGElement.prototype */ {
+          /**
+           * Apply CSS to HTML elements. This is used in text within SVG rendering and
+           * by the VML renderer
+           *
+           * @private
+           * @function Highcharts.SVGElement#htmlCss
+           *
+           * @param {Highcharts.CSSObject} styles
+           *
+           * @return {Highcharts.SVGElement}
+           */
+          htmlCss: function (styles) {
+            var wrapper = this,
+              element = wrapper.element,
+              // When setting or unsetting the width style, we need to update
+              // transform (#8809)
+              isSettingWidth =
+                element.tagName === "SPAN" && styles && "width" in styles,
+              textWidth = pick(isSettingWidth && styles.width, void 0),
+              doTransform;
+            if (isSettingWidth) {
+              delete styles.width;
+              wrapper.textWidth = textWidth;
+              doTransform = true;
+            }
+            if (styles && styles.textOverflow === "ellipsis") {
+              styles.whiteSpace = "nowrap";
+              styles.overflow = "hidden";
+            }
+            wrapper.styles = extend(wrapper.styles, styles);
+            css(wrapper.element, styles);
+            // Now that all styles are applied, to the transform
+            if (doTransform) {
+              wrapper.htmlUpdateTransform();
+            }
+            return wrapper;
+          },
+          /**
+           * VML and useHTML method for calculating the bounding box based on offsets.
+           *
+           * @private
+           * @function Highcharts.SVGElement#htmlGetBBox
+           *
+           * @param {boolean} refresh
+           *        Whether to force a fresh value from the DOM or to use the cached
+           *        value.
+           *
+           * @return {Highcharts.BBoxObject}
+           *         A hash containing values for x, y, width and height.
+           */
+          htmlGetBBox: function () {
+            var wrapper = this,
+              element = wrapper.element;
+            return {
+              x: element.offsetLeft,
+              y: element.offsetTop,
+              width: element.offsetWidth,
+              height: element.offsetHeight,
+            };
+          },
+          /**
+           * VML override private method to update elements based on internal
+           * properties based on SVG transform.
+           *
+           * @private
+           * @function Highcharts.SVGElement#htmlUpdateTransform
+           * @return {void}
+           */
+          htmlUpdateTransform: function () {
+            // aligning non added elements is expensive
+            if (!this.added) {
+              this.alignOnAdd = true;
+              return;
+            }
+            var wrapper = this,
+              renderer = wrapper.renderer,
+              elem = wrapper.element,
+              translateX = wrapper.translateX || 0,
+              translateY = wrapper.translateY || 0,
+              x = wrapper.x || 0,
+              y = wrapper.y || 0,
+              align = wrapper.textAlign || "left",
+              alignCorrection = {
+                left: 0,
+                center: 0.5,
+                right: 1,
+              }[align],
+              styles = wrapper.styles,
+              whiteSpace = styles && styles.whiteSpace;
             /**
              * @private
-             * @function Highcharts.SVGElement#alignSetter
-             * @param {"left"|"center"|"right"} value
-             */
-            SVGElement.prototype.alignSetter = function (value) {
-                var convert = {
-                        left: 'start',
-                        center: 'middle',
-                        right: 'end'
-                    };
-                if (convert[value]) {
-                    this.alignValue = value;
-                    this.element.setAttribute('text-anchor', convert[value]);
-                }
-            };
-            /**
-             * Animate to given attributes or CSS properties.
-             *
-             * @sample highcharts/members/element-on/
-             *         Setting some attributes by animation
-             *
-             * @function Highcharts.SVGElement#animate
-             *
-             * @param {Highcharts.SVGAttributes} params
-             *        SVG attributes or CSS to animate.
-             *
-             * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [options]
-             *        Animation options.
-             *
-             * @param {Function} [complete]
-             *        Function to perform at the end of animation.
-             *
-             * @return {Highcharts.SVGElement}
-             *         Returns the SVGElement for chaining.
+             * @return {number}
              */
-            SVGElement.prototype.animate = function (params, options, complete) {
-                var _this = this;
-                var animOptions = animObject(pick(options,
-                    this.renderer.globalAnimation,
-                    true)),
-                    deferTime = animOptions.defer;
-                // When the page is hidden save resources in the background by not
-                // running animation at all (#9749).
-                if (pick(doc.hidden, doc.msHidden, doc.webkitHidden, false)) {
-                    animOptions.duration = 0;
-                }
-                if (animOptions.duration !== 0) {
-                    // allows using a callback with the global animation without
-                    // overwriting it
-                    if (complete) {
-                        animOptions.complete = complete;
+            function getTextPxLength() {
+              // Reset multiline/ellipsis in order to read width (#4928,
+              // #5417)
+              css(elem, {
+                width: "",
+                whiteSpace: whiteSpace || "nowrap",
+              });
+              return elem.offsetWidth;
+            }
+            // apply translate
+            css(elem, {
+              marginLeft: translateX,
+              marginTop: translateY,
+            });
+            if (!renderer.styledMode && wrapper.shadows) {
+              // used in labels/tooltip
+              wrapper.shadows.forEach(function (shadow) {
+                css(shadow, {
+                  marginLeft: translateX + 1,
+                  marginTop: translateY + 1,
+                });
+              });
+            }
+            // apply inversion
+            if (wrapper.inverted) {
+              // wrapper is a group
+              [].forEach.call(elem.childNodes, function (child) {
+                renderer.invertChild(child, elem);
+              });
+            }
+            if (elem.tagName === "SPAN") {
+              var rotation = wrapper.rotation,
+                baseline,
+                textWidth = wrapper.textWidth && pInt(wrapper.textWidth),
+                currentTextTransform = [
+                  rotation,
+                  align,
+                  elem.innerHTML,
+                  wrapper.textWidth,
+                  wrapper.textAlign,
+                ].join(",");
+              // Update textWidth. Use the memoized textPxLength if possible, to
+              // avoid the getTextPxLength function using elem.offsetWidth.
+              // Calling offsetWidth affects rendering time as it forces layout
+              // (#7656).
+              if (
+                textWidth !== wrapper.oldTextWidth &&
+                (textWidth > wrapper.oldTextWidth ||
+                  (wrapper.textPxLength || getTextPxLength()) > textWidth) &&
+                // Only set the width if the text is able to word-wrap, or
+                // text-overflow is ellipsis (#9537)
+                (/[ \-]/.test(elem.textContent || elem.innerText) ||
+                  elem.style.textOverflow === "ellipsis")
+              ) {
+                // #983, #1254
+                css(elem, {
+                  width: textWidth + "px",
+                  display: "block",
+                  whiteSpace: whiteSpace || "normal", // #3331
+                });
+                wrapper.oldTextWidth = textWidth;
+                wrapper.hasBoxWidthChanged = true; // #8159
+              } else {
+                wrapper.hasBoxWidthChanged = false; // #8159
+              }
+              // Do the calculations and DOM access only if properties changed
+              if (currentTextTransform !== wrapper.cTT) {
+                baseline = renderer.fontMetrics(elem.style.fontSize, elem).b;
+                // Renderer specific handling of span rotation, but only if we
+                // have something to update.
+                if (
+                  defined(rotation) &&
+                  (rotation !== (wrapper.oldRotation || 0) ||
+                    align !== wrapper.oldAlign)
+                ) {
+                  wrapper.setSpanRotation(rotation, alignCorrection, baseline);
+                }
+                wrapper.getSpanCorrection(
+                  // Avoid elem.offsetWidth if we can, it affects rendering
+                  // time heavily (#7656)
+                  (!defined(rotation) && wrapper.textPxLength) || // #7920
+                    elem.offsetWidth,
+                  baseline,
+                  alignCorrection,
+                  rotation,
+                  align
+                );
+              }
+              // apply position with correction
+              css(elem, {
+                left: x + (wrapper.xCorr || 0) + "px",
+                top: y + (wrapper.yCorr || 0) + "px",
+              });
+              // record current text transform
+              wrapper.cTT = currentTextTransform;
+              wrapper.oldRotation = rotation;
+              wrapper.oldAlign = align;
+            }
+          },
+          /**
+           * Set the rotation of an individual HTML span.
+           *
+           * @private
+           * @function Highcharts.SVGElement#setSpanRotation
+           * @param {number} rotation
+           * @param {number} alignCorrection
+           * @param {number} baseline
+           * @return {void}
+           */
+          setSpanRotation: function (rotation, alignCorrection, baseline) {
+            var rotationStyle = {},
+              cssTransformKey = this.renderer.getTransformKey();
+            rotationStyle[cssTransformKey] = rotationStyle.transform =
+              "rotate(" + rotation + "deg)";
+            rotationStyle[
+              cssTransformKey + (isFirefox ? "Origin" : "-origin")
+            ] = rotationStyle.transformOrigin =
+              alignCorrection * 100 + "% " + baseline + "px";
+            css(this.element, rotationStyle);
+          },
+          /**
+           * Get the correction in X and Y positioning as the element is rotated.
+           *
+           * @private
+           * @function Highcharts.SVGElement#getSpanCorrection
+           * @param {number} width
+           * @param {number} baseline
+           * @param {number} alignCorrection
+           * @return {void}
+           */
+          getSpanCorrection: function (width, baseline, alignCorrection) {
+            this.xCorr = -width * alignCorrection;
+            this.yCorr = -baseline;
+          },
+        }
+      );
+
+      return HTMLElement;
+    }
+  );
+  _registerModule(
+    _modules,
+    "Core/Renderer/HTML/HTMLRenderer.js",
+    [
+      _modules["Core/Globals.js"],
+      _modules["Core/Renderer/SVG/SVGElement.js"],
+      _modules["Core/Renderer/SVG/SVGRenderer.js"],
+      _modules["Core/Utilities.js"],
+    ],
+    function (H, SVGElement, SVGRenderer, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      var isFirefox = H.isFirefox,
+        isMS = H.isMS,
+        isWebKit = H.isWebKit,
+        win = H.win;
+      var attr = U.attr,
+        createElement = U.createElement,
+        extend = U.extend,
+        pick = U.pick;
+      /**
+       * Renderer placebo
+       * @private
+       */
+      var HTMLRenderer = SVGRenderer;
+      /* eslint-disable valid-jsdoc */
+      // Extend SvgRenderer for useHTML option.
+      extend(
+        SVGRenderer.prototype,
+        /** @lends SVGRenderer.prototype */ {
+          /**
+           * @private
+           * @function Highcharts.SVGRenderer#getTransformKey
+           *
+           * @return {string}
+           */
+          getTransformKey: function () {
+            return isMS && !/Edge/.test(win.navigator.userAgent)
+              ? "-ms-transform"
+              : isWebKit
+              ? "-webkit-transform"
+              : isFirefox
+              ? "MozTransform"
+              : win.opera
+              ? "-o-transform"
+              : "";
+          },
+          /**
+           * Create HTML text node. This is used by the VML renderer as well as the
+           * SVG renderer through the useHTML option.
+           *
+           * @private
+           * @function Highcharts.SVGRenderer#html
+           *
+           * @param {string} str
+           *        The text of (subset) HTML to draw.
+           *
+           * @param {number} x
+           *        The x position of the text's lower left corner.
+           *
+           * @param {number} y
+           *        The y position of the text's lower left corner.
+           *
+           * @return {Highcharts.HTMLDOMElement}
+           */
+          html: function (str, x, y) {
+            var wrapper = this.createElement("span"),
+              element = wrapper.element,
+              renderer = wrapper.renderer,
+              isSVG = renderer.isSVG,
+              addSetters = function (gWrapper, style) {
+                // These properties are set as attributes on the SVG group, and
+                // as identical CSS properties on the div. (#3542)
+                ["opacity", "visibility"].forEach(function (prop) {
+                  gWrapper[prop + "Setter"] = function (value, key, elem) {
+                    var styleObject = gWrapper.div ? gWrapper.div.style : style;
+                    SVGElement.prototype[prop + "Setter"].call(
+                      this,
+                      value,
+                      key,
+                      elem
+                    );
+                    if (styleObject) {
+                      styleObject[key] = value;
                     }
-                    // If defer option is defined delay the animation #12901
-                    syncTimeout(function () {
-                        if (_this.element) {
-                            animate(_this, params, animOptions);
-                        }
-                    }, deferTime);
+                  };
+                });
+                gWrapper.addedSetters = true;
+              };
+            // Text setter
+            wrapper.textSetter = function (value) {
+              if (value !== element.innerHTML) {
+                delete this.bBox;
+                delete this.oldTextWidth;
+              }
+              this.textStr = value;
+              element.innerHTML = pick(value, "");
+              wrapper.doTransform = true;
+            };
+            // Add setters for the element itself (#4938)
+            if (isSVG) {
+              // #4938, only for HTML within SVG
+              addSetters(wrapper, wrapper.element.style);
+            }
+            // Various setters which rely on update transform
+            wrapper.xSetter =
+              wrapper.ySetter =
+              wrapper.alignSetter =
+              wrapper.rotationSetter =
+                function (value, key) {
+                  if (key === "align") {
+                    // Do not overwrite the SVGElement.align method. Same as VML.
+                    wrapper.alignValue = wrapper.textAlign = value;
+                  } else {
+                    wrapper[key] = value;
+                  }
+                  wrapper.doTransform = true;
+                };
+            // Runs at the end of .attr()
+            wrapper.afterSetters = function () {
+              // Update transform. Do this outside the loop to prevent redundant
+              // updating for batch setting of attributes.
+              if (this.doTransform) {
+                this.htmlUpdateTransform();
+                this.doTransform = false;
+              }
+            };
+            // Set the default attributes
+            wrapper
+              .attr({
+                text: str,
+                x: Math.round(x),
+                y: Math.round(y),
+              })
+              .css({
+                position: "absolute",
+              });
+            if (!renderer.styledMode) {
+              wrapper.css({
+                fontFamily: this.style.fontFamily,
+                fontSize: this.style.fontSize,
+              });
+            }
+            // Keep the whiteSpace style outside the wrapper.styles collection
+            element.style.whiteSpace = "nowrap";
+            // Use the HTML specific .css method
+            wrapper.css = wrapper.htmlCss;
+            // This is specific for HTML within SVG
+            if (isSVG) {
+              wrapper.add = function (svgGroupWrapper) {
+                var htmlGroup,
+                  container = renderer.box.parentNode,
+                  parentGroup,
+                  parents = [];
+                this.parentGroup = svgGroupWrapper;
+                // Create a mock group to hold the HTML elements
+                if (svgGroupWrapper) {
+                  htmlGroup = svgGroupWrapper.div;
+                  if (!htmlGroup) {
+                    // Read the parent chain into an array and read from top
+                    // down
+                    parentGroup = svgGroupWrapper;
+                    while (parentGroup) {
+                      parents.push(parentGroup);
+                      // Move up to the next parent group
+                      parentGroup = parentGroup.parentGroup;
+                    }
+                    // Ensure dynamically updating position when any parent
+                    // is translated
+                    parents.reverse().forEach(function (parentGroup) {
+                      var htmlGroupStyle,
+                        cls = attr(parentGroup.element, "class");
+                      /**
+                       * Common translate setter for X and Y on the HTML
+                       * group. Reverted the fix for #6957 du to
+                       * positioning problems and offline export (#7254,
+                       * #7280, #7529)
+                       * @private
+                       * @param {*} value
+                       * @param {string} key
+                       * @return {void}
+                       */
+                      function translateSetter(value, key) {
+                        parentGroup[key] = value;
+                        if (key === "translateX") {
+                          htmlGroupStyle.left = value + "px";
+                        } else {
+                          htmlGroupStyle.top = value + "px";
+                        }
+                        parentGroup.doTransform = true;
+                      }
+                      // Create a HTML div and append it to the parent div
+                      // to emulate the SVG group structure
+                      htmlGroup = parentGroup.div =
+                        parentGroup.div ||
+                        createElement(
+                          "div",
+                          cls ? { className: cls } : void 0,
+                          {
+                            position: "absolute",
+                            left: (parentGroup.translateX || 0) + "px",
+                            top: (parentGroup.translateY || 0) + "px",
+                            display: parentGroup.display,
+                            opacity: parentGroup.opacity,
+                            pointerEvents:
+                              parentGroup.styles &&
+                              parentGroup.styles.pointerEvents, // #5595
+                            // the top group is appended to container
+                          },
+                          htmlGroup || container
+                        );
+                      // Shortcut
+                      htmlGroupStyle = htmlGroup.style;
+                      // Set listeners to update the HTML div's position
+                      // whenever the SVG group position is changed.
+                      extend(parentGroup, {
+                        // (#7287) Pass htmlGroup to use
+                        // the related group
+                        classSetter: (function (htmlGroup) {
+                          return function (value) {
+                            this.element.setAttribute("class", value);
+                            htmlGroup.className = value;
+                          };
+                        })(htmlGroup),
+                        on: function () {
+                          if (parents[0].div) {
+                            // #6418
+                            wrapper.on.apply(
+                              { element: parents[0].div },
+                              arguments
+                            );
+                          }
+                          return parentGroup;
+                        },
+                        translateXSetter: translateSetter,
+                        translateYSetter: translateSetter,
+                      });
+                      if (!parentGroup.addedSetters) {
+                        addSetters(parentGroup);
+                      }
+                    });
+                  }
+                } else {
+                  htmlGroup = container;
                 }
-                else {
-                    this.attr(params, void 0, complete);
-                    // Call the end step synchronously
-                    objectEach(params, function (val, prop) {
-                        if (animOptions.step) {
-                            animOptions.step.call(this, val, { prop: prop, pos: 1 });
-                        }
-                    }, this);
+                htmlGroup.appendChild(element);
+                // Shared with VML:
+                wrapper.added = true;
+                if (wrapper.alignOnAdd) {
+                  wrapper.htmlUpdateTransform();
                 }
-                return this;
-            };
-            /**
-             * Apply a text outline through a custom CSS property, by copying the text
-             * element and apply stroke to the copy. Used internally. Contrast checks at
-             * [example](https://jsfiddle.net/highcharts/43soe9m1/2/).
-             *
-             * @example
-             * // Specific color
-             * text.css({
-             *    textOutline: '1px black'
-             * });
-             * // Automatic contrast
-             * text.css({
-             *    color: '#000000', // black text
-             *    textOutline: '1px contrast' // => white outline
-             * });
-             *
-             * @private
-             * @function Highcharts.SVGElement#applyTextOutline
-             *
-             * @param {string} textOutline
-             *        A custom CSS `text-outline` setting, defined by `width color`.
-             */
-            SVGElement.prototype.applyTextOutline = function (textOutline) {
-                var elem = this.element,
-                    tspans,
-                    hasContrast = textOutline.indexOf('contrast') !== -1,
-                    styles = {},
-                    color,
-                    strokeWidth,
-                    firstRealChild;
-                // When the text shadow is set to contrast, use dark stroke for light
-                // text and vice versa.
-                if (hasContrast) {
-                    styles.textOutline = textOutline = textOutline.replace(/contrast/g, this.renderer.getContrast(elem.style.fill));
-                }
-                // Extract the stroke width and color
-                textOutline = textOutline.split(' ');
-                color = textOutline[textOutline.length - 1];
-                strokeWidth = textOutline[0];
-                if (strokeWidth && strokeWidth !== 'none' && H.svg) {
-                    this.fakeTS = true; // Fake text shadow
-                    tspans = [].slice.call(elem.getElementsByTagName('tspan'));
-                    // In order to get the right y position of the clone,
-                    // copy over the y setter
-                    this.ySetter = this.xSetter;
-                    // Since the stroke is applied on center of the actual outline, we
-                    // need to double it to get the correct stroke-width outside the
-                    // glyphs.
-                    strokeWidth = strokeWidth.replace(/(^[\d\.]+)(.*?)$/g, function (match, digit, unit) {
-                        return (2 * digit) + unit;
-                    });
-                    // Remove shadows from previous runs.
-                    this.removeTextOutline(tspans);
-                    // Check if the element contains RTL characters.
-                    // Comparing against Hebrew and Arabic characters,
-                    // excluding Arabic digits. Source:
-                    // https://www.unicode.org/Public/UNIDATA/extracted/DerivedBidiClass.txt
-                    var isRTL_1 = elem.textContent ?
-                            /^[\u0591-\u065F\u066A-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC]/
-                                .test(elem.textContent) : false;
-                    // For each of the tspans, create a stroked copy behind it.
-                    firstRealChild = elem.firstChild;
-                    tspans.forEach(function (tspan, y) {
-                        var clone;
-                        // Let the first line start at the correct X position
-                        if (y === 0) {
-                            tspan.setAttribute('x', elem.getAttribute('x'));
-                            y = elem.getAttribute('y');
-                            tspan.setAttribute('y', y || 0);
-                            if (y === null) {
-                                elem.setAttribute('y', 0);
-                            }
-                        }
-                        // Create the clone and apply outline properties.
-                        // For RTL elements apply outline properties for orginal element
-                        // to prevent outline from overlapping the text.
-                        // For RTL in Firefox keep the orginal order (#10162).
-                        clone = tspan.cloneNode(true);
-                        attr((isRTL_1 && !isFirefox) ? tspan : clone, {
-                            'class': 'highcharts-text-outline',
-                            fill: color,
-                            stroke: color,
-                            'stroke-width': strokeWidth,
-                            'stroke-linejoin': 'round'
-                        });
-                        elem.insertBefore(clone, firstRealChild);
-                    });
-                    // Create a whitespace between tspan and clone,
-                    // to fix the display of Arabic characters in Firefox.
-                    if (isRTL_1 && isFirefox && tspans[0]) {
-                        var whitespace = tspans[0].cloneNode(true);
-                        whitespace.textContent = ' ';
-                        elem.insertBefore(whitespace, firstRealChild);
-                    }
-                }
-            };
-            /**
-             * @function Highcharts.SVGElement#attr
-             * @param {string} key
-             * @return {number|string}
-             */ /**
-            * Apply native and custom attributes to the SVG elements.
-            *
-            * In order to set the rotation center for rotation, set x and y to 0 and
-            * use `translateX` and `translateY` attributes to position the element
-            * instead.
-            *
-            * Attributes frequently used in Highcharts are `fill`, `stroke`,
-            * `stroke-width`.
-            *
-            * @sample highcharts/members/renderer-rect/
-            *         Setting some attributes
-            *
-            * @example
-            * // Set multiple attributes
-            * element.attr({
-            *     stroke: 'red',
-            *     fill: 'blue',
-            *     x: 10,
-            *     y: 10
-            * });
-            *
-            * // Set a single attribute
-            * element.attr('stroke', 'red');
-            *
-            * // Get an attribute
-            * element.attr('stroke'); // => 'red'
-            *
-            * @function Highcharts.SVGElement#attr
-            *
-            * @param {string|Highcharts.SVGAttributes} [hash]
-            *        The native and custom SVG attributes.
-            *
-            * @param {number|string|Highcharts.SVGPathArray} [val]
-            *        If the type of the first argument is `string`, the second can be a
-            *        value, which will serve as a single attribute setter. If the first
-            *        argument is a string and the second is undefined, the function
-            *        serves as a getter and the current value of the property is
-            *        returned.
-            *
-            * @param {Function} [complete]
-            *        A callback function to execute after setting the attributes. This
-            *        makes the function compliant and interchangeable with the
-            *        {@link SVGElement#animate} function.
-            *
-            * @param {boolean} [continueAnimation=true]
-            *        Used internally when `.attr` is called as part of an animation
-            *        step. Otherwise, calling `.attr` for an attribute will stop
-            *        animation for that attribute.
-            *
-            * @return {Highcharts.SVGElement}
-            *         If used as a setter, it returns the current
-            *         {@link Highcharts.SVGElement} so the calls can be chained. If
-            *         used as a getter, the current value of the attribute is returned.
-            */
-            SVGElement.prototype.attr = function (hash, val, complete, continueAnimation) {
-                var key,
-                    element = this.element,
-                    hasSetSymbolSize,
-                    ret = this,
-                    skipAttr,
-                    setter,
-                    symbolCustomAttribs = this.symbolCustomAttribs;
-                // single key-value pair
-                if (typeof hash === 'string' && typeof val !== 'undefined') {
-                    key = hash;
-                    hash = {};
-                    hash[key] = val;
-                }
-                // used as a getter: first argument is a string, second is undefined
-                if (typeof hash === 'string') {
-                    ret = (this[hash + 'Getter'] ||
-                        this._defaultGetter).call(this, hash, element);
-                    // setter
-                }
-                else {
-                    objectEach(hash, function eachAttribute(val, key) {
-                        skipAttr = false;
-                        // Unless .attr is from the animator update, stop current
-                        // running animation of this property
-                        if (!continueAnimation) {
-                            stop(this, key);
-                        }
-                        // Special handling of symbol attributes
-                        if (this.symbolName &&
-                            symbolCustomAttribs.indexOf(key) !== -1) {
-                            if (!hasSetSymbolSize) {
-                                this.symbolAttr(hash);
-                                hasSetSymbolSize = true;
-                            }
-                            skipAttr = true;
-                        }
-                        if (this.rotation && (key === 'x' || key === 'y')) {
-                            this.doTransform = true;
-                        }
-                        if (!skipAttr) {
-                            setter = (this[key + 'Setter'] ||
-                                this._defaultSetter);
-                            setter.call(this, val, key, element);
-                            // Let the shadow follow the main element
-                            if (!this.styledMode &&
-                                this.shadows &&
-                                /^(width|height|visibility|x|y|d|transform|cx|cy|r)$/.test(key)) {
-                                this.updateShadows(key, val, setter);
-                            }
-                        }
-                    }, this);
-                    this.afterSetters();
-                }
-                // In accordance with animate, run a complete callback
-                if (complete) {
-                    complete.call(this);
-                }
-                return ret;
-            };
-            /**
-             * Apply a clipping rectangle to this element.
-             *
-             * @function Highcharts.SVGElement#clip
-             *
-             * @param {Highcharts.ClipRectElement} [clipRect]
-             *        The clipping rectangle. If skipped, the current clip is removed.
-             *
-             * @return {Highcharts.SVGElement}
-             *         Returns the SVG element to allow chaining.
-             */
-            SVGElement.prototype.clip = function (clipRect) {
-                return this.attr('clip-path', clipRect ?
-                    'url(' + this.renderer.url + '#' + clipRect.id + ')' :
-                    'none');
-            };
-            /**
-             * Calculate the coordinates needed for drawing a rectangle crisply and
-             * return the calculated attributes.
-             *
-             * @function Highcharts.SVGElement#crisp
-             *
-             * @param {Highcharts.RectangleObject} rect
-             * Rectangle to crisp.
-             *
-             * @param {number} [strokeWidth]
-             * The stroke width to consider when computing crisp positioning. It can
-             * also be set directly on the rect parameter.
-             *
-             * @return {Highcharts.RectangleObject}
-             * The modified rectangle arguments.
-             */
-            SVGElement.prototype.crisp = function (rect, strokeWidth) {
-                var wrapper = this,
-                    normalizer;
-                strokeWidth = strokeWidth || rect.strokeWidth || 0;
-                // Math.round because strokeWidth can sometimes have roundoff errors
-                normalizer = Math.round(strokeWidth) % 2 / 2;
-                // normalize for crisp edges
-                rect.x = Math.floor(rect.x || wrapper.x || 0) + normalizer;
-                rect.y = Math.floor(rect.y || wrapper.y || 0) + normalizer;
-                rect.width = Math.floor((rect.width || wrapper.width || 0) - 2 * normalizer);
-                rect.height = Math.floor((rect.height || wrapper.height || 0) - 2 * normalizer);
-                if (defined(rect.strokeWidth)) {
-                    rect.strokeWidth = strokeWidth;
-                }
-                return rect;
-            };
-            /**
-             * Build and apply an SVG gradient out of a common JavaScript configuration
-             * object. This function is called from the attribute setters. An event
-             * hook is added for supporting other complex color types.
-             *
-             * @private
-             * @function Highcharts.SVGElement#complexColor
-             *
-             * @param {Highcharts.GradientColorObject|Highcharts.PatternObject} colorOptions
-             * The gradient or pattern options structure.
-             *
-             * @param {string} prop
-             * The property to apply, can either be `fill` or `stroke`.
-             *
-             * @param {Highcharts.SVGDOMElement} elem
-             * SVG element to apply the gradient on.
-             */
-            SVGElement.prototype.complexColor = function (colorOptions, prop, elem) {
-                var renderer = this.renderer,
-                    colorObject,
-                    gradName,
-                    gradAttr,
-                    radAttr,
-                    gradients,
-                    stops,
-                    stopColor,
-                    stopOpacity,
-                    radialReference,
-                    id,
-                    key = [],
-                    value;
-                fireEvent(this.renderer, 'complexColor', {
-                    args: arguments
-                }, function () {
-                    // Apply linear or radial gradients
-                    if (colorOptions.radialGradient) {
-                        gradName = 'radialGradient';
-                    }
-                    else if (colorOptions.linearGradient) {
-                        gradName = 'linearGradient';
-                    }
-                    if (gradName) {
-                        gradAttr = colorOptions[gradName];
-                        gradients = renderer.gradients;
-                        stops = colorOptions.stops;
-                        radialReference = elem.radialReference;
-                        // Keep < 2.2 kompatibility
-                        if (isArray(gradAttr)) {
-                            colorOptions[gradName] = gradAttr = {
-                                x1: gradAttr[0],
-                                y1: gradAttr[1],
-                                x2: gradAttr[2],
-                                y2: gradAttr[3],
-                                gradientUnits: 'userSpaceOnUse'
-                            };
-                        }
-                        // Correct the radial gradient for the radial reference system
-                        if (gradName === 'radialGradient' &&
-                            radialReference &&
-                            !defined(gradAttr.gradientUnits)) {
-                            // Save the radial attributes for updating
-                            radAttr = gradAttr;
-                            gradAttr = merge(gradAttr, renderer.getRadialAttr(radialReference, radAttr), { gradientUnits: 'userSpaceOnUse' });
-                        }
-                        // Build the unique key to detect whether we need to create a
-                        // new element (#1282)
-                        objectEach(gradAttr, function (val, n) {
-                            if (n !== 'id') {
-                                key.push(n, val);
-                            }
-                        });
-                        objectEach(stops, function (val) {
-                            key.push(val);
-                        });
-                        key = key.join(',');
-                        // Check if a gradient object with the same config object is
-                        // created within this renderer
-                        if (gradients[key]) {
-                            id = gradients[key].attr('id');
-                        }
-                        else {
-                            // Set the id and create the element
-                            gradAttr.id = id = uniqueKey();
-                            var gradientObject_1 = gradients[key] =
-                                    renderer.createElement(gradName)
-                                        .attr(gradAttr)
-                                        .add(renderer.defs);
-                            gradientObject_1.radAttr = radAttr;
-                            // The gradient needs to keep a list of stops to be able to
-                            // destroy them
-                            gradientObject_1.stops = [];
-                            stops.forEach(function (stop) {
-                                var stopObject;
-                                if (stop[1].indexOf('rgba') === 0) {
-                                    colorObject = Color.parse(stop[1]);
-                                    stopColor = colorObject.get('rgb');
-                                    stopOpacity = colorObject.get('a');
-                                }
-                                else {
-                                    stopColor = stop[1];
-                                    stopOpacity = 1;
-                                }
-                                stopObject = renderer.createElement('stop').attr({
-                                    offset: stop[0],
-                                    'stop-color': stopColor,
-                                    'stop-opacity': stopOpacity
-                                }).add(gradientObject_1);
-                                // Add the stop element to the gradient
-                                gradientObject_1.stops.push(stopObject);
-                            });
-                        }
-                        // Set the reference to the gradient object
-                        value = 'url(' + renderer.url + '#' + id + ')';
-                        elem.setAttribute(prop, value);
-                        elem.gradient = key;
-                        // Allow the color to be concatenated into tooltips formatters
-                        // etc. (#2995)
-                        colorOptions.toString = function () {
-                            return value;
-                        };
-                    }
-                });
-            };
-            /**
-             * Set styles for the element. In addition to CSS styles supported by
-             * native SVG and HTML elements, there are also some custom made for
-             * Highcharts, like `width`, `ellipsis` and `textOverflow` for SVG text
-             * elements.
-             *
-             * @sample highcharts/members/renderer-text-on-chart/
-             *         Styled text
-             *
-             * @function Highcharts.SVGElement#css
-             *
-             * @param {Highcharts.CSSObject} styles
-             *        The new CSS styles.
-             *
-             * @return {Highcharts.SVGElement}
-             *         Return the SVG element for chaining.
-             */
-            SVGElement.prototype.css = function (styles) {
-                var oldStyles = this.styles, newStyles = {}, elem = this.element, textWidth, serializedCss = '', hyphenate, hasNew = !oldStyles, 
-                    // These CSS properties are interpreted internally by the SVG
-                    // renderer, but are not supported by SVG and should not be added to
-                    // the DOM. In styled mode, no CSS should find its way to the DOM
-                    // whatsoever (#6173, #6474).
-                    svgPseudoProps = ['textOutline', 'textOverflow', 'width'];
-                // convert legacy
-                if (styles && styles.color) {
-                    styles.fill = styles.color;
-                }
-                // Filter out existing styles to increase performance (#2640)
-                if (oldStyles) {
-                    objectEach(styles, function (style, n) {
-                        if (oldStyles && oldStyles[n] !== style) {
-                            newStyles[n] = style;
-                            hasNew = true;
-                        }
-                    });
-                }
-                if (hasNew) {
-                    // Merge the new styles with the old ones
-                    if (oldStyles) {
-                        styles = extend(oldStyles, newStyles);
-                    }
-                    // Get the text width from style
-                    if (styles) {
-                        // Previously set, unset it (#8234)
-                        if (styles.width === null || styles.width === 'auto') {
-                            delete this.textWidth;
-                            // Apply new
-                        }
-                        else if (elem.nodeName.toLowerCase() === 'text' &&
-                            styles.width) {
-                            textWidth = this.textWidth = pInt(styles.width);
-                        }
-                    }
-                    // store object
-                    this.styles = styles;
-                    if (textWidth && (!svg && this.renderer.forExport)) {
-                        delete styles.width;
-                    }
-                    // Serialize and set style attribute
-                    if (elem.namespaceURI === this.SVG_NS) { // #7633
-                        hyphenate = function (a, b) {
-                            return '-' + b.toLowerCase();
-                        };
-                        objectEach(styles, function (style, n) {
-                            if (svgPseudoProps.indexOf(n) === -1) {
-                                serializedCss +=
-                                    n.replace(/([A-Z])/g, hyphenate) + ':' +
-                                        style + ';';
-                            }
-                        });
-                        if (serializedCss) {
-                            attr(elem, 'style', serializedCss); // #1881
-                        }
-                    }
-                    else {
-                        css(elem, styles);
-                    }
-                    if (this.added) {
-                        // Rebuild text after added. Cache mechanisms in the buildText
-                        // will prevent building if there are no significant changes.
-                        if (this.element.nodeName === 'text') {
-                            this.renderer.buildText(this);
-                        }
-                        // Apply text outline after added
-                        if (styles && styles.textOutline) {
-                            this.applyTextOutline(styles.textOutline);
-                        }
-                    }
-                }
-                return this;
-            };
-            /**
-             * @private
-             * @function Highcharts.SVGElement#dashstyleSetter
-             * @param {string} value
-             */
-            SVGElement.prototype.dashstyleSetter = function (value) {
-                var i,
-                    strokeWidth = this['stroke-width'];
-                // If "inherit", like maps in IE, assume 1 (#4981). With HC5 and the new
-                // strokeWidth function, we should be able to use that instead.
-                if (strokeWidth === 'inherit') {
-                    strokeWidth = 1;
-                }
-                value = value && value.toLowerCase();
-                if (value) {
-                    var v = value
-                            .replace('shortdashdotdot', '3,1,1,1,1,1,')
-                            .replace('shortdashdot', '3,1,1,1')
-                            .replace('shortdot', '1,1,')
-                            .replace('shortdash', '3,1,')
-                            .replace('longdash', '8,3,')
-                            .replace(/dot/g, '1,3,')
-                            .replace('dash', '4,3,')
-                            .replace(/,$/, '')
-                            .split(','); // ending comma
-                        i = v.length;
-                    while (i--) {
-                        v[i] = '' + (pInt(v[i]) * pick(strokeWidth, NaN));
-                    }
-                    value = v.join(',').replace(/NaN/g, 'none'); // #3226
-                    this.element.setAttribute('stroke-dasharray', value);
-                }
-            };
-            /**
-             * Destroy the element and element wrapper and clear up the DOM and event
-             * hooks.
-             *
-             * @function Highcharts.SVGElement#destroy
-             */
-            SVGElement.prototype.destroy = function () {
-                var wrapper = this,
-                    element = wrapper.element || {},
-                    renderer = wrapper.renderer,
-                    parentToClean = (renderer.isSVG &&
-                        element.nodeName === 'SPAN' &&
-                        wrapper.parentGroup ||
-                        void 0),
-                    grandParent,
-                    ownerSVGElement = element.ownerSVGElement,
-                    i;
-                // remove events
-                element.onclick = element.onmouseout = element.onmouseover =
-                    element.onmousemove = element.point = null;
-                stop(wrapper); // stop running animations
-                if (wrapper.clipPath && ownerSVGElement) {
-                    var clipPath_1 = wrapper.clipPath;
-                    // Look for existing references to this clipPath and remove them
-                    // before destroying the element (#6196).
-                    // The upper case version is for Edge
-                    [].forEach.call(ownerSVGElement.querySelectorAll('[clip-path],[CLIP-PATH]'), function (el) {
-                        var clipPathAttr = el.getAttribute('clip-path');
-                        if (clipPathAttr.indexOf(clipPath_1.element.id) > -1) {
-                            el.removeAttribute('clip-path');
-                        }
-                    });
-                    wrapper.clipPath = clipPath_1.destroy();
-                }
-                // Destroy stops in case this is a gradient object @todo old code?
-                if (wrapper.stops) {
-                    for (i = 0; i < wrapper.stops.length; i++) {
-                        wrapper.stops[i].destroy();
-                    }
-                    wrapper.stops.length = 0;
-                    wrapper.stops = void 0;
-                }
-                // remove element
-                wrapper.safeRemoveChild(element);
-                if (!renderer.styledMode) {
-                    wrapper.destroyShadows();
-                }
-                // In case of useHTML, clean up empty containers emulating SVG groups
-                // (#1960, #2393, #2697).
-                while (parentToClean &&
-                    parentToClean.div &&
-                    parentToClean.div.childNodes.length === 0) {
-                    grandParent = parentToClean.parentGroup;
-                    wrapper.safeRemoveChild(parentToClean.div);
-                    delete parentToClean.div;
-                    parentToClean = grandParent;
-                }
-                // remove from alignObjects
-                if (wrapper.alignTo) {
-                    erase(renderer.alignedObjects, wrapper);
-                }
-                objectEach(wrapper, function (val, key) {
-                    // Destroy child elements of a group
-                    if (wrapper[key] &&
-                        wrapper[key].parentGroup === wrapper &&
-                        wrapper[key].destroy) {
-                        wrapper[key].destroy();
-                    }
-                    // Delete all properties
-                    delete wrapper[key];
+                return wrapper;
+              };
+            }
+            return wrapper;
+          },
+        }
+      );
+
+      return HTMLRenderer;
+    }
+  );
+  _registerModule(
+    _modules,
+    "Core/Axis/Tick.js",
+    [_modules["Core/Globals.js"], _modules["Core/Utilities.js"]],
+    function (H, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      /**
+       * Optional parameters for the tick.
+       * @private
+       * @interface Highcharts.TickParametersObject
+       */ /**
+       * Set category for the tick.
+       * @name Highcharts.TickParametersObject#category
+       * @type {string|undefined}
+       */ /**
+       * @name Highcharts.TickParametersObject#options
+       * @type {Highcharts.Dictionary<any>|undefined}
+       */ /**
+       * Set tickmarkOffset for the tick.
+       * @name Highcharts.TickParametersObject#tickmarkOffset
+       * @type {number|undefined}
+       */
+      var clamp = U.clamp,
+        correctFloat = U.correctFloat,
+        defined = U.defined,
+        destroyObjectProperties = U.destroyObjectProperties,
+        extend = U.extend,
+        fireEvent = U.fireEvent,
+        isNumber = U.isNumber,
+        merge = U.merge,
+        objectEach = U.objectEach,
+        pick = U.pick;
+      var deg2rad = H.deg2rad;
+      /* eslint-disable no-invalid-this, valid-jsdoc */
+      /**
+       * The Tick class.
+       *
+       * @class
+       * @name Highcharts.Tick
+       *
+       * @param {Highcharts.Axis} axis
+       * The axis of the tick.
+       *
+       * @param {number} pos
+       * The position of the tick on the axis in terms of axis values.
+       *
+       * @param {string} [type]
+       * The type of tick, either 'minor' or an empty string
+       *
+       * @param {boolean} [noLabel=false]
+       * Whether to disable the label or not. Defaults to false.
+       *
+       * @param {object} [parameters]
+       * Optional parameters for the tick.
+       */
+      var Tick = /** @class */ (function () {
+        /* *
+         *
+         *  Constructors
+         *
+         * */
+        function Tick(axis, pos, type, noLabel, parameters) {
+          this.isNew = true;
+          this.isNewLabel = true;
+          /**
+           * The related axis of the tick.
+           * @name Highcharts.Tick#axis
+           * @type {Highcharts.Axis}
+           */
+          this.axis = axis;
+          /**
+           * The logical position of the tick on the axis in terms of axis values.
+           * @name Highcharts.Tick#pos
+           * @type {number}
+           */
+          this.pos = pos;
+          /**
+           * The tick type, which can be `"minor"`, or an empty string.
+           * @name Highcharts.Tick#type
+           * @type {string}
+           */
+          this.type = type || "";
+          this.parameters = parameters || {};
+          /**
+           * The mark offset of the tick on the axis. Usually `undefined`, numeric
+           * for grid axes.
+           * @name Highcharts.Tick#tickmarkOffset
+           * @type {number|undefined}
+           */
+          this.tickmarkOffset = this.parameters.tickmarkOffset;
+          this.options = this.parameters.options;
+          fireEvent(this, "init");
+          if (!type && !noLabel) {
+            this.addLabel();
+          }
+        }
+        /* *
+         *
+         *  Functions
+         *
+         * */
+        /**
+         * Write the tick label.
+         *
+         * @private
+         * @function Highcharts.Tick#addLabel
+         * @return {void}
+         */
+        Tick.prototype.addLabel = function () {
+          var tick = this,
+            axis = tick.axis,
+            options = axis.options,
+            chart = axis.chart,
+            categories = axis.categories,
+            log = axis.logarithmic,
+            names = axis.names,
+            pos = tick.pos,
+            labelOptions = pick(
+              tick.options && tick.options.labels,
+              options.labels
+            ),
+            str,
+            tickPositions = axis.tickPositions,
+            isFirst = pos === tickPositions[0],
+            isLast = pos === tickPositions[tickPositions.length - 1],
+            value =
+              this.parameters.category ||
+              (categories ? pick(categories[pos], names[pos], pos) : pos),
+            label = tick.label,
+            animateLabels =
+              (!labelOptions.step || labelOptions.step === 1) &&
+              axis.tickInterval === 1,
+            tickPositionInfo = tickPositions.info,
+            dateTimeLabelFormat,
+            dateTimeLabelFormats,
+            i,
+            list;
+          // Set the datetime label format. If a higher rank is set for this
+          // position, use that. If not, use the general format.
+          if (axis.dateTime && tickPositionInfo) {
+            dateTimeLabelFormats = chart.time.resolveDTLFormat(
+              options.dateTimeLabelFormats[
+                (!options.grid && tickPositionInfo.higherRanks[pos]) ||
+                  tickPositionInfo.unitName
+              ]
+            );
+            dateTimeLabelFormat = dateTimeLabelFormats.main;
+          }
+          // set properties for access in render method
+          /**
+           * True if the tick is the first one on the axis.
+           * @name Highcharts.Tick#isFirst
+           * @readonly
+           * @type {boolean|undefined}
+           */
+          tick.isFirst = isFirst;
+          /**
+           * True if the tick is the last one on the axis.
+           * @name Highcharts.Tick#isLast
+           * @readonly
+           * @type {boolean|undefined}
+           */
+          tick.isLast = isLast;
+          // Get the string
+          tick.formatCtx = {
+            axis: axis,
+            chart: chart,
+            isFirst: isFirst,
+            isLast: isLast,
+            dateTimeLabelFormat: dateTimeLabelFormat,
+            tickPositionInfo: tickPositionInfo,
+            value: log ? correctFloat(log.lin2log(value)) : value,
+            pos: pos,
+          };
+          str = axis.labelFormatter.call(tick.formatCtx, this.formatCtx);
+          // Set up conditional formatting based on the format list if existing.
+          list = dateTimeLabelFormats && dateTimeLabelFormats.list;
+          if (list) {
+            tick.shortenLabel = function () {
+              for (i = 0; i < list.length; i++) {
+                label.attr({
+                  text: axis.labelFormatter.call(
+                    extend(tick.formatCtx, { dateTimeLabelFormat: list[i] })
+                  ),
                 });
-                return;
-            };
-            /**
-             * Destroy shadows on the element.
-             *
-             * @private
-             * @function Highcharts.SVGElement#destroyShadows
-             *
-             * @return {void}
-             */
-            SVGElement.prototype.destroyShadows = function () {
-                (this.shadows || []).forEach(function (shadow) {
-                    this.safeRemoveChild(shadow);
-                }, this);
-                this.shadows = void 0;
-            };
-            /**
-             * @private
-             */
-            SVGElement.prototype.destroyTextPath = function (elem, path) {
-                var textElement = elem.getElementsByTagName('text')[0];
-                var tspans;
-                if (textElement) {
-                    // Remove textPath attributes
-                    textElement.removeAttribute('dx');
-                    textElement.removeAttribute('dy');
-                    // Remove ID's:
-                    path.element.setAttribute('id', '');
-                    // Check if textElement includes textPath,
-                    if (this.textPathWrapper &&
-                        textElement.getElementsByTagName('textPath').length) {
-                        // Move nodes to <text>
-                        tspans = this.textPathWrapper.element.childNodes;
-                        // Now move all <tspan>'s to the <textPath> node
-                        while (tspans.length) {
-                            textElement.appendChild(tspans[0]);
-                        }
-                        // Remove <textPath> from the DOM
-                        textElement.removeChild(this.textPathWrapper.element);
-                    }
-                }
-                else if (elem.getAttribute('dx') || elem.getAttribute('dy')) {
-                    // Remove textPath attributes from elem
-                    // to get correct text-outline position
-                    elem.removeAttribute('dx');
-                    elem.removeAttribute('dy');
-                }
-                if (this.textPathWrapper) {
-                    // Set textPathWrapper to undefined and destroy it
-                    this.textPathWrapper = this.textPathWrapper.destroy();
-                }
-            };
-            /**
-             * @private
-             * @function Highcharts.SVGElement#dSettter
-             * @param {number|string|Highcharts.SVGPathArray} value
-             * @param {string} key
-             * @param {Highcharts.SVGDOMElement} element
-             */
-            SVGElement.prototype.dSetter = function (value, key, element) {
-                if (isArray(value)) {
-                    // Backwards compatibility, convert one-dimensional array into an
-                    // array of segments
-                    if (typeof value[0] === 'string') {
-                        value = this.renderer.pathToSegments(value);
-                    }
-                    this.pathArray = value;
-                    value = value.reduce(function (acc, seg, i) {
-                        if (!seg || !seg.join) {
-                            return (seg || '').toString();
-                        }
-                        return (i ? acc + ' ' : '') + seg.join(' ');
-                    }, '');
-                }
-                if (/(NaN| {2}|^$)/.test(value)) {
-                    value = 'M 0 0';
-                }
-                // Check for cache before resetting. Resetting causes disturbance in the
-                // DOM, causing flickering in some cases in Edge/IE (#6747). Also
-                // possible performance gain.
-                if (this[key] !== value) {
-                    element.setAttribute(key, value);
-                    this[key] = value;
-                }
-            };
+                if (
+                  label.getBBox().width <
+                  axis.getSlotWidth(tick) - 2 * pick(labelOptions.padding, 5)
+                ) {
+                  return;
+                }
+              }
+              label.attr({
+                text: "",
+              });
+            };
+          }
+          // Call only after first render
+          if (animateLabels && axis._addedPlotLB) {
+            tick.moveLabel(str, labelOptions);
+          }
+          // First call
+          if (!defined(label) && !tick.movedLabel) {
+            /**
+             * The rendered text label of the tick.
+             * @name Highcharts.Tick#label
+             * @type {Highcharts.SVGElement|undefined}
+             */
+            tick.label = label = tick.createLabel(
+              { x: 0, y: 0 },
+              str,
+              labelOptions
+            );
+            // Base value to detect change for new calls to getBBox
+            tick.rotation = 0;
+            // update
+          } else if (label && label.textStr !== str && !animateLabels) {
+            // When resetting text, also reset the width if dynamically set
+            // (#8809)
+            if (
+              label.textWidth &&
+              !(labelOptions.style && labelOptions.style.width) &&
+              !label.styles.width
+            ) {
+              label.css({ width: null });
+            }
+            label.attr({ text: str });
+            label.textPxLength = label.getBBox().width;
+          }
+        };
+        /**
+         * Render and return the label of the tick.
+         *
+         * @private
+         * @function Highcharts.Tick#createLabel
+         * @param {Highcharts.PositionObject} xy
+         * @param {string} str
+         * @param {Highcharts.XAxisLabelsOptions} labelOptions
+         * @return {Highcharts.SVGElement|undefined}
+         */
+        Tick.prototype.createLabel = function (xy, str, labelOptions) {
+          var axis = this.axis,
+            chart = axis.chart,
+            label =
+              defined(str) && labelOptions.enabled
+                ? chart.renderer
+                    .text(str, xy.x, xy.y, labelOptions.useHTML)
+                    .add(axis.labelGroup)
+                : null;
+          // Un-rotated length
+          if (label) {
+            // Without position absolute, IE export sometimes is wrong
+            if (!chart.styledMode) {
+              label.css(merge(labelOptions.style));
+            }
+            label.textPxLength = label.getBBox().width;
+          }
+          return label;
+        };
+        /**
+         * Destructor for the tick prototype
+         *
+         * @private
+         * @function Highcharts.Tick#destroy
+         * @return {void}
+         */
+        Tick.prototype.destroy = function () {
+          destroyObjectProperties(this, this.axis);
+        };
+        /**
+         * Gets the x and y positions for ticks in terms of pixels.
+         *
+         * @private
+         * @function Highcharts.Tick#getPosition
+         *
+         * @param {boolean} horiz
+         * Whether the tick is on an horizontal axis or not.
+         *
+         * @param {number} tickPos
+         * Position of the tick.
+         *
+         * @param {number} tickmarkOffset
+         * Tickmark offset for all ticks.
+         *
+         * @param {boolean} [old]
+         * Whether the axis has changed or not.
+         *
+         * @return {Highcharts.PositionObject}
+         * The tick position.
+         *
+         * @fires Highcharts.Tick#event:afterGetPosition
+         */
+        Tick.prototype.getPosition = function (
+          horiz,
+          tickPos,
+          tickmarkOffset,
+          old
+        ) {
+          var axis = this.axis,
+            chart = axis.chart,
+            cHeight = (old && chart.oldChartHeight) || chart.chartHeight,
+            pos;
+          pos = {
+            x: horiz
+              ? correctFloat(
+                  axis.translate(tickPos + tickmarkOffset, null, null, old) +
+                    axis.transB
+                )
+              : axis.left +
+                axis.offset +
+                (axis.opposite
+                  ? ((old && chart.oldChartWidth) || chart.chartWidth) -
+                    axis.right -
+                    axis.left
+                  : 0),
+            y: horiz
+              ? cHeight -
+                axis.bottom +
+                axis.offset -
+                (axis.opposite ? axis.height : 0)
+              : correctFloat(
+                  cHeight -
+                    axis.translate(tickPos + tickmarkOffset, null, null, old) -
+                    axis.transB
+                ),
+          };
+          // Chrome workaround for #10516
+          pos.y = clamp(pos.y, -1e5, 1e5);
+          fireEvent(this, "afterGetPosition", { pos: pos });
+          return pos;
+        };
+        /**
+         * Get the x, y position of the tick label
+         *
+         * @private
+         * @return {Highcharts.PositionObject}
+         */
+        Tick.prototype.getLabelPosition = function (
+          x,
+          y,
+          label,
+          horiz,
+          labelOptions,
+          tickmarkOffset,
+          index,
+          step
+        ) {
+          var axis = this.axis,
+            transA = axis.transA,
+            reversed = // #7911
+              axis.isLinked && axis.linkedParent
+                ? axis.linkedParent.reversed
+                : axis.reversed,
+            staggerLines = axis.staggerLines,
+            rotCorr = axis.tickRotCorr || { x: 0, y: 0 },
+            yOffset = labelOptions.y,
+            // Adjust for label alignment if we use reserveSpace: true (#5286)
+            labelOffsetCorrection =
+              !horiz && !axis.reserveSpaceDefault
+                ? -axis.labelOffset * (axis.labelAlign === "center" ? 0.5 : 1)
+                : 0,
+            line,
+            pos = {};
+          if (!defined(yOffset)) {
+            if (axis.side === 0) {
+              yOffset = label.rotation ? -8 : -label.getBBox().height;
+            } else if (axis.side === 2) {
+              yOffset = rotCorr.y + 8;
+            } else {
+              // #3140, #3140
+              yOffset =
+                Math.cos(label.rotation * deg2rad) *
+                (rotCorr.y - label.getBBox(false, 0).height / 2);
+            }
+          }
+          x =
+            x +
+            labelOptions.x +
+            labelOffsetCorrection +
+            rotCorr.x -
+            (tickmarkOffset && horiz
+              ? tickmarkOffset * transA * (reversed ? -1 : 1)
+              : 0);
+          y =
+            y +
+            yOffset -
+            (tickmarkOffset && !horiz
+              ? tickmarkOffset * transA * (reversed ? 1 : -1)
+              : 0);
+          // Correct for staggered labels
+          if (staggerLines) {
+            line = (index / (step || 1)) % staggerLines;
+            if (axis.opposite) {
+              line = staggerLines - line - 1;
+            }
+            y += line * (axis.labelOffset / staggerLines);
+          }
+          pos.x = x;
+          pos.y = Math.round(y);
+          fireEvent(this, "afterGetLabelPosition", {
+            pos: pos,
+            tickmarkOffset: tickmarkOffset,
+            index: index,
+          });
+          return pos;
+        };
+        /**
+         * Get the offset height or width of the label
+         *
+         * @private
+         * @function Highcharts.Tick#getLabelSize
+         * @return {number}
+         */
+        Tick.prototype.getLabelSize = function () {
+          return this.label
+            ? this.label.getBBox()[this.axis.horiz ? "height" : "width"]
+            : 0;
+        };
+        /**
+         * Extendible method to return the path of the marker
+         *
+         * @private
+         *
+         */
+        Tick.prototype.getMarkPath = function (
+          x,
+          y,
+          tickLength,
+          tickWidth,
+          horiz,
+          renderer
+        ) {
+          return renderer.crispLine(
+            [
+              ["M", x, y],
+              [
+                "L",
+                x + (horiz ? 0 : -tickLength),
+                y + (horiz ? tickLength : 0),
+              ],
+            ],
+            tickWidth
+          );
+        };
+        /**
+         * Handle the label overflow by adjusting the labels to the left and right
+         * edge, or hide them if they collide into the neighbour label.
+         *
+         * @private
+         * @function Highcharts.Tick#handleOverflow
+         * @param {Highcharts.PositionObject} xy
+         * @return {void}
+         */
+        Tick.prototype.handleOverflow = function (xy) {
+          var tick = this,
+            axis = this.axis,
+            labelOptions = axis.options.labels,
+            pxPos = xy.x,
+            chartWidth = axis.chart.chartWidth,
+            spacing = axis.chart.spacing,
+            leftBound = pick(axis.labelLeft, Math.min(axis.pos, spacing[3])),
+            rightBound = pick(
+              axis.labelRight,
+              Math.max(
+                !axis.isRadial ? axis.pos + axis.len : 0,
+                chartWidth - spacing[1]
+              )
+            ),
+            label = this.label,
+            rotation = this.rotation,
+            factor = {
+              left: 0,
+              center: 0.5,
+              right: 1,
+            }[axis.labelAlign || label.attr("align")],
+            labelWidth = label.getBBox().width,
+            slotWidth = axis.getSlotWidth(tick),
+            modifiedSlotWidth = slotWidth,
+            xCorrection = factor,
+            goRight = 1,
+            leftPos,
+            rightPos,
+            textWidth,
+            css = {};
+          // Check if the label overshoots the chart spacing box. If it does, move
+          // it. If it now overshoots the slotWidth, add ellipsis.
+          if (
+            !rotation &&
+            pick(labelOptions.overflow, "justify") === "justify"
+          ) {
+            leftPos = pxPos - factor * labelWidth;
+            rightPos = pxPos + (1 - factor) * labelWidth;
+            if (leftPos < leftBound) {
+              modifiedSlotWidth =
+                xy.x + modifiedSlotWidth * (1 - factor) - leftBound;
+            } else if (rightPos > rightBound) {
+              modifiedSlotWidth =
+                rightBound - xy.x + modifiedSlotWidth * factor;
+              goRight = -1;
+            }
+            modifiedSlotWidth = Math.min(slotWidth, modifiedSlotWidth); // #4177
+            if (modifiedSlotWidth < slotWidth && axis.labelAlign === "center") {
+              xy.x +=
+                goRight *
+                (slotWidth -
+                  modifiedSlotWidth -
+                  xCorrection *
+                    (slotWidth - Math.min(labelWidth, modifiedSlotWidth)));
+            }
+            // If the label width exceeds the available space, set a text width
+            // to be picked up below. Also, if a width has been set before, we
+            // need to set a new one because the reported labelWidth will be
+            // limited by the box (#3938).
+            if (
+              labelWidth > modifiedSlotWidth ||
+              (axis.autoRotation && (label.styles || {}).width)
+            ) {
+              textWidth = modifiedSlotWidth;
+            }
+            // Add ellipsis to prevent rotated labels to be clipped against the edge
+            // of the chart
+          } else if (rotation < 0 && pxPos - factor * labelWidth < leftBound) {
+            textWidth = Math.round(
+              pxPos / Math.cos(rotation * deg2rad) - leftBound
+            );
+          } else if (rotation > 0 && pxPos + factor * labelWidth > rightBound) {
+            textWidth = Math.round(
+              (chartWidth - pxPos) / Math.cos(rotation * deg2rad)
+            );
+          }
+          if (textWidth) {
+            if (tick.shortenLabel) {
+              tick.shortenLabel();
+            } else {
+              css.width = Math.floor(textWidth) + "px";
+              if (!(labelOptions.style || {}).textOverflow) {
+                css.textOverflow = "ellipsis";
+              }
+              label.css(css);
+            }
+          }
+        };
+        /**
+         * Try to replace the label if the same one already exists.
+         *
+         * @private
+         * @function Highcharts.Tick#moveLabel
+         * @param {string} str
+         * @param {Highcharts.XAxisLabelsOptions} labelOptions
+         *
+         * @return {void}
+         */
+        Tick.prototype.moveLabel = function (str, labelOptions) {
+          var tick = this,
+            label = tick.label,
+            moved = false,
+            axis = tick.axis,
+            labelPos,
+            reversed = axis.reversed,
+            xPos,
+            yPos;
+          if (label && label.textStr === str) {
+            tick.movedLabel = label;
+            moved = true;
+            delete tick.label;
+          } else {
+            // Find a label with the same string
+            objectEach(axis.ticks, function (currentTick) {
+              if (
+                !moved &&
+                !currentTick.isNew &&
+                currentTick !== tick &&
+                currentTick.label &&
+                currentTick.label.textStr === str
+              ) {
+                tick.movedLabel = currentTick.label;
+                moved = true;
+                currentTick.labelPos = tick.movedLabel.xy;
+                delete currentTick.label;
+              }
+            });
+          }
+          // Create new label if the actual one is moved
+          if (!moved && (tick.labelPos || label)) {
+            labelPos = tick.labelPos || label.xy;
+            xPos = axis.horiz
+              ? reversed
+                ? 0
+                : axis.width + axis.left
+              : labelPos.x;
+            yPos = axis.horiz
+              ? labelPos.y
+              : reversed
+              ? axis.width + axis.left
+              : 0;
+            tick.movedLabel = tick.createLabel(
+              { x: xPos, y: yPos },
+              str,
+              labelOptions
+            );
+            if (tick.movedLabel) {
+              tick.movedLabel.attr({ opacity: 0 });
+            }
+          }
+        };
+        /**
+         * Put everything in place
+         *
+         * @private
+         * @param {number} index
+         * @param {boolean} [old]
+         *        Use old coordinates to prepare an animation into new position
+         * @param {number} [opacity]
+         * @return {voids}
+         */
+        Tick.prototype.render = function (index, old, opacity) {
+          var tick = this,
+            axis = tick.axis,
+            horiz = axis.horiz,
+            pos = tick.pos,
+            tickmarkOffset = pick(tick.tickmarkOffset, axis.tickmarkOffset),
+            xy = tick.getPosition(horiz, pos, tickmarkOffset, old),
+            x = xy.x,
+            y = xy.y,
+            reverseCrisp =
+              (horiz && x === axis.pos + axis.len) || (!horiz && y === axis.pos)
+                ? -1
+                : 1; // #1480, #1687
+          opacity = pick(opacity, 1);
+          this.isActive = true;
+          // Create the grid line
+          this.renderGridLine(old, opacity, reverseCrisp);
+          // create the tick mark
+          this.renderMark(xy, opacity, reverseCrisp);
+          // the label is created on init - now move it into place
+          this.renderLabel(xy, old, opacity, index);
+          tick.isNew = false;
+          fireEvent(this, "afterRender");
+        };
+        /**
+         * Renders the gridLine.
+         *
+         * @private
+         * @param {boolean} old  Whether or not the tick is old
+         * @param {number} opacity  The opacity of the grid line
+         * @param {number} reverseCrisp  Modifier for avoiding overlapping 1 or -1
+         * @return {void}
+         */
+        Tick.prototype.renderGridLine = function (old, opacity, reverseCrisp) {
+          var tick = this,
+            axis = tick.axis,
+            options = axis.options,
+            gridLine = tick.gridLine,
+            gridLinePath,
+            attribs = {},
+            pos = tick.pos,
+            type = tick.type,
+            tickmarkOffset = pick(tick.tickmarkOffset, axis.tickmarkOffset),
+            renderer = axis.chart.renderer,
+            gridPrefix = type ? type + "Grid" : "grid",
+            gridLineWidth = options[gridPrefix + "LineWidth"],
+            gridLineColor = options[gridPrefix + "LineColor"],
+            dashStyle = options[gridPrefix + "LineDashStyle"];
+          if (!gridLine) {
+            if (!axis.chart.styledMode) {
+              attribs.stroke = gridLineColor;
+              attribs["stroke-width"] = gridLineWidth;
+              if (dashStyle) {
+                attribs.dashstyle = dashStyle;
+              }
+            }
+            if (!type) {
+              attribs.zIndex = 1;
+            }
+            if (old) {
+              opacity = 0;
+            }
             /**
-             * Fade out an element by animating its opacity down to 0, and hide it on
-             * complete. Used internally for the tooltip.
-             *
-             * @function Highcharts.SVGElement#fadeOut
-             *
-             * @param {number} [duration=150]
-             * The fade duration in milliseconds.
-             */
-            SVGElement.prototype.fadeOut = function (duration) {
-                var elemWrapper = this;
-                elemWrapper.animate({
-                    opacity: 0
-                }, {
-                    duration: pick(duration, 150),
-                    complete: function () {
-                        // #3088, assuming we're only using this for tooltips
-                        elemWrapper.attr({ y: -9999 }).hide();
-                    }
+             * The rendered grid line of the tick.
+             * @name Highcharts.Tick#gridLine
+             * @type {Highcharts.SVGElement|undefined}
+             */
+            tick.gridLine = gridLine = renderer
+              .path()
+              .attr(attribs)
+              .addClass("highcharts-" + (type ? type + "-" : "") + "grid-line")
+              .add(axis.gridGroup);
+          }
+          if (gridLine) {
+            gridLinePath = axis.getPlotLinePath({
+              value: pos + tickmarkOffset,
+              lineWidth: gridLine.strokeWidth() * reverseCrisp,
+              force: "pass",
+              old: old,
+            });
+            // If the parameter 'old' is set, the current call will be followed
+            // by another call, therefore do not do any animations this time
+            if (gridLinePath) {
+              gridLine[old || tick.isNew ? "attr" : "animate"]({
+                d: gridLinePath,
+                opacity: opacity,
+              });
+            }
+          }
+        };
+        /**
+         * Renders the tick mark.
+         *
+         * @private
+         * @param {Highcharts.PositionObject} xy  The position vector of the mark
+         * @param {number} opacity  The opacity of the mark
+         * @param {number} reverseCrisp  Modifier for avoiding overlapping 1 or -1
+         * @return {void}
+         */
+        Tick.prototype.renderMark = function (xy, opacity, reverseCrisp) {
+          var tick = this,
+            axis = tick.axis,
+            options = axis.options,
+            renderer = axis.chart.renderer,
+            type = tick.type,
+            tickPrefix = type ? type + "Tick" : "tick",
+            tickSize = axis.tickSize(tickPrefix),
+            mark = tick.mark,
+            isNewMark = !mark,
+            x = xy.x,
+            y = xy.y,
+            tickWidth = pick(
+              options[tickPrefix + "Width"],
+              !type && axis.isXAxis ? 1 : 0
+            ), // X axis defaults to 1
+            tickColor = options[tickPrefix + "Color"];
+          if (tickSize) {
+            // negate the length
+            if (axis.opposite) {
+              tickSize[0] = -tickSize[0];
+            }
+            // First time, create it
+            if (isNewMark) {
+              /**
+               * The rendered mark of the tick.
+               * @name Highcharts.Tick#mark
+               * @type {Highcharts.SVGElement|undefined}
+               */
+              tick.mark = mark = renderer
+                .path()
+                .addClass("highcharts-" + (type ? type + "-" : "") + "tick")
+                .add(axis.axisGroup);
+              if (!axis.chart.styledMode) {
+                mark.attr({
+                  stroke: tickColor,
+                  "stroke-width": tickWidth,
                 });
+              }
+            }
+            mark[isNewMark ? "attr" : "animate"]({
+              d: tick.getMarkPath(
+                x,
+                y,
+                tickSize[0],
+                mark.strokeWidth() * reverseCrisp,
+                axis.horiz,
+                renderer
+              ),
+              opacity: opacity,
+            });
+          }
+        };
+        /**
+         * Renders the tick label.
+         * Note: The label should already be created in init(), so it should only
+         * have to be moved into place.
+         *
+         * @private
+         * @param {Highcharts.PositionObject} xy  The position vector of the label
+         * @param {boolean} old  Whether or not the tick is old
+         * @param {number} opacity  The opacity of the label
+         * @param {number} index  The index of the tick
+         * @return {void}
+         */
+        Tick.prototype.renderLabel = function (xy, old, opacity, index) {
+          var tick = this,
+            axis = tick.axis,
+            horiz = axis.horiz,
+            options = axis.options,
+            label = tick.label,
+            labelOptions = options.labels,
+            step = labelOptions.step,
+            tickmarkOffset = pick(tick.tickmarkOffset, axis.tickmarkOffset),
+            show = true,
+            x = xy.x,
+            y = xy.y;
+          if (label && isNumber(x)) {
+            label.xy = xy = tick.getLabelPosition(
+              x,
+              y,
+              label,
+              horiz,
+              labelOptions,
+              tickmarkOffset,
+              index,
+              step
+            );
+            // Apply show first and show last. If the tick is both first and
+            // last, it is a single centered tick, in which case we show the
+            // label anyway (#2100).
+            if (
+              (tick.isFirst &&
+                !tick.isLast &&
+                !pick(options.showFirstLabel, 1)) ||
+              (tick.isLast && !tick.isFirst && !pick(options.showLastLabel, 1))
+            ) {
+              show = false;
+              // Handle label overflow and show or hide accordingly
+            } else if (
+              horiz &&
+              !labelOptions.step &&
+              !labelOptions.rotation &&
+              !old &&
+              opacity !== 0
+            ) {
+              tick.handleOverflow(xy);
+            }
+            // apply step
+            if (step && index % step) {
+              // show those indices dividable by step
+              show = false;
+            }
+            // Set the new position, and show or hide
+            if (show && isNumber(xy.y)) {
+              xy.opacity = opacity;
+              label[tick.isNewLabel ? "attr" : "animate"](xy);
+              tick.isNewLabel = false;
+            } else {
+              label.attr("y", -9999); // #1338
+              tick.isNewLabel = true;
+            }
+          }
+        };
+        /**
+         * Replace labels with the moved ones to perform animation. Additionally
+         * destroy unused labels.
+         *
+         * @private
+         * @function Highcharts.Tick#replaceMovedLabel
+         * @return {void}
+         */
+        Tick.prototype.replaceMovedLabel = function () {
+          var tick = this,
+            label = tick.label,
+            axis = tick.axis,
+            reversed = axis.reversed,
+            x,
+            y;
+          // Animate and destroy
+          if (label && !tick.isNew) {
+            x = axis.horiz
+              ? reversed
+                ? axis.left
+                : axis.width + axis.left
+              : label.xy.x;
+            y = axis.horiz
+              ? label.xy.y
+              : reversed
+              ? axis.width + axis.top
+              : axis.top;
+            label.animate({ x: x, y: y, opacity: 0 }, void 0, label.destroy);
+            delete tick.label;
+          }
+          axis.isDirty = true;
+          tick.label = tick.movedLabel;
+          delete tick.movedLabel;
+        };
+        return Tick;
+      })();
+      H.Tick = Tick;
+
+      return H.Tick;
+    }
+  );
+  _registerModule(
+    _modules,
+    "Core/Time.js",
+    [_modules["Core/Globals.js"], _modules["Core/Utilities.js"]],
+    function (Highcharts, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      /**
+       * Normalized interval.
+       *
+       * @interface Highcharts.TimeNormalizedObject
+       */ /**
+       * The count.
+       *
+       * @name Highcharts.TimeNormalizedObject#count
+       * @type {number}
+       */ /**
+       * The interval in axis values (ms).
+       *
+       * @name Highcharts.TimeNormalizedObject#unitRange
+       * @type {number}
+       */
+      /**
+       * Function of an additional date format specifier.
+       *
+       * @callback Highcharts.TimeFormatCallbackFunction
+       *
+       * @param {number} timestamp
+       *        The time to format.
+       *
+       * @return {string}
+       *         The formatted portion of the date.
+       */
+      /**
+       * Additonal time tick information.
+       *
+       * @interface Highcharts.TimeTicksInfoObject
+       * @extends Highcharts.TimeNormalizedObject
+       */ /**
+       * @name Highcharts.TimeTicksInfoObject#higherRanks
+       * @type {Array<string>}
+       */ /**
+       * @name Highcharts.TimeTicksInfoObject#totalRange
+       * @type {number}
+       */
+      /**
+       * Time ticks.
+       *
+       * @interface Highcharts.AxisTickPositionsArray
+       * @extends global.Array<number>
+       */ /**
+       * @name Highcharts.AxisTickPositionsArray#info
+       * @type {Highcharts.TimeTicksInfoObject|undefined}
+       */
+      /**
+       * A callback to return the time zone offset for a given datetime. It
+       * takes the timestamp in terms of milliseconds since January 1 1970,
+       * and returns the timezone offset in minutes. This provides a hook
+       * for drawing time based charts in specific time zones using their
+       * local DST crossover dates, with the help of external libraries.
+       *
+       * @callback Highcharts.TimezoneOffsetCallbackFunction
+       *
+       * @param {number} timestamp
+       * Timestamp in terms of milliseconds since January 1 1970.
+       *
+       * @return {number}
+       * Timezone offset in minutes.
+       */
+      /**
+       * Allows to manually load the `moment.js` library from Highcharts options
+       * instead of the `window`.
+       * In case of loading the library from a `script` tag,
+       * this option is not needed, it will be loaded from there by default.
+       *
+       * @type {function}
+       * @since 8.2.0
+       * @apioption time.moment
+       */
+      var defined = U.defined,
+        error = U.error,
+        extend = U.extend,
+        isObject = U.isObject,
+        merge = U.merge,
+        objectEach = U.objectEach,
+        pad = U.pad,
+        pick = U.pick,
+        splat = U.splat,
+        timeUnits = U.timeUnits;
+      var H = Highcharts,
+        win = H.win;
+      /* eslint-disable no-invalid-this, valid-jsdoc */
+      /**
+       * The Time class. Time settings are applied in general for each page using
+       * `Highcharts.setOptions`, or individually for each Chart item through the
+       * [time](https://api.highcharts.com/highcharts/time) options set.
+       *
+       * The Time object is available from {@link Highcharts.Chart#time},
+       * which refers to  `Highcharts.time` if no individual time settings are
+       * applied.
+       *
+       * @example
+       * // Apply time settings globally
+       * Highcharts.setOptions({
+       *     time: {
+       *         timezone: 'Europe/London'
+       *     }
+       * });
+       *
+       * // Apply time settings by instance
+       * var chart = Highcharts.chart('container', {
+       *     time: {
+       *         timezone: 'America/New_York'
+       *     },
+       *     series: [{
+       *         data: [1, 4, 3, 5]
+       *     }]
+       * });
+       *
+       * // Use the Time object
+       * console.log(
+       *        'Current time in New York',
+       *        chart.time.dateFormat('%Y-%m-%d %H:%M:%S', Date.now())
+       * );
+       *
+       * @since 6.0.5
+       *
+       * @class
+       * @name Highcharts.Time
+       *
+       * @param {Highcharts.TimeOptions} options
+       * Time options as defined in [chart.options.time](/highcharts/time).
+       */
+      var Time = /** @class */ (function () {
+        /* *
+         *
+         *  Constructors
+         *
+         * */
+        function Time(options) {
+          /* *
+           *
+           *  Properties
+           *
+           * */
+          this.options = {};
+          this.useUTC = false;
+          this.variableTimezone = false;
+          this.Date = win.Date;
+          /**
+           * Get the time zone offset based on the current timezone information as
+           * set in the global options.
+           *
+           * @function Highcharts.Time#getTimezoneOffset
+           *
+           * @param {number} timestamp
+           *        The JavaScript timestamp to inspect.
+           *
+           * @return {number}
+           *         The timezone offset in minutes compared to UTC.
+           */
+          this.getTimezoneOffset = this.timezoneOffsetFunction();
+          this.update(options);
+        }
+        /* *
+         *
+         *  Functions
+         *
+         * */
+        /**
+         * Time units used in `Time.get` and `Time.set`
+         *
+         * @typedef {"Date"|"Day"|"FullYear"|"Hours"|"Milliseconds"|"Minutes"|"Month"|"Seconds"} Highcharts.TimeUnitValue
+         */
+        /**
+         * Get the value of a date object in given units, and subject to the Time
+         * object's current timezone settings. This function corresponds directly to
+         * JavaScripts `Date.getXXX / Date.getUTCXXX`, so instead of calling
+         * `date.getHours()` or `date.getUTCHours()` we will call
+         * `time.get('Hours')`.
+         *
+         * @function Highcharts.Time#get
+         *
+         * @param {Highcharts.TimeUnitValue} unit
+         * @param {Date} date
+         *
+         * @return {number}
+         *        The given time unit
+         */
+        Time.prototype.get = function (unit, date) {
+          if (this.variableTimezone || this.timezoneOffset) {
+            var realMs = date.getTime();
+            var ms = realMs - this.getTimezoneOffset(date);
+            date.setTime(ms); // Temporary adjust to timezone
+            var ret = date["getUTC" + unit]();
+            date.setTime(realMs); // Reset
+            return ret;
+          }
+          // UTC time with no timezone handling
+          if (this.useUTC) {
+            return date["getUTC" + unit]();
+          }
+          // Else, local time
+          return date["get" + unit]();
+        };
+        /**
+         * Set the value of a date object in given units, and subject to the Time
+         * object's current timezone settings. This function corresponds directly to
+         * JavaScripts `Date.setXXX / Date.setUTCXXX`, so instead of calling
+         * `date.setHours(0)` or `date.setUTCHours(0)` we will call
+         * `time.set('Hours', 0)`.
+         *
+         * @function Highcharts.Time#set
+         *
+         * @param {Highcharts.TimeUnitValue} unit
+         * @param {Date} date
+         * @param {number} value
+         *
+         * @return {number}
+         *        The epoch milliseconds of the updated date
+         */
+        Time.prototype.set = function (unit, date, value) {
+          // UTC time with timezone handling
+          if (this.variableTimezone || this.timezoneOffset) {
+            // For lower order time units, just set it directly using UTC
+            // time
+            if (
+              unit === "Milliseconds" ||
+              unit === "Seconds" ||
+              unit === "Minutes"
+            ) {
+              return date["setUTC" + unit](value);
+            }
+            // Higher order time units need to take the time zone into
+            // account
+            // Adjust by timezone
+            var offset = this.getTimezoneOffset(date);
+            var ms = date.getTime() - offset;
+            date.setTime(ms);
+            date["setUTC" + unit](value);
+            var newOffset = this.getTimezoneOffset(date);
+            ms = date.getTime() + newOffset;
+            return date.setTime(ms);
+          }
+          // UTC time with no timezone handling
+          if (this.useUTC) {
+            return date["setUTC" + unit](value);
+          }
+          // Else, local time
+          return date["set" + unit](value);
+        };
+        /**
+         * Update the Time object with current options. It is called internally on
+         * initializing Highcharts, after running `Highcharts.setOptions` and on
+         * `Chart.update`.
+         *
+         * @private
+         * @function Highcharts.Time#update
+         *
+         * @param {Highcharts.TimeOptions} options
+         *
+         * @return {void}
+         */
+        Time.prototype.update = function (options) {
+          var useUTC = pick(options && options.useUTC, true),
+            time = this;
+          this.options = options = merge(true, this.options || {}, options);
+          // Allow using a different Date class
+          this.Date = options.Date || win.Date || Date;
+          this.useUTC = useUTC;
+          this.timezoneOffset = useUTC && options.timezoneOffset;
+          this.getTimezoneOffset = this.timezoneOffsetFunction();
+          /*
+           * The time object has options allowing for variable time zones, meaning
+           * the axis ticks or series data needs to consider this.
+           */
+          this.variableTimezone = !!(
+            !useUTC ||
+            options.getTimezoneOffset ||
+            options.timezone
+          );
+        };
+        /**
+         * Make a time and returns milliseconds. Interprets the inputs as UTC time,
+         * local time or a specific timezone time depending on the current time
+         * settings.
+         *
+         * @function Highcharts.Time#makeTime
+         *
+         * @param {number} year
+         *        The year
+         *
+         * @param {number} month
+         *        The month. Zero-based, so January is 0.
+         *
+         * @param {number} [date=1]
+         *        The day of the month
+         *
+         * @param {number} [hours=0]
+         *        The hour of the day, 0-23.
+         *
+         * @param {number} [minutes=0]
+         *        The minutes
+         *
+         * @param {number} [seconds=0]
+         *        The seconds
+         *
+         * @return {number}
+         *         The time in milliseconds since January 1st 1970.
+         */
+        Time.prototype.makeTime = function (
+          year,
+          month,
+          date,
+          hours,
+          minutes,
+          seconds
+        ) {
+          var d, offset, newOffset;
+          if (this.useUTC) {
+            d = this.Date.UTC.apply(0, arguments);
+            offset = this.getTimezoneOffset(d);
+            d += offset;
+            newOffset = this.getTimezoneOffset(d);
+            if (offset !== newOffset) {
+              d += newOffset - offset;
+              // A special case for transitioning from summer time to winter time.
+              // When the clock is set back, the same time is repeated twice, i.e.
+              // 02:30 am is repeated since the clock is set back from 3 am to
+              // 2 am. We need to make the same time as local Date does.
+            } else if (
+              offset - 36e5 === this.getTimezoneOffset(d - 36e5) &&
+              !H.isSafari
+            ) {
+              d -= 36e5;
+            }
+          } else {
+            d = new this.Date(
+              year,
+              month,
+              pick(date, 1),
+              pick(hours, 0),
+              pick(minutes, 0),
+              pick(seconds, 0)
+            ).getTime();
+          }
+          return d;
+        };
+        /**
+         * Sets the getTimezoneOffset function. If the `timezone` option is set, a
+         * default getTimezoneOffset function with that timezone is returned. If
+         * a `getTimezoneOffset` option is defined, it is returned. If neither are
+         * specified, the function using the `timezoneOffset` option or 0 offset is
+         * returned.
+         *
+         * @private
+         * @function Highcharts.Time#timezoneOffsetFunction
+         *
+         * @return {Function}
+         *         A getTimezoneOffset function
+         */
+        Time.prototype.timezoneOffsetFunction = function () {
+          var time = this,
+            options = this.options,
+            moment = options.moment || win.moment;
+          if (!this.useUTC) {
+            return function (timestamp) {
+              return new Date(timestamp.toString()).getTimezoneOffset() * 60000;
+            };
+          }
+          if (options.timezone) {
+            if (!moment) {
+              // getTimezoneOffset-function stays undefined because it depends
+              // on Moment.js
+              error(25);
+            } else {
+              return function (timestamp) {
+                return (
+                  -moment.tz(timestamp, options.timezone).utcOffset() * 60000
+                );
+              };
+            }
+          }
+          // If not timezone is set, look for the getTimezoneOffset callback
+          if (this.useUTC && options.getTimezoneOffset) {
+            return function (timestamp) {
+              return options.getTimezoneOffset(timestamp.valueOf()) * 60000;
+            };
+          }
+          // Last, use the `timezoneOffset` option if set
+          return function () {
+            return (time.timezoneOffset || 0) * 60000;
+          };
+        };
+        /**
+         * Formats a JavaScript date timestamp (milliseconds since Jan 1st 1970)
+         * into a human readable date string. The available format keys are listed
+         * below. Additional formats can be given in the
+         * {@link Highcharts.dateFormats} hook.
+         *
+         * Supported format keys:
+         * - `%a`: Short weekday, like 'Mon'
+         * - `%A`: Long weekday, like 'Monday'
+         * - `%d`: Two digit day of the month, 01 to 31
+         * - `%e`: Day of the month, 1 through 31
+         * - `%w`: Day of the week, 0 through 6
+         * - `%b`: Short month, like 'Jan'
+         * - `%B`: Long month, like 'January'
+         * - `%m`: Two digit month number, 01 through 12
+         * - `%y`: Two digits year, like 09 for 2009
+         * - `%Y`: Four digits year, like 2009
+         * - `%H`: Two digits hours in 24h format, 00 through 23
+         * - `%k`: Hours in 24h format, 0 through 23
+         * - `%I`: Two digits hours in 12h format, 00 through 11
+         * - `%l`: Hours in 12h format, 1 through 12
+         * - `%M`: Two digits minutes, 00 through 59
+         * - `%p`: Upper case AM or PM
+         * - `%P`: Lower case AM or PM
+         * - `%S`: Two digits seconds, 00 through 59
+         * - `%L`: Milliseconds (naming from Ruby)
+         *
+         * @example
+         * const time = new Highcharts.Time();
+         * const s = time.dateFormat('%Y-%m-%d %H:%M:%S', Date.UTC(2020, 0, 1));
+         * console.log(s); // => 2020-01-01 00:00:00
+         *
+         * @function Highcharts.Time#dateFormat
+         *
+         * @param {string} format
+         *        The desired format where various time representations are
+         *        prefixed with %.
+         *
+         * @param {number} timestamp
+         *        The JavaScript timestamp.
+         *
+         * @param {boolean} [capitalize=false]
+         *        Upper case first letter in the return.
+         *
+         * @return {string}
+         *         The formatted date.
+         */
+        Time.prototype.dateFormat = function (format, timestamp, capitalize) {
+          var _a;
+          if (!defined(timestamp) || isNaN(timestamp)) {
+            return (
+              ((_a = H.defaultOptions.lang) === null || _a === void 0
+                ? void 0
+                : _a.invalidDate) || ""
+            );
+          }
+          format = pick(format, "%Y-%m-%d %H:%M:%S");
+          var time = this,
+            date = new this.Date(timestamp),
+            // get the basic time values
+            hours = this.get("Hours", date),
+            day = this.get("Day", date),
+            dayOfMonth = this.get("Date", date),
+            month = this.get("Month", date),
+            fullYear = this.get("FullYear", date),
+            lang = H.defaultOptions.lang,
+            langWeekdays =
+              lang === null || lang === void 0 ? void 0 : lang.weekdays,
+            shortWeekdays =
+              lang === null || lang === void 0 ? void 0 : lang.shortWeekdays,
+            // List all format keys. Custom formats can be added from the
+            // outside.
+            replacements = extend(
+              {
+                // Day
+                // Short weekday, like 'Mon'
+                a: shortWeekdays
+                  ? shortWeekdays[day]
+                  : langWeekdays[day].substr(0, 3),
+                // Long weekday, like 'Monday'
+                A: langWeekdays[day],
+                // Two digit day of the month, 01 to 31
+                d: pad(dayOfMonth),
+                // Day of the month, 1 through 31
+                e: pad(dayOfMonth, 2, " "),
+                // Day of the week, 0 through 6
+                w: day,
+                // Week (none implemented)
+                // 'W': weekNumber(),
+                // Month
+                // Short month, like 'Jan'
+                b: lang.shortMonths[month],
+                // Long month, like 'January'
+                B: lang.months[month],
+                // Two digit month number, 01 through 12
+                m: pad(month + 1),
+                // Month number, 1 through 12 (#8150)
+                o: month + 1,
+                // Year
+                // Two digits year, like 09 for 2009
+                y: fullYear.toString().substr(2, 2),
+                // Four digits year, like 2009
+                Y: fullYear,
+                // Time
+                // Two digits hours in 24h format, 00 through 23
+                H: pad(hours),
+                // Hours in 24h format, 0 through 23
+                k: hours,
+                // Two digits hours in 12h format, 00 through 11
+                I: pad(hours % 12 || 12),
+                // Hours in 12h format, 1 through 12
+                l: hours % 12 || 12,
+                // Two digits minutes, 00 through 59
+                M: pad(this.get("Minutes", date)),
+                // Upper case AM or PM
+                p: hours < 12 ? "AM" : "PM",
+                // Lower case AM or PM
+                P: hours < 12 ? "am" : "pm",
+                // Two digits seconds, 00 through  59
+                S: pad(date.getSeconds()),
+                // Milliseconds (naming from Ruby)
+                L: pad(Math.floor(timestamp % 1000), 3),
+              },
+              H.dateFormats
+            );
+          // Do the replaces
+          objectEach(replacements, function (val, key) {
+            // Regex would do it in one line, but this is faster
+            while (format.indexOf("%" + key) !== -1) {
+              format = format.replace(
+                "%" + key,
+                typeof val === "function" ? val.call(time, timestamp) : val
+              );
+            }
+          });
+          // Optionally capitalize the string and return
+          return capitalize
+            ? format.substr(0, 1).toUpperCase() + format.substr(1)
+            : format;
+        };
+        /**
+         * Resolve legacy formats of dateTimeLabelFormats (strings and arrays) into
+         * an object.
+         * @private
+         * @param {string|Array<T>|Highcharts.Dictionary<T>} f - General format description
+         * @return {Highcharts.Dictionary<T>} - The object definition
+         */
+        Time.prototype.resolveDTLFormat = function (f) {
+          if (!isObject(f, true)) {
+            // check for string or array
+            f = splat(f);
+            return {
+              main: f[0],
+              from: f[1],
+              to: f[2],
             };
-            /**
-             * @private
-             * @function Highcharts.SVGElement#fillSetter
-             * @param {Highcharts.ColorType} value
-             * @param {string} key
-             * @param {Highcharts.SVGDOMElement} element
-             */
-            SVGElement.prototype.fillSetter = function (value, key, element) {
-                if (typeof value === 'string') {
-                    element.setAttribute(key, value);
-                }
-                else if (value) {
-                    this.complexColor(value, key, element);
-                }
-            };
-            /**
-             * Get the bounding box (width, height, x and y) for the element. Generally
-             * used to get rendered text size. Since this is called a lot in charts,
-             * the results are cached based on text properties, in order to save DOM
-             * traffic. The returned bounding box includes the rotation, so for example
-             * a single text line of rotation 90 will report a greater height, and a
-             * width corresponding to the line-height.
-             *
-             * @sample highcharts/members/renderer-on-chart/
-             *         Draw a rectangle based on a text's bounding box
-             *
-             * @function Highcharts.SVGElement#getBBox
-             *
-             * @param {boolean} [reload]
-             *        Skip the cache and get the updated DOM bouding box.
-             *
-             * @param {number} [rot]
-             *        Override the element's rotation. This is internally used on axis
-             *        labels with a value of 0 to find out what the bounding box would
-             *        be have been if it were not rotated.
-             *
-             * @return {Highcharts.BBoxObject}
-             *         The bounding box with `x`, `y`, `width` and `height` properties.
-             */
-            SVGElement.prototype.getBBox = function (reload, rot) {
-                var wrapper = this,
-                    bBox, // = wrapper.bBox,
-                    renderer = wrapper.renderer,
-                    width,
-                    height,
-                    element = wrapper.element,
-                    styles = wrapper.styles,
-                    fontSize,
-                    textStr = wrapper.textStr,
-                    toggleTextShadowShim,
-                    cache = renderer.cache,
-                    cacheKeys = renderer.cacheKeys,
-                    isSVG = element.namespaceURI === wrapper.SVG_NS,
-                    cacheKey;
-                var rotation = pick(rot,
-                    wrapper.rotation, 0);
-                fontSize = renderer.styledMode ? (element &&
-                    SVGElement.prototype.getStyle.call(element, 'font-size')) : (styles && styles.fontSize);
-                // Avoid undefined and null (#7316)
-                if (defined(textStr)) {
-                    cacheKey = textStr.toString();
-                    // Since numbers are monospaced, and numerical labels appear a lot
-                    // in a chart, we assume that a label of n characters has the same
-                    // bounding box as others of the same length. Unless there is inner
-                    // HTML in the label. In that case, leave the numbers as is (#5899).
-                    if (cacheKey.indexOf('<') === -1) {
-                        cacheKey = cacheKey.replace(/[0-9]/g, '0');
-                    }
-                    // Properties that affect bounding box
-                    cacheKey += [
-                        '',
-                        rotation,
-                        fontSize,
-                        wrapper.textWidth,
-                        styles && styles.textOverflow,
-                        styles && styles.fontWeight // #12163
-                    ].join(',');
-                }
-                if (cacheKey && !reload) {
-                    bBox = cache[cacheKey];
-                }
-                // No cache found
-                if (!bBox) {
-                    // SVG elements
-                    if (isSVG || renderer.forExport) {
-                        try { // Fails in Firefox if the container has display: none.
-                            // When the text shadow shim is used, we need to hide the
-                            // fake shadows to get the correct bounding box (#3872)
-                            toggleTextShadowShim = this.fakeTS && function (display) {
-                                [].forEach.call(element.querySelectorAll('.highcharts-text-outline'), function (tspan) {
-                                    tspan.style.display = display;
-                                });
-                            };
-                            // Workaround for #3842, Firefox reporting wrong bounding
-                            // box for shadows
-                            if (isFunction(toggleTextShadowShim)) {
-                                toggleTextShadowShim('none');
-                            }
-                            bBox = element.getBBox ?
-                                // SVG: use extend because IE9 is not allowed to change
-                                // width and height in case of rotation (below)
-                                extend({}, element.getBBox()) : {
-                                // Legacy IE in export mode
-                                width: element.offsetWidth,
-                                height: element.offsetHeight
-                            };
-                            // #3842
-                            if (isFunction(toggleTextShadowShim)) {
-                                toggleTextShadowShim('');
-                            }
-                        }
-                        catch (e) {
-                            '';
-                        }
-                        // If the bBox is not set, the try-catch block above failed. The
-                        // other condition is for Opera that returns a width of
-                        // -Infinity on hidden elements.
-                        if (!bBox || bBox.width < 0) {
-                            bBox = { width: 0, height: 0 };
-                        }
-                        // VML Renderer or useHTML within SVG
-                    }
-                    else {
-                        bBox = wrapper.htmlGetBBox();
-                    }
-                    // True SVG elements as well as HTML elements in modern browsers
-                    // using the .useHTML option need to compensated for rotation
-                    if (renderer.isSVG) {
-                        width = bBox.width;
-                        height = bBox.height;
-                        // Workaround for wrong bounding box in IE, Edge and Chrome on
-                        // Windows. With Highcharts' default font, IE and Edge report
-                        // a box height of 16.899 and Chrome rounds it to 17. If this
-                        // stands uncorrected, it results in more padding added below
-                        // the text than above when adding a label border or background.
-                        // Also vertical positioning is affected.
-                        // https://jsfiddle.net/highcharts/em37nvuj/
-                        // (#1101, #1505, #1669, #2568, #6213).
-                        if (isSVG) {
-                            bBox.height = height = ({
-                                '11px,17': 14,
-                                '13px,20': 16
-                            }[styles &&
-                                styles.fontSize + ',' + Math.round(height)] ||
-                                height);
-                        }
-                        // Adjust for rotated text
-                        if (rotation) {
-                            var rad = rotation * deg2rad;
-                            bBox.width = Math.abs(height * Math.sin(rad)) +
-                                Math.abs(width * Math.cos(rad));
-                            bBox.height = Math.abs(height * Math.cos(rad)) +
-                                Math.abs(width * Math.sin(rad));
-                        }
-                    }
-                    // Cache it. When loading a chart in a hidden iframe in Firefox and
-                    // IE/Edge, the bounding box height is 0, so don't cache it (#5620).
-                    if (cacheKey && bBox.height > 0) {
-                        // Rotate (#4681)
-                        while (cacheKeys.length > 250) {
-                            delete cache[cacheKeys.shift()];
-                        }
-                        if (!cache[cacheKey]) {
-                            cacheKeys.push(cacheKey);
-                        }
-                        cache[cacheKey] = bBox;
-                    }
-                }
-                return bBox;
-            };
-            /**
-             * Get the computed style. Only in styled mode.
-             *
-             * @example
-             * chart.series[0].points[0].graphic.getStyle('stroke-width'); // => '1px'
-             *
-             * @function Highcharts.SVGElement#getStyle
-             *
-             * @param {string} prop
-             *        The property name to check for.
-             *
-             * @return {string}
-             *         The current computed value.
-             */
-            SVGElement.prototype.getStyle = function (prop) {
-                return win
-                    .getComputedStyle(this.element || this, '')
-                    .getPropertyValue(prop);
-            };
-            /**
-             * Check if an element has the given class name.
-             *
-             * @function Highcharts.SVGElement#hasClass
-             *
-             * @param {string} className
-             * The class name to check for.
-             *
-             * @return {boolean}
-             * Whether the class name is found.
-             */
-            SVGElement.prototype.hasClass = function (className) {
-                return ('' + this.attr('class'))
-                    .split(' ')
-                    .indexOf(className) !== -1;
-            };
-            /**
-             * Hide the element, similar to setting the `visibility` attribute to
-             * `hidden`.
-             *
-             * @function Highcharts.SVGElement#hide
-             *
-             * @param {boolean} [hideByTranslation=false]
-             *        The flag to determine if element should be hidden by moving out
-             *        of the viewport. Used for example for dataLabels.
-             *
-             * @return {Highcharts.SVGElement}
-             *         Returns the SVGElement for chaining.
-             */
-            SVGElement.prototype.hide = function (hideByTranslation) {
-                if (hideByTranslation) {
-                    this.attr({ y: -9999 });
-                }
-                else {
-                    this.attr({ visibility: 'hidden' });
-                }
-                return this;
-            };
-            /**
-             * @private
-             */
-            SVGElement.prototype.htmlGetBBox = function () {
-                return { height: 0, width: 0, x: 0, y: 0 };
-            };
-            /**
-             * Initialize the SVG element. This function only exists to make the
-             * initialization process overridable. It should not be called directly.
-             *
-             * @function Highcharts.SVGElement#init
-             *
-             * @param {Highcharts.SVGRenderer} renderer
-             * The SVGRenderer instance to initialize to.
-             *
-             * @param {string} nodeName
-             * The SVG node name.
-             */
-            SVGElement.prototype.init = function (renderer, nodeName) {
-                /**
-                 * The primary DOM node. Each `SVGElement` instance wraps a main DOM
-                 * node, but may also represent more nodes.
-                 *
-                 * @name Highcharts.SVGElement#element
-                 * @type {Highcharts.SVGDOMElement|Highcharts.HTMLDOMElement}
-                 */
-                this.element = nodeName === 'span' ?
-                    createElement(nodeName) :
-                    doc.createElementNS(this.SVG_NS, nodeName);
-                /**
-                 * The renderer that the SVGElement belongs to.
-                 *
-                 * @name Highcharts.SVGElement#renderer
-                 * @type {Highcharts.SVGRenderer}
-                 */
-                this.renderer = renderer;
-                fireEvent(this, 'afterInit');
-            };
-            /**
-             * Invert a group, rotate and flip. This is used internally on inverted
-             * charts, where the points and graphs are drawn as if not inverted, then
-             * the series group elements are inverted.
-             *
-             * @function Highcharts.SVGElement#invert
-             *
-             * @param {boolean} inverted
-             *        Whether to invert or not. An inverted shape can be un-inverted by
-             *        setting it to false.
-             *
-             * @return {Highcharts.SVGElement}
-             *         Return the SVGElement for chaining.
-             */
-            SVGElement.prototype.invert = function (inverted) {
-                var wrapper = this;
-                wrapper.inverted = inverted;
-                wrapper.updateTransform();
-                return wrapper;
-            };
-            /**
-             * Add an event listener. This is a simple setter that replaces all other
-             * events of the same type, opposed to the {@link Highcharts#addEvent}
-             * function.
-             *
-             * @sample highcharts/members/element-on/
-             *         A clickable rectangle
-             *
-             * @function Highcharts.SVGElement#on
-             *
-             * @param {string} eventType
-             * The event type. If the type is `click`, Highcharts will internally
-             * translate it to a `touchstart` event on touch devices, to prevent the
-             * browser from waiting for a click event from firing.
-             *
-             * @param {Function} handler
-             * The handler callback.
-             *
-             * @return {Highcharts.SVGElement}
-             * The SVGElement for chaining.
-             */
-            SVGElement.prototype.on = function (eventType, handler) {
-                var svgElement = this,
-                    element = svgElement.element,
-                    touchStartPos,
-                    touchEventFired;
-                // touch
-                if (hasTouch && eventType === 'click') {
-                    element.ontouchstart = function (e) {
-                        // save touch position for later calculation
-                        touchStartPos = {
-                            clientX: e.touches[0].clientX,
-                            clientY: e.touches[0].clientY
-                        };
-                    };
-                    // Instead of ontouchstart, event handlers should be called
-                    // on touchend - similar to how current mouseup events are called
-                    element.ontouchend = function (e) {
-                        // hasMoved is a boolean variable containing logic if page
-                        // was scrolled, so if touch position changed more than
-                        // ~4px (value borrowed from general touch handler)
-                        var hasMoved = touchStartPos.clientX ? Math.sqrt(Math.pow(touchStartPos.clientX - e.changedTouches[0].clientX, 2) +
-                                Math.pow(touchStartPos.clientY - e.changedTouches[0].clientY, 2)) >= 4 : false;
-                        if (!hasMoved) { // only call handlers if page was not scrolled
-                            handler.call(element, e);
-                        }
-                        touchEventFired = true;
-                        if (e.cancelable !== false) {
-                            // prevent other events from being fired. #9682
-                            e.preventDefault();
-                        }
-                    };
-                    element.onclick = function (e) {
-                        // Do not call onclick handler if touch event was fired already.
-                        if (!touchEventFired) {
-                            handler.call(element, e);
-                        }
-                    };
-                }
-                else {
-                    // simplest possible event model for internal use
-                    element['on' + eventType] = handler;
-                }
-                return this;
-            };
-            /**
-             * @private
-             * @function Highcharts.SVGElement#opacitySetter
-             * @param {string} value
-             * @param {string} key
-             * @param {Highcharts.SVGDOMElement} element
-             */
-            SVGElement.prototype.opacitySetter = function (value, key, element) {
-                // Round off to avoid float errors, like tests where opacity lands on
-                // 9.86957e-06 instead of 0
-                var opacity = Number(Number(value).toFixed(3));
-                this.opacity = opacity;
-                element.setAttribute(key, opacity);
-            };
-            /**
-             * Remove a class name from the element.
-             *
-             * @function Highcharts.SVGElement#removeClass
-             *
-             * @param {string|RegExp} className
-             *        The class name to remove.
-             *
-             * @return {Highcharts.SVGElement} Returns the SVG element for chainability.
-             */
-            SVGElement.prototype.removeClass = function (className) {
-                return this.attr('class', ('' + this.attr('class'))
-                    .replace(isString(className) ?
-                    new RegExp("(^| )" + className + "( |$)") : // #12064, #13590
-                    className, ' ')
-                    .replace(/ +/g, ' ')
-                    .trim());
-            };
-            /**
-             * @private
-             * @param {Array<Highcharts.SVGDOMElement>} tspans
-             * Text spans.
-             */
-            SVGElement.prototype.removeTextOutline = function (tspans) {
-                // Iterate from the end to
-                // support removing items inside the cycle (#6472).
-                var i = tspans.length,
-                    tspan;
-                while (i--) {
-                    tspan = tspans[i];
-                    if (tspan.getAttribute('class') === 'highcharts-text-outline') {
-                        // Remove then erase
-                        erase(tspans, this.element.removeChild(tspan));
-                    }
+          }
+          return f;
+        };
+        /**
+         * Return an array with time positions distributed on round time values
+         * right and right after min and max. Used in datetime axes as well as for
+         * grouping data on a datetime axis.
+         *
+         * @function Highcharts.Time#getTimeTicks
+         *
+         * @param {Highcharts.TimeNormalizedObject} normalizedInterval
+         *        The interval in axis values (ms) and the count
+         *
+         * @param {number} [min]
+         *        The minimum in axis values
+         *
+         * @param {number} [max]
+         *        The maximum in axis values
+         *
+         * @param {number} [startOfWeek=1]
+         *
+         * @return {Highcharts.AxisTickPositionsArray}
+         */
+        Time.prototype.getTimeTicks = function (
+          normalizedInterval,
+          min,
+          max,
+          startOfWeek
+        ) {
+          var time = this,
+            Date = time.Date,
+            tickPositions = [],
+            i,
+            higherRanks = {},
+            minYear, // used in months and years as a basis for Date.UTC()
+            // When crossing DST, use the max. Resolves #6278.
+            minDate = new Date(min),
+            interval = normalizedInterval.unitRange,
+            count = normalizedInterval.count || 1,
+            variableDayLength,
+            minDay;
+          startOfWeek = pick(startOfWeek, 1);
+          if (defined(min)) {
+            // #1300
+            time.set(
+              "Milliseconds",
+              minDate,
+              interval >= timeUnits.second
+                ? 0 // #3935
+                : count * Math.floor(time.get("Milliseconds", minDate) / count)
+            ); // #3652, #3654
+            if (interval >= timeUnits.second) {
+              // second
+              time.set(
+                "Seconds",
+                minDate,
+                interval >= timeUnits.minute
+                  ? 0 // #3935
+                  : count * Math.floor(time.get("Seconds", minDate) / count)
+              );
+            }
+            if (interval >= timeUnits.minute) {
+              // minute
+              time.set(
+                "Minutes",
+                minDate,
+                interval >= timeUnits.hour
+                  ? 0
+                  : count * Math.floor(time.get("Minutes", minDate) / count)
+              );
+            }
+            if (interval >= timeUnits.hour) {
+              // hour
+              time.set(
+                "Hours",
+                minDate,
+                interval >= timeUnits.day
+                  ? 0
+                  : count * Math.floor(time.get("Hours", minDate) / count)
+              );
+            }
+            if (interval >= timeUnits.day) {
+              // day
+              time.set(
+                "Date",
+                minDate,
+                interval >= timeUnits.month
+                  ? 1
+                  : Math.max(
+                      1,
+                      count * Math.floor(time.get("Date", minDate) / count)
+                    )
+              );
+            }
+            if (interval >= timeUnits.month) {
+              // month
+              time.set(
+                "Month",
+                minDate,
+                interval >= timeUnits.year
+                  ? 0
+                  : count * Math.floor(time.get("Month", minDate) / count)
+              );
+              minYear = time.get("FullYear", minDate);
+            }
+            if (interval >= timeUnits.year) {
+              // year
+              minYear -= minYear % count;
+              time.set("FullYear", minDate, minYear);
+            }
+            // week is a special case that runs outside the hierarchy
+            if (interval === timeUnits.week) {
+              // get start of current week, independent of count
+              minDay = time.get("Day", minDate);
+              time.set(
+                "Date",
+                minDate,
+                time.get("Date", minDate) -
+                  minDay +
+                  startOfWeek +
+                  // We don't want to skip days that are before
+                  // startOfWeek (#7051)
+                  (minDay < startOfWeek ? -7 : 0)
+              );
+            }
+            // Get basics for variable time spans
+            minYear = time.get("FullYear", minDate);
+            var minMonth = time.get("Month", minDate),
+              minDateDate = time.get("Date", minDate),
+              minHours = time.get("Hours", minDate);
+            // Redefine min to the floored/rounded minimum time (#7432)
+            min = minDate.getTime();
+            // Handle local timezone offset
+            if (time.variableTimezone) {
+              // Detect whether we need to take the DST crossover into
+              // consideration. If we're crossing over DST, the day length may
+              // be 23h or 25h and we need to compute the exact clock time for
+              // each tick instead of just adding hours. This comes at a cost,
+              // so first we find out if it is needed (#4951).
+              variableDayLength =
+                // Long range, assume we're crossing over.
+                max - min > 4 * timeUnits.month ||
+                // Short range, check if min and max are in different time
+                // zones.
+                time.getTimezoneOffset(min) !== time.getTimezoneOffset(max);
+            }
+            // Iterate and add tick positions at appropriate values
+            var t = minDate.getTime();
+            i = 1;
+            while (t < max) {
+              tickPositions.push(t);
+              // if the interval is years, use Date.UTC to increase years
+              if (interval === timeUnits.year) {
+                t = time.makeTime(minYear + i * count, 0);
+                // if the interval is months, use Date.UTC to increase months
+              } else if (interval === timeUnits.month) {
+                t = time.makeTime(minYear, minMonth + i * count);
+                // if we're using global time, the interval is not fixed as it
+                // jumps one hour at the DST crossover
+              } else if (
+                variableDayLength &&
+                (interval === timeUnits.day || interval === timeUnits.week)
+              ) {
+                t = time.makeTime(
+                  minYear,
+                  minMonth,
+                  minDateDate + i * count * (interval === timeUnits.day ? 1 : 7)
+                );
+              } else if (
+                variableDayLength &&
+                interval === timeUnits.hour &&
+                count > 1
+              ) {
+                // make sure higher ranks are preserved across DST (#6797,
+                // #7621)
+                t = time.makeTime(
+                  minYear,
+                  minMonth,
+                  minDateDate,
+                  minHours + i * count
+                );
+                // else, the interval is fixed and we use simple addition
+              } else {
+                t += interval * count;
+              }
+              i++;
+            }
+            // push the last time
+            tickPositions.push(t);
+            // Handle higher ranks. Mark new days if the time is on midnight
+            // (#950, #1649, #1760, #3349). Use a reasonable dropout threshold
+            // to prevent looping over dense data grouping (#6156).
+            if (interval <= timeUnits.hour && tickPositions.length < 10000) {
+              tickPositions.forEach(function (t) {
+                if (
+                  // Speed optimization, no need to run dateFormat unless
+                  // we're on a full or half hour
+                  t % 1800000 === 0 &&
+                  // Check for local or global midnight
+                  time.dateFormat("%H%M%S%L", t) === "000000000"
+                ) {
+                  higherRanks[t] = "day";
                 }
-            };
-            /**
-             * Removes an element from the DOM.
-             *
-             * @private
-             * @function Highcharts.SVGElement#safeRemoveChild
-             *
-             * @param {Highcharts.SVGDOMElement|Highcharts.HTMLDOMElement} element
-             * The DOM node to remove.
-             */
-            SVGElement.prototype.safeRemoveChild = function (element) {
-                var parentNode = element.parentNode;
-                if (parentNode) {
-                    parentNode.removeChild(element);
-                }
-            };
-            /**
-             * Set the coordinates needed to draw a consistent radial gradient across
-             * a shape regardless of positioning inside the chart. Used on pie slices
-             * to make all the slices have the same radial reference point.
-             *
-             * @function Highcharts.SVGElement#setRadialReference
-             *
-             * @param {Array<number>} coordinates
-             * The center reference. The format is `[centerX, centerY, diameter]` in
-             * pixels.
-             *
-             * @return {Highcharts.SVGElement}
-             * Returns the SVGElement for chaining.
-             */
-            SVGElement.prototype.setRadialReference = function (coordinates) {
-                var existingGradient = (this.element.gradient &&
-                        this.renderer.gradients[this.element.gradient]);
-                this.element.radialReference = coordinates;
-                // On redrawing objects with an existing gradient, the gradient needs
-                // to be repositioned (#3801)
-                if (existingGradient && existingGradient.radAttr) {
-                    existingGradient.animate(this.renderer.getRadialAttr(coordinates, existingGradient.radAttr));
-                }
-                return this;
-            };
-            /**
-             * @private
-             * @function Highcharts.SVGElement#setTextPath
-             * @param {Highcharts.SVGElement} path
-             * Path to follow.
-             * @param {Highcharts.DataLabelsTextPathOptionsObject} textPathOptions
-             * Options.
-             * @return {Highcharts.SVGElement}
-             * Returns the SVGElement for chaining.
-             */
-            SVGElement.prototype.setTextPath = function (path, textPathOptions) {
-                var elem = this.element,
-                    attribsMap = {
-                        textAnchor: 'text-anchor'
-                    },
-                    attrs,
-                    adder = false,
-                    textPathElement,
-                    textPathId,
-                    textPathWrapper = this.textPathWrapper,
-                    tspans,
-                    firstTime = !textPathWrapper;
-                // Defaults
-                textPathOptions = merge(true, {
-                    enabled: true,
-                    attributes: {
-                        dy: -5,
-                        startOffset: '50%',
-                        textAnchor: 'middle'
-                    }
-                }, textPathOptions);
-                attrs = textPathOptions.attributes;
-                if (path && textPathOptions && textPathOptions.enabled) {
-                    // In case of fixed width for a text, string is rebuilt
-                    // (e.g. ellipsis is applied), so we need to rebuild textPath too
-                    if (textPathWrapper &&
-                        textPathWrapper.element.parentNode === null) {
-                        // When buildText functionality was triggered again
-                        // and deletes textPathWrapper parentNode
-                        firstTime = true;
-                        textPathWrapper = textPathWrapper.destroy();
-                    }
-                    else if (textPathWrapper) {
-                        // Case after drillup when spans were added into
-                        // the DOM outside the textPathWrapper parentGroup
-                        this.removeTextOutline.call(textPathWrapper.parentGroup, [].slice.call(elem.getElementsByTagName('tspan')));
-                    }
-                    // label() has padding, text() doesn't
-                    if (this.options && this.options.padding) {
-                        attrs.dx = -this.options.padding;
-                    }
-                    if (!textPathWrapper) {
-                        // Create <textPath>, defer the DOM adder
-                        this.textPathWrapper = textPathWrapper =
-                            this.renderer.createElement('textPath');
-                        adder = true;
-                    }
-                    textPathElement = textPathWrapper.element;
-                    // Set ID for the path
-                    textPathId = path.element.getAttribute('id');
-                    if (!textPathId) {
-                        path.element.setAttribute('id', textPathId = uniqueKey());
-                    }
-                    // Change DOM structure, by placing <textPath> tag in <text>
-                    if (firstTime) {
-                        tspans = elem.getElementsByTagName('tspan');
-                        // Now move all <tspan>'s to the <textPath> node
-                        while (tspans.length) {
-                            // Remove "y" from tspans, as Firefox translates them
-                            tspans[0].setAttribute('y', 0);
-                            // Remove "x" from tspans
-                            if (isNumber(attrs.dx)) {
-                                tspans[0].setAttribute('x', -attrs.dx);
-                            }
-                            textPathElement.appendChild(tspans[0]);
-                        }
-                    }
-                    // Add <textPath> to the DOM
-                    if (adder &&
-                        textPathWrapper) {
-                        textPathWrapper.add({
-                            // label() is placed in a group, text() is standalone
-                            element: this.text ? this.text.element : elem
-                        });
-                    }
-                    // Set basic options:
-                    // Use `setAttributeNS` because Safari needs this..
-                    textPathElement.setAttributeNS('http://www.w3.org/1999/xlink', 'href', this.renderer.url + '#' + textPathId);
-                    // Presentation attributes:
-                    // dx/dy options must by set on <text> (parent),
-                    // the rest should be set on <textPath>
-                    if (defined(attrs.dy)) {
-                        textPathElement.parentNode
-                            .setAttribute('dy', attrs.dy);
-                        delete attrs.dy;
-                    }
-                    if (defined(attrs.dx)) {
-                        textPathElement.parentNode
-                            .setAttribute('dx', attrs.dx);
-                        delete attrs.dx;
-                    }
-                    // Additional attributes
-                    objectEach(attrs, function (val, key) {
-                        textPathElement.setAttribute(attribsMap[key] || key, val);
-                    });
-                    // Remove translation, text that follows path does not need that
-                    elem.removeAttribute('transform');
-                    // Remove shadows and text outlines
-                    this.removeTextOutline.call(textPathWrapper, [].slice.call(elem.getElementsByTagName('tspan')));
-                    // Remove background and border for label(), see #10545
-                    // Alternatively, we can disable setting background rects in
-                    // series.drawDataLabels()
-                    if (this.text && !this.renderer.styledMode) {
-                        this.attr({
-                            fill: 'none',
-                            'stroke-width': 0
-                        });
-                    }
-                    // Disable some functions
-                    this.updateTransform = noop;
-                    this.applyTextOutline = noop;
-                }
-                else if (textPathWrapper) {
-                    // Reset to prototype
-                    delete this.updateTransform;
-                    delete this.applyTextOutline;
-                    // Restore DOM structure:
-                    this.destroyTextPath(elem, path);
-                    // Bring attributes back
-                    this.updateTransform();
-                    // Set textOutline back for text()
-                    if (this.options && this.options.rotation) {
-                        this.applyTextOutline(this.options.style.textOutline);
-                    }
-                }
-                return this;
-            };
-            /**
-             * Add a shadow to the element. Must be called after the element is added to
-             * the DOM. In styled mode, this method is not used, instead use `defs` and
-             * filters.
-             *
-             * @example
-             * renderer.rect(10, 100, 100, 100)
-             *     .attr({ fill: 'red' })
-             *     .shadow(true);
-             *
-             * @function Highcharts.SVGElement#shadow
-             *
-             * @param {boolean|Highcharts.ShadowOptionsObject} [shadowOptions]
-             *        The shadow options. If `true`, the default options are applied. If
-             *        `false`, the current shadow will be removed.
-             *
-             * @param {Highcharts.SVGElement} [group]
-             *        The SVG group element where the shadows will be applied. The
-             *        default is to add it to the same parent as the current element.
-             *        Internally, this is ised for pie slices, where all the shadows are
-             *        added to an element behind all the slices.
-             *
-             * @param {boolean} [cutOff]
-             *        Used internally for column shadows.
-             *
-             * @return {Highcharts.SVGElement}
-             *         Returns the SVGElement for chaining.
-             */
-            SVGElement.prototype.shadow = function (shadowOptions, group, cutOff) {
-                var shadows = [],
-                    i,
-                    shadow,
-                    element = this.element,
-                    strokeWidth,
-                    shadowElementOpacity,
-                    update = false,
-                    oldShadowOptions = this.oldShadowOptions, 
-                    // compensate for inverted plot area
-                    transform;
-                var defaultShadowOptions = {
-                        color: '#000000',
-                        offsetX: 1,
-                        offsetY: 1,
-                        opacity: 0.15,
-                        width: 3
-                    };
-                var options;
-                if (shadowOptions === true) {
-                    options = defaultShadowOptions;
-                }
-                else if (typeof shadowOptions === 'object') {
-                    options = extend(defaultShadowOptions, shadowOptions);
-                }
-                // Update shadow when options change (#12091).
-                if (options) {
-                    // Go over each key to look for change
-                    if (options && oldShadowOptions) {
-                        objectEach(options, function (value, key) {
-                            if (value !== oldShadowOptions[key]) {
-                                update = true;
-                            }
-                        });
-                    }
-                    if (update) {
-                        this.destroyShadows();
-                    }
-                    this.oldShadowOptions = options;
-                }
-                if (!options) {
-                    this.destroyShadows();
-                }
-                else if (!this.shadows) {
-                    shadowElementOpacity = options.opacity / options.width;
-                    transform = this.parentInverted ?
-                        'translate(-1,-1)' :
-                        "translate(" + options.offsetX + ", " + options.offsetY + ")";
-                    for (i = 1; i <= options.width; i++) {
-                        shadow = element.cloneNode(false);
-                        strokeWidth = (options.width * 2) + 1 - (2 * i);
-                        attr(shadow, {
-                            stroke: (shadowOptions.color ||
-                                '#000000'),
-                            'stroke-opacity': shadowElementOpacity * i,
-                            'stroke-width': strokeWidth,
-                            transform: transform,
-                            fill: 'none'
-                        });
-                        shadow.setAttribute('class', (shadow.getAttribute('class') || '') + ' highcharts-shadow');
-                        if (cutOff) {
-                            attr(shadow, 'height', Math.max(attr(shadow, 'height') - strokeWidth, 0));
-                            shadow.cutHeight = strokeWidth;
-                        }
-                        if (group) {
-                            group.element.appendChild(shadow);
-                        }
-                        else if (element.parentNode) {
-                            element.parentNode.insertBefore(shadow, element);
-                        }
-                        shadows.push(shadow);
-                    }
-                    this.shadows = shadows;
-                }
-                return this;
-            };
-            /**
-             * Show the element after it has been hidden.
-             *
-             * @function Highcharts.SVGElement#show
-             *
-             * @param {boolean} [inherit=false]
-             *        Set the visibility attribute to `inherit` rather than `visible`.
-             *        The difference is that an element with `visibility="visible"`
-             *        will be visible even if the parent is hidden.
-             *
-             * @return {Highcharts.SVGElement}
-             *         Returns the SVGElement for chaining.
-             */
-            SVGElement.prototype.show = function (inherit) {
-                return this.attr({ visibility: inherit ? 'inherit' : 'visible' });
-            };
-            /**
-             * WebKit and Batik have problems with a stroke-width of zero, so in this
-             * case we remove the stroke attribute altogether. #1270, #1369, #3065,
-             * #3072.
-             *
-             * @private
-             * @function Highcharts.SVGElement#strokeSetter
-             * @param {number|string} value
-             * @param {string} key
-             * @param {Highcharts.SVGDOMElement} element
-             */
-            SVGElement.prototype.strokeSetter = function (value, key, element) {
-                this[key] = value;
-                // Only apply the stroke attribute if the stroke width is defined and
-                // larger than 0
-                if (this.stroke && this['stroke-width']) {
-                    // Use prototype as instance may be overridden
-                    SVGElement.prototype.fillSetter.call(this, this.stroke, 'stroke', element);
-                    element.setAttribute('stroke-width', this['stroke-width']);
-                    this.hasStroke = true;
-                }
-                else if (key === 'stroke-width' && value === 0 && this.hasStroke) {
-                    element.removeAttribute('stroke');
-                    this.hasStroke = false;
-                }
-                else if (this.renderer.styledMode && this['stroke-width']) {
-                    element.setAttribute('stroke-width', this['stroke-width']);
-                    this.hasStroke = true;
-                }
-            };
-            /**
-             * Get the computed stroke width in pixel values. This is used extensively
-             * when drawing shapes to ensure the shapes are rendered crisp and
-             * positioned correctly relative to each other. Using
-             * `shape-rendering: crispEdges` leaves us less control over positioning,
-             * for example when we want to stack columns next to each other, or position
-             * things pixel-perfectly within the plot box.
-             *
-             * The common pattern when placing a shape is:
-             * - Create the SVGElement and add it to the DOM. In styled mode, it will
-             *   now receive a stroke width from the style sheet. In classic mode we
-             *   will add the `stroke-width` attribute.
-             * - Read the computed `elem.strokeWidth()`.
-             * - Place it based on the stroke width.
-             *
-             * @function Highcharts.SVGElement#strokeWidth
-             *
-             * @return {number}
-             * The stroke width in pixels. Even if the given stroke widtch (in CSS or by
-             * attributes) is based on `em` or other units, the pixel size is returned.
-             */
-            SVGElement.prototype.strokeWidth = function () {
-                // In non-styled mode, read the stroke width as set by .attr
-                if (!this.renderer.styledMode) {
-                    return this['stroke-width'] || 0;
-                }
-                // In styled mode, read computed stroke width
-                var val = this.getStyle('stroke-width'),
-                    ret = 0,
-                    dummy;
-                // Read pixel values directly
-                if (val.indexOf('px') === val.length - 2) {
-                    ret = pInt(val);
-                    // Other values like em, pt etc need to be measured
-                }
-                else if (val !== '') {
-                    dummy = doc.createElementNS(SVG_NS, 'rect');
-                    attr(dummy, {
-                        width: val,
-                        'stroke-width': 0
-                    });
-                    this.element.parentNode.appendChild(dummy);
-                    ret = dummy.getBBox().width;
-                    dummy.parentNode.removeChild(dummy);
-                }
-                return ret;
-            };
+              });
+            }
+          }
+          // record information on the chosen unit - for dynamic label formatter
+          tickPositions.info = extend(normalizedInterval, {
+            higherRanks: higherRanks,
+            totalRange: interval * count,
+          });
+          return tickPositions;
+        };
+        return Time;
+      })();
+      H.Time = Time;
+
+      return H.Time;
+    }
+  );
+  _registerModule(
+    _modules,
+    "Core/Options.js",
+    [
+      _modules["Core/Globals.js"],
+      _modules["Core/Color/Color.js"],
+      _modules["Core/Time.js"],
+      _modules["Core/Utilities.js"],
+    ],
+    function (H, Color, Time, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      var isTouchDevice = H.isTouchDevice,
+        svg = H.svg;
+      var color = Color.parse;
+      var merge = U.merge;
+      /**
+       * @typedef {"plotBox"|"spacingBox"} Highcharts.ButtonRelativeToValue
+       */
+      /**
+       * Gets fired when a series is added to the chart after load time, using the
+       * `addSeries` method. Returning `false` prevents the series from being added.
+       *
+       * @callback Highcharts.ChartAddSeriesCallbackFunction
+       *
+       * @param {Highcharts.Chart} this
+       *        The chart on which the event occured.
+       *
+       * @param {Highcharts.ChartAddSeriesEventObject} event
+       *        The event that occured.
+       */
+      /**
+       * Contains common event information. Through the `options` property you can
+       * access the series options that were passed to the `addSeries` method.
+       *
+       * @interface Highcharts.ChartAddSeriesEventObject
+       */ /**
+       * The series options that were passed to the `addSeries` method.
+       * @name Highcharts.ChartAddSeriesEventObject#options
+       * @type {Highcharts.SeriesOptionsType}
+       */ /**
+       * Prevents the default behaviour of the event.
+       * @name Highcharts.ChartAddSeriesEventObject#preventDefault
+       * @type {Function}
+       */ /**
+       * The event target.
+       * @name Highcharts.ChartAddSeriesEventObject#target
+       * @type {Highcharts.Chart}
+       */ /**
+       * The event type.
+       * @name Highcharts.ChartAddSeriesEventObject#type
+       * @type {"addSeries"}
+       */
+      /**
+       * Gets fired when clicking on the plot background.
+       *
+       * @callback Highcharts.ChartClickCallbackFunction
+       *
+       * @param {Highcharts.Chart} this
+       *        The chart on which the event occured.
+       *
+       * @param {Highcharts.PointerEventObject} event
+       *        The event that occured.
+       */
+      /**
+       * Contains an axes of the clicked spot.
+       *
+       * @interface Highcharts.ChartClickEventAxisObject
+       */ /**
+       * Axis at the clicked spot.
+       * @name Highcharts.ChartClickEventAxisObject#axis
+       * @type {Highcharts.Axis}
+       */ /**
+       * Axis value at the clicked spot.
+       * @name Highcharts.ChartClickEventAxisObject#value
+       * @type {number}
+       */
+      /**
+       * Contains information about the clicked spot on the chart. Remember the unit
+       * of a datetime axis is milliseconds since 1970-01-01 00:00:00.
+       *
+       * @interface Highcharts.ChartClickEventObject
+       * @extends Highcharts.PointerEventObject
+       */ /**
+       * Information about the x-axis on the clicked spot.
+       * @name Highcharts.ChartClickEventObject#xAxis
+       * @type {Array<Highcharts.ChartClickEventAxisObject>}
+       */ /**
+       * Information about the y-axis on the clicked spot.
+       * @name Highcharts.ChartClickEventObject#yAxis
+       * @type {Array<Highcharts.ChartClickEventAxisObject>}
+       */ /**
+       * Information about the z-axis on the clicked spot.
+       * @name Highcharts.ChartClickEventObject#zAxis
+       * @type {Array<Highcharts.ChartClickEventAxisObject>|undefined}
+       */
+      /**
+       * Gets fired when the chart is finished loading.
+       *
+       * @callback Highcharts.ChartLoadCallbackFunction
+       *
+       * @param {Highcharts.Chart} this
+       *        The chart on which the event occured.
+       *
+       * @param {global.Event} event
+       *        The event that occured.
+       */
+      /**
+       * Fires when the chart is redrawn, either after a call to `chart.redraw()` or
+       * after an axis, series or point is modified with the `redraw` option set to
+       * `true`.
+       *
+       * @callback Highcharts.ChartRedrawCallbackFunction
+       *
+       * @param {Highcharts.Chart} this
+       *        The chart on which the event occured.
+       *
+       * @param {global.Event} event
+       *        The event that occured.
+       */
+      /**
+       * Gets fired after initial load of the chart (directly after the `load` event),
+       * and after each redraw (directly after the `redraw` event).
+       *
+       * @callback Highcharts.ChartRenderCallbackFunction
+       *
+       * @param {Highcharts.Chart} this
+       *        The chart on which the event occured.
+       *
+       * @param {global.Event} event
+       *        The event that occured.
+       */
+      /**
+       * Gets fired when an area of the chart has been selected. The default action
+       * for the selection event is to zoom the chart to the selected area. It can be
+       * prevented by calling `event.preventDefault()` or return false.
+       *
+       * @callback Highcharts.ChartSelectionCallbackFunction
+       *
+       * @param {Highcharts.Chart} this
+       *        The chart on which the event occured.
+       *
+       * @param {global.ChartSelectionContextObject} event
+       *        Event informations
+       *
+       * @return {boolean|undefined}
+       *         Return false to prevent the default action, usually zoom.
+       */
+      /**
+       * The primary axes are `xAxis[0]` and `yAxis[0]`. Remember the unit of a
+       * datetime axis is milliseconds since 1970-01-01 00:00:00.
+       *
+       * @interface Highcharts.ChartSelectionContextObject
+       * @extends global.Event
+       */ /**
+       * Arrays containing the axes of each dimension and each axis' min and max
+       * values.
+       * @name Highcharts.ChartSelectionContextObject#xAxis
+       * @type {Array<Highcharts.ChartSelectionAxisContextObject>}
+       */ /**
+       * Arrays containing the axes of each dimension and each axis' min and max
+       * values.
+       * @name Highcharts.ChartSelectionContextObject#yAxis
+       * @type {Array<Highcharts.ChartSelectionAxisContextObject>}
+       */
+      /**
+       * Axis context of the selection.
+       *
+       * @interface Highcharts.ChartSelectionAxisContextObject
+       */ /**
+       * The selected Axis.
+       * @name Highcharts.ChartSelectionAxisContextObject#axis
+       * @type {Highcharts.Axis}
+       */ /**
+       * The maximum axis value, either automatic or set manually.
+       * @name Highcharts.ChartSelectionAxisContextObject#max
+       * @type {number}
+       */ /**
+       * The minimum axis value, either automatic or set manually.
+       * @name Highcharts.ChartSelectionAxisContextObject#min
+       * @type {number}
+       */
+      (""); // detach doclets above
+      /* ************************************************************************** *
+       * Handle the options                                                         *
+       * ************************************************************************** */
+      /**
+       * Global default settings.
+       *
+       * @name Highcharts.defaultOptions
+       * @type {Highcharts.Options}
+       */ /**
+       * @optionparent
+       */
+      H.defaultOptions = {
+        /**
+         * An array containing the default colors for the chart's series. When
+         * all colors are used, new colors are pulled from the start again.
+         *
+         * Default colors can also be set on a series or series.type basis,
+         * see [column.colors](#plotOptions.column.colors),
+         * [pie.colors](#plotOptions.pie.colors).
+         *
+         * In styled mode, the colors option doesn't exist. Instead, colors
+         * are defined in CSS and applied either through series or point class
+         * names, or through the [chart.colorCount](#chart.colorCount) option.
+         *
+         *
+         * ### Legacy
+         *
+         * In Highcharts 3.x, the default colors were:
+         * ```js
+         * colors: ['#2f7ed8', '#0d233a', '#8bbc21', '#910000', '#1aadce',
+         *         '#492970', '#f28f43', '#77a1e5', '#c42525', '#a6c96a']
+         * ```
+         *
+         * In Highcharts 2.x, the default colors were:
+         * ```js
+         * colors: ['#4572A7', '#AA4643', '#89A54E', '#80699B', '#3D96AE',
+         *         '#DB843D', '#92A8CD', '#A47D7C', '#B5CA92']
+         * ```
+         *
+         * @sample {highcharts} highcharts/chart/colors/
+         *         Assign a global color theme
+         *
+         * @type    {Array<Highcharts.ColorString>}
+         * @default ["#7cb5ec", "#434348", "#90ed7d", "#f7a35c", "#8085e9",
+         *          "#f15c80", "#e4d354", "#2b908f", "#f45b5b", "#91e8e1"]
+         */
+        colors:
+          "#7cb5ec #434348 #90ed7d #f7a35c #8085e9 #f15c80 #e4d354 #2b908f #f45b5b #91e8e1".split(
+            " "
+          ),
+        /**
+         * Styled mode only. Configuration object for adding SVG definitions for
+         * reusable elements. See [gradients, shadows and
+         * patterns](https://www.highcharts.com/docs/chart-design-and-style/gradients-shadows-and-patterns)
+         * for more information and code examples.
+         *
+         * @type      {*}
+         * @since     5.0.0
+         * @apioption defs
+         */
+        /**
+         * @ignore-option
+         */
+        symbols: ["circle", "diamond", "square", "triangle", "triangle-down"],
+        /**
+         * The language object is global and it can't be set on each chart
+         * initialization. Instead, use `Highcharts.setOptions` to set it before any
+         * chart is initialized.
+         *
+         * ```js
+         * Highcharts.setOptions({
+         *     lang: {
+         *         months: [
+         *             'Janvier', 'Février', 'Mars', 'Avril',
+         *             'Mai', 'Juin', 'Juillet', 'Août',
+         *             'Septembre', 'Octobre', 'Novembre', 'Décembre'
+         *         ],
+         *         weekdays: [
+         *             'Dimanche', 'Lundi', 'Mardi', 'Mercredi',
+         *             'Jeudi', 'Vendredi', 'Samedi'
+         *         ]
+         *     }
+         * });
+         * ```
+         */
+        lang: {
+          /**
+           * The loading text that appears when the chart is set into the loading
+           * state following a call to `chart.showLoading`.
+           */
+          loading: "Loading...",
+          /**
+           * An array containing the months names. Corresponds to the `%B` format
+           * in `Highcharts.dateFormat()`.
+           *
+           * @type    {Array<string>}
+           * @default ["January", "February", "March", "April", "May", "June",
+           *          "July", "August", "September", "October", "November",
+           *          "December"]
+           */
+          months: [
+            "January",
+            "February",
+            "March",
+            "April",
+            "May",
+            "June",
+            "July",
+            "August",
+            "September",
+            "October",
+            "November",
+            "December",
+          ],
+          /**
+           * An array containing the months names in abbreviated form. Corresponds
+           * to the `%b` format in `Highcharts.dateFormat()`.
+           *
+           * @type    {Array<string>}
+           * @default ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
+           *          "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
+           */
+          shortMonths: [
+            "Jan",
+            "Feb",
+            "Mar",
+            "Apr",
+            "May",
+            "Jun",
+            "Jul",
+            "Aug",
+            "Sep",
+            "Oct",
+            "Nov",
+            "Dec",
+          ],
+          /**
+           * An array containing the weekday names.
+           *
+           * @type    {Array<string>}
+           * @default ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
+           *          "Friday", "Saturday"]
+           */
+          weekdays: [
+            "Sunday",
+            "Monday",
+            "Tuesday",
+            "Wednesday",
+            "Thursday",
+            "Friday",
+            "Saturday",
+          ],
+          /**
+           * Short week days, starting Sunday. If not specified, Highcharts uses
+           * the first three letters of the `lang.weekdays` option.
+           *
+           * @sample highcharts/lang/shortweekdays/
+           *         Finnish two-letter abbreviations
+           *
+           * @type      {Array<string>}
+           * @since     4.2.4
+           * @apioption lang.shortWeekdays
+           */
+          /**
+           * What to show in a date field for invalid dates. Defaults to an empty
+           * string.
+           *
+           * @type      {string}
+           * @since     4.1.8
+           * @product   highcharts highstock
+           * @apioption lang.invalidDate
+           */
+          /**
+           * The title appearing on hovering the zoom in button. The text itself
+           * defaults to "+" and can be changed in the button options.
+           *
+           * @type      {string}
+           * @default   Zoom in
+           * @product   highmaps
+           * @apioption lang.zoomIn
+           */
+          /**
+           * The title appearing on hovering the zoom out button. The text itself
+           * defaults to "-" and can be changed in the button options.
+           *
+           * @type      {string}
+           * @default   Zoom out
+           * @product   highmaps
+           * @apioption lang.zoomOut
+           */
+          /**
+           * The default decimal point used in the `Highcharts.numberFormat`
+           * method unless otherwise specified in the function arguments.
+           *
+           * @since 1.2.2
+           */
+          decimalPoint: ".",
+          /**
+           * [Metric prefixes](https://en.wikipedia.org/wiki/Metric_prefix) used
+           * to shorten high numbers in axis labels. Replacing any of the
+           * positions with `null` causes the full number to be written. Setting
+           * `numericSymbols` to `null` disables shortening altogether.
+           *
+           * @sample {highcharts} highcharts/lang/numericsymbols/
+           *         Replacing the symbols with text
+           * @sample {highstock} highcharts/lang/numericsymbols/
+           *         Replacing the symbols with text
+           *
+           * @type    {Array<string>}
+           * @default ["k", "M", "G", "T", "P", "E"]
+           * @since   2.3.0
+           */
+          numericSymbols: ["k", "M", "G", "T", "P", "E"],
+          /**
+           * The magnitude of [numericSymbols](#lang.numericSymbol) replacements.
+           * Use 10000 for Japanese, Korean and various Chinese locales, which
+           * use symbols for 10^4, 10^8 and 10^12.
+           *
+           * @sample highcharts/lang/numericsymbolmagnitude/
+           *         10000 magnitude for Japanese
+           *
+           * @type      {number}
+           * @default   1000
+           * @since     5.0.3
+           * @apioption lang.numericSymbolMagnitude
+           */
+          /**
+           * The text for the label appearing when a chart is zoomed.
+           *
+           * @since 1.2.4
+           */
+          resetZoom: "Reset zoom",
+          /**
+           * The tooltip title for the label appearing when a chart is zoomed.
+           *
+           * @since 1.2.4
+           */
+          resetZoomTitle: "Reset zoom level 1:1",
+          /**
+           * The default thousands separator used in the `Highcharts.numberFormat`
+           * method unless otherwise specified in the function arguments. Defaults
+           * to a single space character, which is recommended in
+           * [ISO 31-0](https://en.wikipedia.org/wiki/ISO_31-0#Numbers) and works
+           * across Anglo-American and continental European languages.
+           *
+           * @default \u0020
+           * @since   1.2.2
+           */
+          thousandsSep: " ",
+        },
+        /**
+         * Global options that don't apply to each chart. These options, like
+         * the `lang` options, must be set using the `Highcharts.setOptions`
+         * method.
+         *
+         * ```js
+         * Highcharts.setOptions({
+         *     global: {
+         *         useUTC: false
+         *     }
+         * });
+         * ```
+         */
+        /**
+         * _Canvg rendering for Android 2.x is removed as of Highcharts 5.0\.
+         * Use the [libURL](#exporting.libURL) option to configure exporting._
+         *
+         * The URL to the additional file to lazy load for Android 2.x devices.
+         * These devices don't support SVG, so we download a helper file that
+         * contains [canvg](https://github.com/canvg/canvg), its dependency
+         * rbcolor, and our own CanVG Renderer class. To avoid hotlinking to
+         * our site, you can install canvas-tools.js on your own server and
+         * change this option accordingly.
+         *
+         * @deprecated
+         *
+         * @type      {string}
+         * @default   https://code.highcharts.com/{version}/modules/canvas-tools.js
+         * @product   highcharts highmaps
+         * @apioption global.canvasToolsURL
+         */
+        /**
+         * This option is deprecated since v6.0.5. Instead, use
+         * [time.useUTC](#time.useUTC) that supports individual time settings
+         * per chart.
+         *
+         * @deprecated
+         *
+         * @type      {boolean}
+         * @apioption global.useUTC
+         */
+        /**
+         * This option is deprecated since v6.0.5. Instead, use
+         * [time.Date](#time.Date) that supports individual time settings
+         * per chart.
+         *
+         * @deprecated
+         *
+         * @type      {Function}
+         * @product   highcharts highstock
+         * @apioption global.Date
+         */
+        /**
+         * This option is deprecated since v6.0.5. Instead, use
+         * [time.getTimezoneOffset](#time.getTimezoneOffset) that supports
+         * individual time settings per chart.
+         *
+         * @deprecated
+         *
+         * @type      {Function}
+         * @product   highcharts highstock
+         * @apioption global.getTimezoneOffset
+         */
+        /**
+         * This option is deprecated since v6.0.5. Instead, use
+         * [time.timezone](#time.timezone) that supports individual time
+         * settings per chart.
+         *
+         * @deprecated
+         *
+         * @type      {string}
+         * @product   highcharts highstock
+         * @apioption global.timezone
+         */
+        /**
+         * This option is deprecated since v6.0.5. Instead, use
+         * [time.timezoneOffset](#time.timezoneOffset) that supports individual
+         * time settings per chart.
+         *
+         * @deprecated
+         *
+         * @type      {number}
+         * @product   highcharts highstock
+         * @apioption global.timezoneOffset
+         */
+        global: {},
+        /**
+         * Time options that can apply globally or to individual charts. These
+         * settings affect how `datetime` axes are laid out, how tooltips are
+         * formatted, how series
+         * [pointIntervalUnit](#plotOptions.series.pointIntervalUnit) works and how
+         * the Highstock range selector handles time.
+         *
+         * The common use case is that all charts in the same Highcharts object
+         * share the same time settings, in which case the global settings are set
+         * using `setOptions`.
+         *
+         * ```js
+         * // Apply time settings globally
+         * Highcharts.setOptions({
+         *     time: {
+         *         timezone: 'Europe/London'
+         *     }
+         * });
+         * // Apply time settings by instance
+         * var chart = Highcharts.chart('container', {
+         *     time: {
+         *         timezone: 'America/New_York'
+         *     },
+         *     series: [{
+         *         data: [1, 4, 3, 5]
+         *     }]
+         * });
+         *
+         * // Use the Time object
+         * console.log(
+         *        'Current time in New York',
+         *        chart.time.dateFormat('%Y-%m-%d %H:%M:%S', Date.now())
+         * );
+         * ```
+         *
+         * Since v6.0.5, the time options were moved from the `global` obect to the
+         * `time` object, and time options can be set on each individual chart.
+         *
+         * @sample {highcharts|highstock}
+         *         highcharts/time/timezone/
+         *         Set the timezone globally
+         * @sample {highcharts}
+         *         highcharts/time/individual/
+         *         Set the timezone per chart instance
+         * @sample {highstock}
+         *         stock/time/individual/
+         *         Set the timezone per chart instance
+         *
+         * @since     6.0.5
+         * @optionparent time
+         */
+        time: {
+          /**
+           * A custom `Date` class for advanced date handling. For example,
+           * [JDate](https://github.com/tahajahangir/jdate) can be hooked in to
+           * handle Jalali dates.
+           *
+           * @type      {*}
+           * @since     4.0.4
+           * @product   highcharts highstock gantt
+           */
+          Date: void 0,
+          /**
+           * A callback to return the time zone offset for a given datetime. It
+           * takes the timestamp in terms of milliseconds since January 1 1970,
+           * and returns the timezone offset in minutes. This provides a hook
+           * for drawing time based charts in specific time zones using their
+           * local DST crossover dates, with the help of external libraries.
+           *
+           * @see [global.timezoneOffset](#global.timezoneOffset)
+           *
+           * @sample {highcharts|highstock} highcharts/time/gettimezoneoffset/
+           *         Use moment.js to draw Oslo time regardless of browser locale
+           *
+           * @type      {Highcharts.TimezoneOffsetCallbackFunction}
+           * @since     4.1.0
+           * @product   highcharts highstock gantt
+           */
+          getTimezoneOffset: void 0,
+          /**
+           * Requires [moment.js](https://momentjs.com/). If the timezone option
+           * is specified, it creates a default
+           * [getTimezoneOffset](#time.getTimezoneOffset) function that looks
+           * up the specified timezone in moment.js. If moment.js is not included,
+           * this throws a Highcharts error in the console, but does not crash the
+           * chart.
+           *
+           * @see [getTimezoneOffset](#time.getTimezoneOffset)
+           *
+           * @sample {highcharts|highstock} highcharts/time/timezone/
+           *         Europe/Oslo
+           *
+           * @type      {string}
+           * @since     5.0.7
+           * @product   highcharts highstock gantt
+           */
+          timezone: void 0,
+          /**
+           * The timezone offset in minutes. Positive values are west, negative
+           * values are east of UTC, as in the ECMAScript
+           * [getTimezoneOffset](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset)
+           * method. Use this to display UTC based data in a predefined time zone.
+           *
+           * @see [time.getTimezoneOffset](#time.getTimezoneOffset)
+           *
+           * @sample {highcharts|highstock} highcharts/time/timezoneoffset/
+           *         Timezone offset
+           *
+           * @since     3.0.8
+           * @product   highcharts highstock gantt
+           */
+          timezoneOffset: 0,
+          /**
+           * Whether to use UTC time for axis scaling, tickmark placement and
+           * time display in `Highcharts.dateFormat`. Advantages of using UTC
+           * is that the time displays equally regardless of the user agent's
+           * time zone settings. Local time can be used when the data is loaded
+           * in real time or when correct Daylight Saving Time transitions are
+           * required.
+           *
+           * @sample {highcharts} highcharts/time/useutc-true/
+           *         True by default
+           * @sample {highcharts} highcharts/time/useutc-false/
+           *         False
+           */
+          useUTC: true,
+        },
+        /**
+         * General options for the chart.
+         */
+        chart: {
+          /**
+           * Default `mapData` for all series. If set to a string, it functions
+           * as an index into the `Highcharts.maps` array. Otherwise it is
+           * interpreted as map data.
+           *
+           * @see [mapData](#series.map.mapData)
+           *
+           * @sample    maps/demo/geojson
+           *            Loading geoJSON data
+           * @sample    maps/chart/topojson
+           *            Loading topoJSON converted to geoJSON
+           *
+           * @type      {string|Array<*>|Highcharts.GeoJSON}
+           * @since     5.0.0
+           * @product   highmaps
+           * @apioption chart.map
+           */
+          /**
+           * Set lat/lon transformation definitions for the chart. If not defined,
+           * these are extracted from the map data.
+           *
+           * @type      {*}
+           * @since     5.0.0
+           * @product   highmaps
+           * @apioption chart.mapTransforms
+           */
+          /**
+           * When using multiple axis, the ticks of two or more opposite axes
+           * will automatically be aligned by adding ticks to the axis or axes
+           * with the least ticks, as if `tickAmount` were specified.
+           *
+           * This can be prevented by setting `alignTicks` to false. If the grid
+           * lines look messy, it's a good idea to hide them for the secondary
+           * axis by setting `gridLineWidth` to 0.
+           *
+           * If `startOnTick` or `endOnTick` in an Axis options are set to false,
+           * then the `alignTicks ` will be disabled for the Axis.
+           *
+           * Disabled for logarithmic axes.
+           *
+           * @sample {highcharts} highcharts/chart/alignticks-true/
+           *         True by default
+           * @sample {highcharts} highcharts/chart/alignticks-false/
+           *         False
+           * @sample {highstock} stock/chart/alignticks-true/
+           *         True by default
+           * @sample {highstock} stock/chart/alignticks-false/
+           *         False
+           *
+           * @type      {boolean}
+           * @default   true
+           * @product   highcharts highstock gantt
+           * @apioption chart.alignTicks
+           */
+          /**
+           * Set the overall animation for all chart updating. Animation can be
+           * disabled throughout the chart by setting it to false here. It can
+           * be overridden for each individual API method as a function parameter.
+           * The only animation not affected by this option is the initial series
+           * animation, see [plotOptions.series.animation](
+           * #plotOptions.series.animation).
+           *
+           * The animation can either be set as a boolean or a configuration
+           * object. If `true`, it will use the 'swing' jQuery easing and a
+           * duration of 500 ms. If used as a configuration object, the following
+           * properties are supported:
+           *
+           * - `defer`: The animation delay time in milliseconds.
+           *
+           * - `duration`: The duration of the animation in milliseconds.
+           *
+           * - `easing`: A string reference to an easing function set on the
+           *   `Math` object. See
+           *   [the easing demo](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/series-animation-easing/).
+           *
+           * When zooming on a series with less than 100 points, the chart redraw
+           * will be done with animation, but in case of more data points, it is
+           * necessary to set this option to ensure animation on zoom.
+           *
+           * @sample {highcharts} highcharts/chart/animation-none/
+           *         Updating with no animation
+           * @sample {highcharts} highcharts/chart/animation-duration/
+           *         With a longer duration
+           * @sample {highcharts} highcharts/chart/animation-easing/
+           *         With a jQuery UI easing
+           * @sample {highmaps} maps/chart/animation-none/
+           *         Updating with no animation
+           * @sample {highmaps} maps/chart/animation-duration/
+           *         With a longer duration
+           *
+           * @type      {boolean|Partial<Highcharts.AnimationOptionsObject>}
+           * @default   undefined
+           * @apioption chart.animation
+           */
+          /**
+           * A CSS class name to apply to the charts container `div`, allowing
+           * unique CSS styling for each chart.
+           *
+           * @type      {string}
+           * @apioption chart.className
+           */
+          /**
+           * Event listeners for the chart.
+           *
+           * @apioption chart.events
+           */
+          /**
+           * Fires when a series is added to the chart after load time, using the
+           * `addSeries` method. One parameter, `event`, is passed to the
+           * function, containing common event information. Through
+           * `event.options` you can access the series options that were passed to
+           * the `addSeries` method. Returning false prevents the series from
+           * being added.
+           *
+           * @sample {highcharts} highcharts/chart/events-addseries/
+           *         Alert on add series
+           * @sample {highstock} stock/chart/events-addseries/
+           *         Alert on add series
+           *
+           * @type      {Highcharts.ChartAddSeriesCallbackFunction}
+           * @since     1.2.0
+           * @context   Highcharts.Chart
+           * @apioption chart.events.addSeries
+           */
+          /**
+           * Fires when clicking on the plot background. One parameter, `event`,
+           * is passed to the function, containing common event information.
+           *
+           * Information on the clicked spot can be found through `event.xAxis`
+           * and `event.yAxis`, which are arrays containing the axes of each
+           * dimension and each axis' value at the clicked spot. The primary axes
+           * are `event.xAxis[0]` and `event.yAxis[0]`. Remember the unit of a
+           * datetime axis is milliseconds since 1970-01-01 00:00:00.
+           *
+           * ```js
+           * click: function(e) {
+           *     console.log(
+           *         Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', e.xAxis[0].value),
+           *         e.yAxis[0].value
+           *     )
+           * }
+           * ```
+           *
+           * @sample {highcharts} highcharts/chart/events-click/
+           *         Alert coordinates on click
+           * @sample {highcharts} highcharts/chart/events-container/
+           *         Alternatively, attach event to container
+           * @sample {highstock} stock/chart/events-click/
+           *         Alert coordinates on click
+           * @sample {highstock} highcharts/chart/events-container/
+           *         Alternatively, attach event to container
+           * @sample {highmaps} maps/chart/events-click/
+           *         Record coordinates on click
+           * @sample {highmaps} highcharts/chart/events-container/
+           *         Alternatively, attach event to container
+           *
+           * @type      {Highcharts.ChartClickCallbackFunction}
+           * @since     1.2.0
+           * @context   Highcharts.Chart
+           * @apioption chart.events.click
+           */
+          /**
+           * Fires when the chart is finished loading. Since v4.2.2, it also waits
+           * for images to be loaded, for example from point markers. One
+           * parameter, `event`, is passed to the function, containing common
+           * event information.
+           *
+           * There is also a second parameter to the chart constructor where a
+           * callback function can be passed to be executed on chart.load.
+           *
+           * @sample {highcharts} highcharts/chart/events-load/
+           *         Alert on chart load
+           * @sample {highstock} stock/chart/events-load/
+           *         Alert on chart load
+           * @sample {highmaps} maps/chart/events-load/
+           *         Add series on chart load
+           *
+           * @type      {Highcharts.ChartLoadCallbackFunction}
+           * @context   Highcharts.Chart
+           * @apioption chart.events.load
+           */
+          /**
+           * Fires when the chart is redrawn, either after a call to
+           * `chart.redraw()` or after an axis, series or point is modified with
+           * the `redraw` option set to `true`. One parameter, `event`, is passed
+           * to the function, containing common event information.
+           *
+           * @sample {highcharts} highcharts/chart/events-redraw/
+           *         Alert on chart redraw
+           * @sample {highstock} stock/chart/events-redraw/
+           *         Alert on chart redraw when adding a series or moving the
+           *         zoomed range
+           * @sample {highmaps} maps/chart/events-redraw/
+           *         Set subtitle on chart redraw
+           *
+           * @type      {Highcharts.ChartRedrawCallbackFunction}
+           * @since     1.2.0
+           * @context   Highcharts.Chart
+           * @apioption chart.events.redraw
+           */
+          /**
+           * Fires after initial load of the chart (directly after the `load`
+           * event), and after each redraw (directly after the `redraw` event).
+           *
+           * @type      {Highcharts.ChartRenderCallbackFunction}
+           * @since     5.0.7
+           * @context   Highcharts.Chart
+           * @apioption chart.events.render
+           */
+          /**
+           * Fires when an area of the chart has been selected. Selection is
+           * enabled by setting the chart's zoomType. One parameter, `event`, is
+           * passed to the function, containing common event information. The
+           * default action for the selection event is to zoom the chart to the
+           * selected area. It can be prevented by calling
+           * `event.preventDefault()` or return false.
+           *
+           * Information on the selected area can be found through `event.xAxis`
+           * and `event.yAxis`, which are arrays containing the axes of each
+           * dimension and each axis' min and max values. The primary axes are
+           * `event.xAxis[0]` and `event.yAxis[0]`. Remember the unit of a
+           * datetime axis is milliseconds since 1970-01-01 00:00:00.
+           *
+           * ```js
+           * selection: function(event) {
+           *     // log the min and max of the primary, datetime x-axis
+           *     console.log(
+           *         Highcharts.dateFormat(
+           *             '%Y-%m-%d %H:%M:%S',
+           *             event.xAxis[0].min
+           *         ),
+           *         Highcharts.dateFormat(
+           *             '%Y-%m-%d %H:%M:%S',
+           *             event.xAxis[0].max
+           *         )
+           *     );
+           *     // log the min and max of the y axis
+           *     console.log(event.yAxis[0].min, event.yAxis[0].max);
+           * }
+           * ```
+           *
+           * @sample {highcharts} highcharts/chart/events-selection/
+           *         Report on selection and reset
+           * @sample {highcharts} highcharts/chart/events-selection-points/
+           *         Select a range of points through a drag selection
+           * @sample {highstock} stock/chart/events-selection/
+           *         Report on selection and reset
+           * @sample {highstock} highcharts/chart/events-selection-points/
+           *         Select a range of points through a drag selection
+           *         (Highcharts)
+           *
+           * @type      {Highcharts.ChartSelectionCallbackFunction}
+           * @apioption chart.events.selection
+           */
+          /**
+           * The margin between the outer edge of the chart and the plot area.
+           * The numbers in the array designate top, right, bottom and left
+           * respectively. Use the options `marginTop`, `marginRight`,
+           * `marginBottom` and `marginLeft` for shorthand setting of one option.
+           *
+           * By default there is no margin. The actual space is dynamically
+           * calculated from the offset of axis labels, axis title, title,
+           * subtitle and legend in addition to the `spacingTop`, `spacingRight`,
+           * `spacingBottom` and `spacingLeft` options.
+           *
+           * @sample {highcharts} highcharts/chart/margins-zero/
+           *         Zero margins
+           * @sample {highstock} stock/chart/margin-zero/
+           *         Zero margins
+           *
+           * @type      {number|Array<number>}
+           * @apioption chart.margin
+           */
+          /**
+           * The margin between the bottom outer edge of the chart and the plot
+           * area. Use this to set a fixed pixel value for the margin as opposed
+           * to the default dynamic margin. See also `spacingBottom`.
+           *
+           * @sample {highcharts} highcharts/chart/marginbottom/
+           *         100px bottom margin
+           * @sample {highstock} stock/chart/marginbottom/
+           *         100px bottom margin
+           * @sample {highmaps} maps/chart/margin/
+           *         100px margins
+           *
+           * @type      {number}
+           * @since     2.0
+           * @apioption chart.marginBottom
+           */
+          /**
+           * The margin between the left outer edge of the chart and the plot
+           * area. Use this to set a fixed pixel value for the margin as opposed
+           * to the default dynamic margin. See also `spacingLeft`.
+           *
+           * @sample {highcharts} highcharts/chart/marginleft/
+           *         150px left margin
+           * @sample {highstock} stock/chart/marginleft/
+           *         150px left margin
+           * @sample {highmaps} maps/chart/margin/
+           *         100px margins
+           *
+           * @type      {number}
+           * @since     2.0
+           * @apioption chart.marginLeft
+           */
+          /**
+           * The margin between the right outer edge of the chart and the plot
+           * area. Use this to set a fixed pixel value for the margin as opposed
+           * to the default dynamic margin. See also `spacingRight`.
+           *
+           * @sample {highcharts} highcharts/chart/marginright/
+           *         100px right margin
+           * @sample {highstock} stock/chart/marginright/
+           *         100px right margin
+           * @sample {highmaps} maps/chart/margin/
+           *         100px margins
+           *
+           * @type      {number}
+           * @since     2.0
+           * @apioption chart.marginRight
+           */
+          /**
+           * The margin between the top outer edge of the chart and the plot area.
+           * Use this to set a fixed pixel value for the margin as opposed to
+           * the default dynamic margin. See also `spacingTop`.
+           *
+           * @sample {highcharts} highcharts/chart/margintop/ 100px top margin
+           * @sample {highstock} stock/chart/margintop/
+           *         100px top margin
+           * @sample {highmaps} maps/chart/margin/
+           *         100px margins
+           *
+           * @type      {number}
+           * @since     2.0
+           * @apioption chart.marginTop
+           */
+          /**
+           * Callback function to override the default function that formats all
+           * the numbers in the chart. Returns a string with the formatted number.
+           *
+           * @sample highcharts/members/highcharts-numberformat
+           *      Arabic digits in Highcharts
+           * @type {Highcharts.NumberFormatterCallbackFunction}
+           * @since 8.0.0
+           * @apioption chart.numberFormatter
+           */
+          /**
+           * Allows setting a key to switch between zooming and panning. Can be
+           * one of `alt`, `ctrl`, `meta` (the command key on Mac and Windows
+           * key on Windows) or `shift`. The keys are mapped directly to the key
+           * properties of the click event argument (`event.altKey`,
+           * `event.ctrlKey`, `event.metaKey` and `event.shiftKey`).
+           *
+           * @type       {string}
+           * @since      4.0.3
+           * @product    highcharts gantt
+           * @validvalue ["alt", "ctrl", "meta", "shift"]
+           * @apioption  chart.panKey
+           */
+          /**
+           * Allow panning in a chart. Best used with [panKey](#chart.panKey)
+           * to combine zooming and panning.
+           *
+           * On touch devices, when the [tooltip.followTouchMove](
+           * #tooltip.followTouchMove) option is `true` (default), panning
+           * requires two fingers. To allow panning with one finger, set
+           * `followTouchMove` to `false`.
+           *
+           * @sample  {highcharts} highcharts/chart/pankey/ Zooming and panning
+           * @sample  {highstock} stock/chart/panning/ Zooming and xy panning
+           *
+           * @product highcharts highstock gantt
+           * @apioption chart.panning
+           */
+          /**
+           * Enable or disable chart panning.
+           *
+           * @type      {boolean}
+           * @default   {highcharts} false
+           * @default   {highstock} true
+           * @apioption chart.panning.enabled
+           */
+          /**
+           * Decides in what dimensions the user can pan the chart. Can be
+           * one of `x`, `y`, or `xy`.
+           *
+           * @sample {highcharts} highcharts/chart/panning-type
+           *         Zooming and xy panning
+           *
+           * @type    {string}
+           * @validvalue ["x", "y", "xy"]
+           * @default x
+           * @apioption chart.panning.type
+           */
+          /**
+           * Equivalent to [zoomType](#chart.zoomType), but for multitouch
+           * gestures only. By default, the `pinchType` is the same as the
+           * `zoomType` setting. However, pinching can be enabled separately in
+           * some cases, for example in stock charts where a mouse drag pans the
+           * chart, while pinching is enabled. When [tooltip.followTouchMove](
+           * #tooltip.followTouchMove) is true, pinchType only applies to
+           * two-finger touches.
+           *
+           * @type       {string}
+           * @default    {highcharts} undefined
+           * @default    {highstock} x
+           * @since      3.0
+           * @product    highcharts highstock gantt
+           * @validvalue ["x", "y", "xy"]
+           * @apioption  chart.pinchType
+           */
+          /**
+           * Whether to apply styled mode. When in styled mode, no presentational
+           * attributes or CSS are applied to the chart SVG. Instead, CSS rules
+           * are required to style the chart. The default style sheet is
+           * available from `https://code.highcharts.com/css/highcharts.css`.
+           *
+           * @type       {boolean}
+           * @default    false
+           * @since      7.0
+           * @apioption  chart.styledMode
+           */
+          styledMode: false,
+          /**
+           * The corner radius of the outer chart border.
+           *
+           * @sample {highcharts} highcharts/chart/borderradius/
+           *         20px radius
+           * @sample {highstock} stock/chart/border/
+           *         10px radius
+           * @sample {highmaps} maps/chart/border/
+           *         Border options
+           *
+           */
+          borderRadius: 0,
+          /**
+           * In styled mode, this sets how many colors the class names
+           * should rotate between. With ten colors, series (or points) are
+           * given class names like `highcharts-color-0`, `highcharts-color-0`
+           * [...] `highcharts-color-9`. The equivalent in non-styled mode
+           * is to set colors using the [colors](#colors) setting.
+           *
+           * @since      5.0.0
+           */
+          colorCount: 10,
+          /**
+           * Alias of `type`.
+           *
+           * @sample {highcharts} highcharts/chart/defaultseriestype/
+           *         Bar
+           *
+           * @deprecated
+           *
+           * @product highcharts
+           */
+          defaultSeriesType: "line",
+          /**
+           * If true, the axes will scale to the remaining visible series once
+           * one series is hidden. If false, hiding and showing a series will
+           * not affect the axes or the other series. For stacks, once one series
+           * within the stack is hidden, the rest of the stack will close in
+           * around it even if the axis is not affected.
+           *
+           * @sample {highcharts} highcharts/chart/ignorehiddenseries-true/
+           *         True by default
+           * @sample {highcharts} highcharts/chart/ignorehiddenseries-false/
+           *         False
+           * @sample {highcharts} highcharts/chart/ignorehiddenseries-true-stacked/
+           *         True with stack
+           * @sample {highstock} stock/chart/ignorehiddenseries-true/
+           *         True by default
+           * @sample {highstock} stock/chart/ignorehiddenseries-false/
+           *         False
+           *
+           * @since   1.2.0
+           * @product highcharts highstock gantt
+           */
+          ignoreHiddenSeries: true,
+          /**
+           * Whether to invert the axes so that the x axis is vertical and y axis
+           * is horizontal. When `true`, the x axis is [reversed](#xAxis.reversed)
+           * by default.
+           *
+           * @productdesc {highcharts}
+           * If a bar series is present in the chart, it will be inverted
+           * automatically. Inverting the chart doesn't have an effect if there
+           * are no cartesian series in the chart, or if the chart is
+           * [polar](#chart.polar).
+           *
+           * @sample {highcharts} highcharts/chart/inverted/
+           *         Inverted line
+           * @sample {highstock} stock/navigator/inverted/
+           *         Inverted stock chart
+           *
+           * @type      {boolean}
+           * @default   false
+           * @product   highcharts highstock gantt
+           * @apioption chart.inverted
+           */
+          /**
+           * The distance between the outer edge of the chart and the content,
+           * like title or legend, or axis title and labels if present. The
+           * numbers in the array designate top, right, bottom and left
+           * respectively. Use the options spacingTop, spacingRight, spacingBottom
+           * and spacingLeft options for shorthand setting of one option.
+           *
+           * @type    {Array<number>}
+           * @see     [chart.margin](#chart.margin)
+           * @default [10, 10, 15, 10]
+           * @since   3.0.6
+           */
+          spacing: [10, 10, 15, 10],
+          /**
+           * The button that appears after a selection zoom, allowing the user
+           * to reset zoom.
+           */
+          resetZoomButton: {
+            /**
+             * What frame the button placement should be related to. Can be
+             * either `plotBox` or `spacingBox`.
+             *
+             * @sample {highcharts} highcharts/chart/resetzoombutton-relativeto/
+             *         Relative to the chart
+             * @sample {highstock} highcharts/chart/resetzoombutton-relativeto/
+             *         Relative to the chart
+             *
+             * @type       {Highcharts.ButtonRelativeToValue}
+             * @default    plot
+             * @since      2.2
+             * @apioption  chart.resetZoomButton.relativeTo
+             */
+            /**
+             * A collection of attributes for the button. The object takes SVG
+             * attributes like `fill`, `stroke`, `stroke-width` or `r`, the
+             * border radius. The theme also supports `style`, a collection of
+             * CSS properties for the text. Equivalent attributes for the hover
+             * state are given in `theme.states.hover`.
+             *
+             * @sample {highcharts} highcharts/chart/resetzoombutton-theme/
+             *         Theming the button
+             * @sample {highstock} highcharts/chart/resetzoombutton-theme/
+             *         Theming the button
+             *
+             * @type {Highcharts.SVGAttributes}
+             * @since 2.2
+             */
+            theme: {
+              /** @internal */
+              zIndex: 6,
+            },
             /**
-             * If one of the symbol size affecting parameters are changed,
-             * check all the others only once for each call to an element's
-             * .attr() method
-             *
-             * @private
-             * @function Highcharts.SVGElement#symbolAttr
-             *
-             * @param {Highcharts.SVGAttributes} hash
-             * The attributes to set.
-             */
-            SVGElement.prototype.symbolAttr = function (hash) {
-                var wrapper = this;
-                [
-                    'x',
-                    'y',
-                    'r',
-                    'start',
-                    'end',
-                    'width',
-                    'height',
-                    'innerR',
-                    'anchorX',
-                    'anchorY',
-                    'clockwise'
-                ].forEach(function (key) {
-                    wrapper[key] = pick(hash[key], wrapper[key]);
-                });
-                wrapper.attr({
-                    d: wrapper.renderer.symbols[wrapper.symbolName](wrapper.x, wrapper.y, wrapper.width, wrapper.height, wrapper)
-                });
-            };
+             * The position of the button.
+             *
+             * @sample {highcharts} highcharts/chart/resetzoombutton-position/
+             *         Above the plot area
+             * @sample {highstock} highcharts/chart/resetzoombutton-position/
+             *         Above the plot area
+             * @sample {highmaps} highcharts/chart/resetzoombutton-position/
+             *         Above the plot area
+             *
+             * @type  {Highcharts.AlignObject}
+             * @since 2.2
+             */
+            position: {
+              /**
+               * The horizontal alignment of the button.
+               */
+              align: "right",
+              /**
+               * The horizontal offset of the button.
+               */
+              x: -10,
+              /**
+               * The vertical alignment of the button.
+               *
+               * @type       {Highcharts.VerticalAlignValue}
+               * @default    top
+               * @apioption  chart.resetZoomButton.position.verticalAlign
+               */
+              /**
+               * The vertical offset of the button.
+               */
+              y: 10,
+            },
+          },
+          /**
+           * The pixel width of the plot area border.
+           *
+           * @sample {highcharts} highcharts/chart/plotborderwidth/
+           *         1px border
+           * @sample {highstock} stock/chart/plotborder/
+           *         2px border
+           * @sample {highmaps} maps/chart/plotborder/
+           *         Plot border options
+           *
+           * @type      {number}
+           * @default   0
+           * @apioption chart.plotBorderWidth
+           */
+          /**
+           * Whether to apply a drop shadow to the plot area. Requires that
+           * plotBackgroundColor be set. The shadow can be an object configuration
+           * containing `color`, `offsetX`, `offsetY`, `opacity` and `width`.
+           *
+           * @sample {highcharts} highcharts/chart/plotshadow/
+           *         Plot shadow
+           * @sample {highstock} stock/chart/plotshadow/
+           *         Plot shadow
+           * @sample {highmaps} maps/chart/plotborder/
+           *         Plot border options
+           *
+           * @type      {boolean|Highcharts.CSSObject}
+           * @default   false
+           * @apioption chart.plotShadow
+           */
+          /**
+           * When true, cartesian charts like line, spline, area and column are
+           * transformed into the polar coordinate system. This produces _polar
+           * charts_, also known as _radar charts_.
+           *
+           * @sample {highcharts} highcharts/demo/polar/
+           *         Polar chart
+           * @sample {highcharts} highcharts/demo/polar-wind-rose/
+           *         Wind rose, stacked polar column chart
+           * @sample {highcharts} highcharts/demo/polar-spider/
+           *         Spider web chart
+           * @sample {highcharts} highcharts/parallel-coordinates/polar/
+           *         Star plot, multivariate data in a polar chart
+           *
+           * @type      {boolean}
+           * @default   false
+           * @since     2.3.0
+           * @product   highcharts
+           * @requires  highcharts-more
+           * @apioption chart.polar
+           */
+          /**
+           * Whether to reflow the chart to fit the width of the container div
+           * on resizing the window.
+           *
+           * @sample {highcharts} highcharts/chart/reflow-true/
+           *         True by default
+           * @sample {highcharts} highcharts/chart/reflow-false/
+           *         False
+           * @sample {highstock} stock/chart/reflow-true/
+           *         True by default
+           * @sample {highstock} stock/chart/reflow-false/
+           *         False
+           * @sample {highmaps} maps/chart/reflow-true/
+           *         True by default
+           * @sample {highmaps} maps/chart/reflow-false/
+           *         False
+           *
+           * @type      {boolean}
+           * @default   true
+           * @since     2.1
+           * @apioption chart.reflow
+           */
+          /**
+           * The HTML element where the chart will be rendered. If it is a string,
+           * the element by that id is used. The HTML element can also be passed
+           * by direct reference, or as the first argument of the chart
+           * constructor, in which case the option is not needed.
+           *
+           * @sample {highcharts} highcharts/chart/reflow-true/
+           *         String
+           * @sample {highcharts} highcharts/chart/renderto-object/
+           *         Object reference
+           * @sample {highcharts} highcharts/chart/renderto-jquery/
+           *         Object reference through jQuery
+           * @sample {highstock} stock/chart/renderto-string/
+           *         String
+           * @sample {highstock} stock/chart/renderto-object/
+           *         Object reference
+           * @sample {highstock} stock/chart/renderto-jquery/
+           *         Object reference through jQuery
+           *
+           * @type      {string|Highcharts.HTMLDOMElement}
+           * @apioption chart.renderTo
+           */
+          /**
+           * The background color of the marker square when selecting (zooming
+           * in on) an area of the chart.
+           *
+           * @see In styled mode, the selection marker fill is set with the
+           *      `.highcharts-selection-marker` class.
+           *
+           * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+           * @default   rgba(51,92,173,0.25)
+           * @since     2.1.7
+           * @apioption chart.selectionMarkerFill
+           */
+          /**
+           * Whether to apply a drop shadow to the outer chart area. Requires
+           * that backgroundColor be set. The shadow can be an object
+           * configuration containing `color`, `offsetX`, `offsetY`, `opacity` and
+           * `width`.
+           *
+           * @sample {highcharts} highcharts/chart/shadow/
+           *         Shadow
+           * @sample {highstock} stock/chart/shadow/
+           *         Shadow
+           * @sample {highmaps} maps/chart/border/
+           *         Chart border and shadow
+           *
+           * @type      {boolean|Highcharts.CSSObject}
+           * @default   false
+           * @apioption chart.shadow
+           */
+          /**
+           * Whether to show the axes initially. This only applies to empty charts
+           * where series are added dynamically, as axes are automatically added
+           * to cartesian series.
+           *
+           * @sample {highcharts} highcharts/chart/showaxes-false/
+           *         False by default
+           * @sample {highcharts} highcharts/chart/showaxes-true/
+           *         True
+           *
+           * @type      {boolean}
+           * @since     1.2.5
+           * @product   highcharts gantt
+           * @apioption chart.showAxes
+           */
+          /**
+           * The space between the bottom edge of the chart and the content (plot
+           * area, axis title and labels, title, subtitle or legend in top
+           * position).
+           *
+           * @sample {highcharts} highcharts/chart/spacingbottom/
+           *         Spacing bottom set to 100
+           * @sample {highstock} stock/chart/spacingbottom/
+           *         Spacing bottom set to 100
+           * @sample {highmaps} maps/chart/spacing/
+           *         Spacing 100 all around
+           *
+           * @type      {number}
+           * @default   15
+           * @since     2.1
+           * @apioption chart.spacingBottom
+           */
+          /**
+           * The space between the left edge of the chart and the content (plot
+           * area, axis title and labels, title, subtitle or legend in top
+           * position).
+           *
+           * @sample {highcharts} highcharts/chart/spacingleft/
+           *         Spacing left set to 100
+           * @sample {highstock} stock/chart/spacingleft/
+           *         Spacing left set to 100
+           * @sample {highmaps} maps/chart/spacing/
+           *         Spacing 100 all around
+           *
+           * @type      {number}
+           * @default   10
+           * @since     2.1
+           * @apioption chart.spacingLeft
+           */
+          /**
+           * The space between the right edge of the chart and the content (plot
+           * area, axis title and labels, title, subtitle or legend in top
+           * position).
+           *
+           * @sample {highcharts} highcharts/chart/spacingright-100/
+           *         Spacing set to 100
+           * @sample {highcharts} highcharts/chart/spacingright-legend/
+           *         Legend in right position with default spacing
+           * @sample {highstock} stock/chart/spacingright/
+           *         Spacing set to 100
+           * @sample {highmaps} maps/chart/spacing/
+           *         Spacing 100 all around
+           *
+           * @type      {number}
+           * @default   10
+           * @since     2.1
+           * @apioption chart.spacingRight
+           */
+          /**
+           * The space between the top edge of the chart and the content (plot
+           * area, axis title and labels, title, subtitle or legend in top
+           * position).
+           *
+           * @sample {highcharts} highcharts/chart/spacingtop-100/
+           *         A top spacing of 100
+           * @sample {highcharts} highcharts/chart/spacingtop-10/
+           *         Floating chart title makes the plot area align to the default
+           *         spacingTop of 10.
+           * @sample {highstock} stock/chart/spacingtop/
+           *         A top spacing of 100
+           * @sample {highmaps} maps/chart/spacing/
+           *         Spacing 100 all around
+           *
+           * @type      {number}
+           * @default   10
+           * @since     2.1
+           * @apioption chart.spacingTop
+           */
+          /**
+           * Additional CSS styles to apply inline to the container `div`. Note
+           * that since the default font styles are applied in the renderer, it
+           * is ignorant of the individual chart options and must be set globally.
+           *
+           * @see    In styled mode, general chart styles can be set with the
+           *         `.highcharts-root` class.
+           * @sample {highcharts} highcharts/chart/style-serif-font/
+           *         Using a serif type font
+           * @sample {highcharts} highcharts/css/em/
+           *         Styled mode with relative font sizes
+           * @sample {highstock} stock/chart/style/
+           *         Using a serif type font
+           * @sample {highmaps} maps/chart/style-serif-font/
+           *         Using a serif type font
+           *
+           * @type      {Highcharts.CSSObject}
+           * @default   {"fontFamily": "\"Lucida Grande\", \"Lucida Sans Unicode\", Verdana, Arial, Helvetica, sans-serif","fontSize":"12px"}
+           * @apioption chart.style
+           */
+          /**
+           * The default series type for the chart. Can be any of the chart types
+           * listed under [plotOptions](#plotOptions) and [series](#series) or can
+           * be a series provided by an additional module.
+           *
+           * In TypeScript this option has no effect in sense of typing and
+           * instead the `type` option must always be set in the series.
+           *
+           * @sample {highcharts} highcharts/chart/type-bar/
+           *         Bar
+           * @sample {highstock} stock/chart/type/
+           *         Areaspline
+           * @sample {highmaps} maps/chart/type-mapline/
+           *         Mapline
+           *
+           * @type       {string}
+           * @default    {highcharts} line
+           * @default    {highstock} line
+           * @default    {highmaps} map
+           * @since      2.1.0
+           * @apioption  chart.type
+           */
+          /**
+           * Decides in what dimensions the user can zoom by dragging the mouse.
+           * Can be one of `x`, `y` or `xy`.
+           *
+           * @see [panKey](#chart.panKey)
+           *
+           * @sample {highcharts} highcharts/chart/zoomtype-none/
+           *         None by default
+           * @sample {highcharts} highcharts/chart/zoomtype-x/
+           *         X
+           * @sample {highcharts} highcharts/chart/zoomtype-y/
+           *         Y
+           * @sample {highcharts} highcharts/chart/zoomtype-xy/
+           *         Xy
+           * @sample {highstock} stock/demo/basic-line/
+           *         None by default
+           * @sample {highstock} stock/chart/zoomtype-x/
+           *         X
+           * @sample {highstock} stock/chart/zoomtype-y/
+           *         Y
+           * @sample {highstock} stock/chart/zoomtype-xy/
+           *         Xy
+           *
+           * @type       {string}
+           * @product    highcharts highstock gantt
+           * @validvalue ["x", "y", "xy"]
+           * @apioption  chart.zoomType
+           */
+          /**
+           * An explicit width for the chart. By default (when `null`) the width
+           * is calculated from the offset width of the containing element.
+           *
+           * @sample {highcharts} highcharts/chart/width/
+           *         800px wide
+           * @sample {highstock} stock/chart/width/
+           *         800px wide
+           * @sample {highmaps} maps/chart/size/
+           *         Chart with explicit size
+           *
+           * @type {null|number|string}
+           */
+          width: null,
+          /**
+           * An explicit height for the chart. If a _number_, the height is
+           * given in pixels. If given a _percentage string_ (for example
+           * `'56%'`), the height is given as the percentage of the actual chart
+           * width. This allows for preserving the aspect ratio across responsive
+           * sizes.
+           *
+           * By default (when `null`) the height is calculated from the offset
+           * height of the containing element, or 400 pixels if the containing
+           * element's height is 0.
+           *
+           * @sample {highcharts} highcharts/chart/height/
+           *         500px height
+           * @sample {highstock} stock/chart/height/
+           *         300px height
+           * @sample {highmaps} maps/chart/size/
+           *         Chart with explicit size
+           * @sample highcharts/chart/height-percent/
+           *         Highcharts with percentage height
+           *
+           * @type {null|number|string}
+           */
+          height: null,
+          /**
+           * The color of the outer chart border.
+           *
+           * @see In styled mode, the stroke is set with the
+           *      `.highcharts-background` class.
+           *
+           * @sample {highcharts} highcharts/chart/bordercolor/
+           *         Brown border
+           * @sample {highstock} stock/chart/border/
+           *         Brown border
+           * @sample {highmaps} maps/chart/border/
+           *         Border options
+           *
+           * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+           */
+          borderColor: "#335cad",
+          /**
+           * The pixel width of the outer chart border.
+           *
+           * @see In styled mode, the stroke is set with the
+           *      `.highcharts-background` class.
+           *
+           * @sample {highcharts} highcharts/chart/borderwidth/
+           *         5px border
+           * @sample {highstock} stock/chart/border/
+           *         2px border
+           * @sample {highmaps} maps/chart/border/
+           *         Border options
+           *
+           * @type      {number}
+           * @default   0
+           * @apioption chart.borderWidth
+           */
+          /**
+           * The background color or gradient for the outer chart area.
+           *
+           * @see In styled mode, the background is set with the
+           *      `.highcharts-background` class.
+           *
+           * @sample {highcharts} highcharts/chart/backgroundcolor-color/
+           *         Color
+           * @sample {highcharts} highcharts/chart/backgroundcolor-gradient/
+           *         Gradient
+           * @sample {highstock} stock/chart/backgroundcolor-color/
+           *         Color
+           * @sample {highstock} stock/chart/backgroundcolor-gradient/
+           *         Gradient
+           * @sample {highmaps} maps/chart/backgroundcolor-color/
+           *         Color
+           * @sample {highmaps} maps/chart/backgroundcolor-gradient/
+           *         Gradient
+           *
+           * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+           */
+          backgroundColor: "#ffffff",
+          /**
+           * The background color or gradient for the plot area.
+           *
+           * @see In styled mode, the plot background is set with the
+           *      `.highcharts-plot-background` class.
+           *
+           * @sample {highcharts} highcharts/chart/plotbackgroundcolor-color/
+           *         Color
+           * @sample {highcharts} highcharts/chart/plotbackgroundcolor-gradient/
+           *         Gradient
+           * @sample {highstock} stock/chart/plotbackgroundcolor-color/
+           *         Color
+           * @sample {highstock} stock/chart/plotbackgroundcolor-gradient/
+           *         Gradient
+           * @sample {highmaps} maps/chart/plotbackgroundcolor-color/
+           *         Color
+           * @sample {highmaps} maps/chart/plotbackgroundcolor-gradient/
+           *         Gradient
+           *
+           * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+           * @apioption chart.plotBackgroundColor
+           */
+          /**
+           * The URL for an image to use as the plot background. To set an image
+           * as the background for the entire chart, set a CSS background image
+           * to the container element. Note that for the image to be applied to
+           * exported charts, its URL needs to be accessible by the export server.
+           *
+           * @see In styled mode, a plot background image can be set with the
+           *      `.highcharts-plot-background` class and a [custom pattern](
+           *      https://www.highcharts.com/docs/chart-design-and-style/
+           *      gradients-shadows-and-patterns).
+           *
+           * @sample {highcharts} highcharts/chart/plotbackgroundimage/
+           *         Skies
+           * @sample {highstock} stock/chart/plotbackgroundimage/
+           *         Skies
+           *
+           * @type      {string}
+           * @apioption chart.plotBackgroundImage
+           */
+          /**
+           * The color of the inner chart or plot area border.
+           *
+           * @see In styled mode, a plot border stroke can be set with the
+           *      `.highcharts-plot-border` class.
+           *
+           * @sample {highcharts} highcharts/chart/plotbordercolor/
+           *         Blue border
+           * @sample {highstock} stock/chart/plotborder/
+           *         Blue border
+           * @sample {highmaps} maps/chart/plotborder/
+           *         Plot border options
+           *
+           * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+           */
+          plotBorderColor: "#cccccc",
+        },
+        /**
+         * The chart's main title.
+         *
+         * @sample {highmaps} maps/title/title/
+         *         Title options demonstrated
+         */
+        title: {
+          /**
+           * When the title is floating, the plot area will not move to make space
+           * for it.
+           *
+           * @sample {highcharts} highcharts/chart/zoomtype-none/
+           *         False by default
+           * @sample {highcharts} highcharts/title/floating/
+           *         True - title on top of the plot area
+           * @sample {highstock} stock/chart/title-floating/
+           *         True - title on top of the plot area
+           *
+           * @type      {boolean}
+           * @default   false
+           * @since     2.1
+           * @apioption title.floating
+           */
+          /**
+           * CSS styles for the title. Use this for font styling, but use `align`,
+           * `x` and `y` for text alignment.
+           *
+           * In styled mode, the title style is given in the `.highcharts-title`
+           * class.
+           *
+           * @sample {highcharts} highcharts/title/style/
+           *         Custom color and weight
+           * @sample {highstock} stock/chart/title-style/
+           *         Custom color and weight
+           * @sample highcharts/css/titles/
+           *         Styled mode
+           *
+           * @type      {Highcharts.CSSObject}
+           * @default   {highcharts|highmaps} { "color": "#333333", "fontSize": "18px" }
+           * @default   {highstock} { "color": "#333333", "fontSize": "16px" }
+           * @apioption title.style
+           */
+          /**
+           * Whether to
+           * [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html)
+           * to render the text.
+           *
+           * @type      {boolean}
+           * @default   false
+           * @apioption title.useHTML
+           */
+          /**
+           * The vertical alignment of the title. Can be one of `"top"`,
+           * `"middle"` and `"bottom"`. When a value is given, the title behaves
+           * as if [floating](#title.floating) were `true`.
+           *
+           * @sample {highcharts} highcharts/title/verticalalign/
+           *         Chart title in bottom right corner
+           * @sample {highstock} stock/chart/title-verticalalign/
+           *         Chart title in bottom right corner
+           *
+           * @type      {Highcharts.VerticalAlignValue}
+           * @since     2.1
+           * @apioption title.verticalAlign
+           */
+          /**
+           * The x position of the title relative to the alignment within
+           * `chart.spacingLeft` and `chart.spacingRight`.
+           *
+           * @sample {highcharts} highcharts/title/align/
+           *         Aligned to the plot area (x = 70px = margin left - spacing
+           *         left)
+           * @sample {highstock} stock/chart/title-align/
+           *         Aligned to the plot area (x = 50px = margin left - spacing
+           *         left)
+           *
+           * @type      {number}
+           * @default   0
+           * @since     2.0
+           * @apioption title.x
+           */
+          /**
+           * The y position of the title relative to the alignment within
+           * [chart.spacingTop](#chart.spacingTop) and [chart.spacingBottom](
+           * #chart.spacingBottom). By default it depends on the font size.
+           *
+           * @sample {highcharts} highcharts/title/y/
+           *         Title inside the plot area
+           * @sample {highstock} stock/chart/title-verticalalign/
+           *         Chart title in bottom right corner
+           *
+           * @type      {number}
+           * @since     2.0
+           * @apioption title.y
+           */
+          /**
+           * The title of the chart. To disable the title, set the `text` to
+           * `undefined`.
+           *
+           * @sample {highcharts} highcharts/title/text/
+           *         Custom title
+           * @sample {highstock} stock/chart/title-text/
+           *         Custom title
+           *
+           * @default {highcharts|highmaps} Chart title
+           * @default {highstock} undefined
+           */
+          text: "Chart title",
+          /**
+           * The horizontal alignment of the title. Can be one of "left", "center"
+           * and "right".
+           *
+           * @sample {highcharts} highcharts/title/align/
+           *         Aligned to the plot area (x = 70px = margin left - spacing
+           *         left)
+           * @sample {highstock} stock/chart/title-align/
+           *         Aligned to the plot area (x = 50px = margin left - spacing
+           *         left)
+           *
+           * @type  {Highcharts.AlignValue}
+           * @since 2.0
+           */
+          align: "center",
+          /**
+           * The margin between the title and the plot area, or if a subtitle
+           * is present, the margin between the subtitle and the plot area.
+           *
+           * @sample {highcharts} highcharts/title/margin-50/
+           *         A chart title margin of 50
+           * @sample {highcharts} highcharts/title/margin-subtitle/
+           *         The same margin applied with a subtitle
+           * @sample {highstock} stock/chart/title-margin/
+           *         A chart title margin of 50
+           *
+           * @since 2.1
+           */
+          margin: 15,
+          /**
+           * Adjustment made to the title width, normally to reserve space for
+           * the exporting burger menu.
+           *
+           * @sample highcharts/title/widthadjust/
+           *         Wider menu, greater padding
+           *
+           * @since 4.2.5
+           */
+          widthAdjust: -44,
+        },
+        /**
+         * The chart's subtitle. This can be used both to display a subtitle below
+         * the main title, and to display random text anywhere in the chart. The
+         * subtitle can be updated after chart initialization through the
+         * `Chart.setTitle` method.
+         *
+         * @sample {highmaps} maps/title/subtitle/
+         *         Subtitle options demonstrated
+         */
+        subtitle: {
+          /**
+           * When the subtitle is floating, the plot area will not move to make
+           * space for it.
+           *
+           * @sample {highcharts} highcharts/subtitle/floating/
+           *         Floating title and subtitle
+           * @sample {highstock} stock/chart/subtitle-footnote
+           *         Footnote floating at bottom right of plot area
+           *
+           * @type      {boolean}
+           * @default   false
+           * @since     2.1
+           * @apioption subtitle.floating
+           */
+          /**
+           * CSS styles for the title.
+           *
+           * In styled mode, the subtitle style is given in the
+           * `.highcharts-subtitle` class.
+           *
+           * @sample {highcharts} highcharts/subtitle/style/
+           *         Custom color and weight
+           * @sample {highcharts} highcharts/css/titles/
+           *         Styled mode
+           * @sample {highstock} stock/chart/subtitle-style
+           *         Custom color and weight
+           * @sample {highstock} highcharts/css/titles/
+           *         Styled mode
+           * @sample {highmaps} highcharts/css/titles/
+           *         Styled mode
+           *
+           * @type      {Highcharts.CSSObject}
+           * @default   {"color": "#666666"}
+           * @apioption subtitle.style
+           */
+          /**
+           * Whether to
+           * [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html)
+           * to render the text.
+           *
+           * @type      {boolean}
+           * @default   false
+           * @apioption subtitle.useHTML
+           */
+          /**
+           * The vertical alignment of the title. Can be one of `"top"`,
+           * `"middle"` and `"bottom"`. When middle, the subtitle behaves as
+           * floating.
+           *
+           * @sample {highcharts} highcharts/subtitle/verticalalign/
+           *         Footnote at the bottom right of plot area
+           * @sample {highstock} stock/chart/subtitle-footnote
+           *         Footnote at the bottom right of plot area
+           *
+           * @type      {Highcharts.VerticalAlignValue}
+           * @since     2.1
+           * @apioption subtitle.verticalAlign
+           */
+          /**
+           * The x position of the subtitle relative to the alignment within
+           * `chart.spacingLeft` and `chart.spacingRight`.
+           *
+           * @sample {highcharts} highcharts/subtitle/align/
+           *         Footnote at right of plot area
+           * @sample {highstock} stock/chart/subtitle-footnote
+           *         Footnote at the bottom right of plot area
+           *
+           * @type      {number}
+           * @default   0
+           * @since     2.0
+           * @apioption subtitle.x
+           */
+          /**
+           * The y position of the subtitle relative to the alignment within
+           * `chart.spacingTop` and `chart.spacingBottom`. By default the subtitle
+           * is laid out below the title unless the title is floating.
+           *
+           * @sample {highcharts} highcharts/subtitle/verticalalign/
+           *         Footnote at the bottom right of plot area
+           * @sample {highstock} stock/chart/subtitle-footnote
+           *         Footnote at the bottom right of plot area
+           *
+           * @type      {number}
+           * @since     2.0
+           * @apioption subtitle.y
+           */
+          /**
+           * The subtitle of the chart.
+           *
+           * @sample {highcharts|highstock} highcharts/subtitle/text/
+           *         Custom subtitle
+           * @sample {highcharts|highstock} highcharts/subtitle/text-formatted/
+           *         Formatted and linked text.
+           */
+          text: "",
+          /**
+           * The horizontal alignment of the subtitle. Can be one of "left",
+           *  "center" and "right".
+           *
+           * @sample {highcharts} highcharts/subtitle/align/
+           *         Footnote at right of plot area
+           * @sample {highstock} stock/chart/subtitle-footnote
+           *         Footnote at bottom right of plot area
+           *
+           * @type  {Highcharts.AlignValue}
+           * @since 2.0
+           */
+          align: "center",
+          /**
+           * Adjustment made to the subtitle width, normally to reserve space
+           * for the exporting burger menu.
+           *
+           * @see [title.widthAdjust](#title.widthAdjust)
+           *
+           * @sample highcharts/title/widthadjust/
+           *         Wider menu, greater padding
+           *
+           * @since 4.2.5
+           */
+          widthAdjust: -44,
+        },
+        /**
+         * The chart's caption, which will render below the chart and will be part
+         * of exported charts. The caption can be updated after chart initialization
+         * through the `Chart.update` or `Chart.caption.update` methods.
+         *
+         * @sample highcharts/caption/text/
+         *         A chart with a caption
+         * @since  7.2.0
+         */
+        caption: {
+          /**
+           * When the caption is floating, the plot area will not move to make
+           * space for it.
+           *
+           * @type      {boolean}
+           * @default   false
+           * @apioption caption.floating
+           */
+          /**
+           * The margin between the caption and the plot area.
+           */
+          margin: 15,
+          /**
+           * CSS styles for the caption.
+           *
+           * In styled mode, the caption style is given in the
+           * `.highcharts-caption` class.
+           *
+           * @sample {highcharts} highcharts/css/titles/
+           *         Styled mode
+           *
+           * @type      {Highcharts.CSSObject}
+           * @default   {"color": "#666666"}
+           * @apioption caption.style
+           */
+          /**
+           * Whether to
+           * [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html)
+           * to render the text.
+           *
+           * @type      {boolean}
+           * @default   false
+           * @apioption caption.useHTML
+           */
+          /**
+           * The x position of the caption relative to the alignment within
+           * `chart.spacingLeft` and `chart.spacingRight`.
+           *
+           * @type      {number}
+           * @default   0
+           * @apioption caption.x
+           */
+          /**
+           * The y position of the caption relative to the alignment within
+           * `chart.spacingTop` and `chart.spacingBottom`.
+           *
+           * @type      {number}
+           * @apioption caption.y
+           */
+          /**
+           * The caption text of the chart.
+           *
+           * @sample {highcharts} highcharts/caption/text/
+           *         Custom caption
+           */
+          text: "",
+          /**
+           * The horizontal alignment of the caption. Can be one of "left",
+           *  "center" and "right".
+           *
+           * @type  {Highcharts.AlignValue}
+           */
+          align: "left",
+          /**
+           * The vertical alignment of the caption. Can be one of `"top"`,
+           * `"middle"` and `"bottom"`. When middle, the caption behaves as
+           * floating.
+           *
+           * @type      {Highcharts.VerticalAlignValue}
+           */
+          verticalAlign: "bottom",
+        },
+        /**
+         * The plotOptions is a wrapper object for config objects for each series
+         * type. The config objects for each series can also be overridden for
+         * each series item as given in the series array.
+         *
+         * Configuration options for the series are given in three levels. Options
+         * for all series in a chart are given in the [plotOptions.series](
+         * #plotOptions.series) object. Then options for all series of a specific
+         * type are given in the plotOptions of that type, for example
+         * `plotOptions.line`. Next, options for one single series are given in
+         * [the series array](#series).
+         */
+        plotOptions: {},
+        /**
+         * HTML labels that can be positioned anywhere in the chart area.
+         *
+         * This option is deprecated since v7.1.2. Instead, use
+         * [annotations](#annotations) that support labels.
+         *
+         * @deprecated
+         * @product   highcharts highstock
+         */
+        labels: {
+          /**
+           * An HTML label that can be positioned anywhere in the chart area.
+           *
+           * @deprecated
+           * @type      {Array<*>}
+           * @apioption labels.items
+           */
+          /**
+           * Inner HTML or text for the label.
+           *
+           * @deprecated
+           * @type      {string}
+           * @apioption labels.items.html
+           */
+          /**
+           * CSS styles for each label. To position the label, use left and top
+           * like this:
+           * ```js
+           * style: {
+           *     left: '100px',
+           *     top: '100px'
+           * }
+           * ```
+           *
+           * @deprecated
+           * @type      {Highcharts.CSSObject}
+           * @apioption labels.items.style
+           */
+          /**
+           * Shared CSS styles for all labels.
+           *
+           * @deprecated
+           * @type    {Highcharts.CSSObject}
+           * @default {"color": "#333333", "position": "absolute"}
+           */
+          style: {
             /**
-             * @private
-             * @function Highcharts.SVGElement#textSetter
-             * @param {string} value
+             * @ignore-option
              */
-            SVGElement.prototype.textSetter = function (value) {
-                if (value !== this.textStr) {
-                    // Delete size caches when the text changes
-                    // delete this.bBox; // old code in series-label
-                    delete this.textPxLength;
-                    this.textStr = value;
-                    if (this.added) {
-                        this.renderer.buildText(this);
-                    }
-                }
-            };
+            position: "absolute",
             /**
-             * @private
-             * @function Highcharts.SVGElement#titleSetter
-             * @param {string} value
+             * @ignore-option
              */
-            SVGElement.prototype.titleSetter = function (value) {
-                var titleNode = this.element.getElementsByTagName('title')[0];
-                if (!titleNode) {
-                    titleNode = doc.createElementNS(this.SVG_NS, 'title');
-                    this.element.appendChild(titleNode);
-                }
-                // Remove text content if it exists
-                if (titleNode.firstChild) {
-                    titleNode.removeChild(titleNode.firstChild);
-                }
-                titleNode.appendChild(doc.createTextNode(
-                // #3276, #3895
-                String(pick(value, ''))
-                    .replace(/<[^>]*>/g, '')
-                    .replace(/&lt;/g, '<')
-                    .replace(/&gt;/g, '>')));
-            };
-            /**
-             * Bring the element to the front. Alternatively, a new zIndex can be set.
-             *
-             * @sample highcharts/members/element-tofront/
-             *         Click an element to bring it to front
-             *
-             * @function Highcharts.SVGElement#toFront
-             *
-             * @return {Highcharts.SVGElement}
-             * Returns the SVGElement for chaining.
+            color: "#333333",
+          },
+        },
+        /**
+         * The legend is a box containing a symbol and name for each series
+         * item or point item in the chart. Each series (or points in case
+         * of pie charts) is represented by a symbol and its name in the legend.
+         *
+         * It is possible to override the symbol creator function and create
+         * [custom legend symbols](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/studies/legend-custom-symbol/).
+         *
+         * @productdesc {highmaps}
+         * A Highmaps legend by default contains one legend item per series, but if
+         * a `colorAxis` is defined, the axis will be displayed in the legend.
+         * Either as a gradient, or as multiple legend items for `dataClasses`.
+         */
+        legend: {
+          /**
+           * The background color of the legend.
+           *
+           * @see In styled mode, the legend background fill can be applied with
+           *      the `.highcharts-legend-box` class.
+           *
+           * @sample {highcharts} highcharts/legend/backgroundcolor/
+           *         Yellowish background
+           * @sample {highstock} stock/legend/align/
+           *         Various legend options
+           * @sample {highmaps} maps/legend/border-background/
+           *         Border and background options
+           *
+           * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+           * @apioption legend.backgroundColor
+           */
+          /**
+           * The width of the drawn border around the legend.
+           *
+           * @see In styled mode, the legend border stroke width can be applied
+           *      with the `.highcharts-legend-box` class.
+           *
+           * @sample {highcharts} highcharts/legend/borderwidth/
+           *         2px border width
+           * @sample {highstock} stock/legend/align/
+           *         Various legend options
+           * @sample {highmaps} maps/legend/border-background/
+           *         Border and background options
+           *
+           * @type      {number}
+           * @default   0
+           * @apioption legend.borderWidth
+           */
+          /**
+           * Enable or disable the legend. There is also a series-specific option,
+           * [showInLegend](#plotOptions.series.showInLegend), that can hide the
+           * series from the legend. In some series types this is `false` by
+           * default, so it must set to `true` in order to show the legend for the
+           * series.
+           *
+           * @sample {highcharts} highcharts/legend/enabled-false/ Legend disabled
+           * @sample {highstock} stock/legend/align/ Various legend options
+           * @sample {highmaps} maps/legend/enabled-false/ Legend disabled
+           *
+           * @default {highstock} false
+           * @default {highmaps} true
+           * @default {gantt} false
+           */
+          enabled: true,
+          /**
+           * The horizontal alignment of the legend box within the chart area.
+           * Valid values are `left`, `center` and `right`.
+           *
+           * In the case that the legend is aligned in a corner position, the
+           * `layout` option will determine whether to place it above/below
+           * or on the side of the plot area.
+           *
+           * @sample {highcharts} highcharts/legend/align/
+           *         Legend at the right of the chart
+           * @sample {highstock} stock/legend/align/
+           *         Various legend options
+           * @sample {highmaps} maps/legend/alignment/
+           *         Legend alignment
+           *
+           * @type  {Highcharts.AlignValue}
+           * @since 2.0
+           */
+          align: "center",
+          /**
+           * If the [layout](legend.layout) is `horizontal` and the legend items
+           * span over two lines or more, whether to align the items into vertical
+           * columns. Setting this to `false` makes room for more items, but will
+           * look more messy.
+           *
+           * @since 6.1.0
+           */
+          alignColumns: true,
+          /**
+           * When the legend is floating, the plot area ignores it and is allowed
+           * to be placed below it.
+           *
+           * @sample {highcharts} highcharts/legend/floating-false/
+           *         False by default
+           * @sample {highcharts} highcharts/legend/floating-true/
+           *         True
+           * @sample {highmaps} maps/legend/alignment/
+           *         Floating legend
+           *
+           * @type      {boolean}
+           * @default   false
+           * @since     2.1
+           * @apioption legend.floating
+           */
+          /**
+           * The layout of the legend items. Can be one of `horizontal` or
+           * `vertical` or `proximate`. When `proximate`, the legend items will be
+           * placed as close as possible to the graphs they're representing,
+           * except in inverted charts or when the legend position doesn't allow
+           * it.
+           *
+           * @sample {highcharts} highcharts/legend/layout-horizontal/
+           *         Horizontal by default
+           * @sample {highcharts} highcharts/legend/layout-vertical/
+           *         Vertical
+           * @sample highcharts/legend/layout-proximate
+           *         Labels proximate to the data
+           * @sample {highstock} stock/legend/layout-horizontal/
+           *         Horizontal by default
+           * @sample {highmaps} maps/legend/padding-itemmargin/
+           *         Vertical with data classes
+           * @sample {highmaps} maps/legend/layout-vertical/
+           *         Vertical with color axis gradient
+           *
+           * @validvalue ["horizontal", "vertical", "proximate"]
+           */
+          layout: "horizontal",
+          /**
+           * In a legend with horizontal layout, the itemDistance defines the
+           * pixel distance between each item.
+           *
+           * @sample {highcharts} highcharts/legend/layout-horizontal/
+           *         50px item distance
+           * @sample {highstock} highcharts/legend/layout-horizontal/
+           *         50px item distance
+           *
+           * @type      {number}
+           * @default   {highcharts} 20
+           * @default   {highstock} 20
+           * @default   {highmaps} 8
+           * @since     3.0.3
+           * @apioption legend.itemDistance
+           */
+          /**
+           * The pixel bottom margin for each legend item.
+           *
+           * @sample {highcharts|highstock} highcharts/legend/padding-itemmargin/
+           *         Padding and item margins demonstrated
+           * @sample {highmaps} maps/legend/padding-itemmargin/
+           *         Padding and item margins demonstrated
+           *
+           * @type      {number}
+           * @default   0
+           * @since     2.2.0
+           * @apioption legend.itemMarginBottom
+           */
+          /**
+           * The pixel top margin for each legend item.
+           *
+           * @sample {highcharts|highstock} highcharts/legend/padding-itemmargin/
+           *         Padding and item margins demonstrated
+           * @sample {highmaps} maps/legend/padding-itemmargin/
+           *         Padding and item margins demonstrated
+           *
+           * @type      {number}
+           * @default   0
+           * @since     2.2.0
+           * @apioption legend.itemMarginTop
+           */
+          /**
+           * The width for each legend item. By default the items are laid out
+           * successively. In a [horizontal layout](legend.layout), if the items
+           * are laid out across two rows or more, they will be vertically aligned
+           * depending on the [legend.alignColumns](legend.alignColumns) option.
+           *
+           * @sample {highcharts} highcharts/legend/itemwidth-default/
+           *         Undefined by default
+           * @sample {highcharts} highcharts/legend/itemwidth-80/
+           *         80 for aligned legend items
+           *
+           * @type      {number}
+           * @since     2.0
+           * @apioption legend.itemWidth
+           */
+          /**
+           * A [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting)
+           * for each legend label. Available variables relates to properties on
+           * the series, or the point in case of pies.
+           *
+           * @type      {string}
+           * @default   {name}
+           * @since     1.3
+           * @apioption legend.labelFormat
+           */
+          /* eslint-disable valid-jsdoc */
+          /**
+           * Callback function to format each of the series' labels. The `this`
+           * keyword refers to the series object, or the point object in case of
+           * pie charts. By default the series or point name is printed.
+           *
+           * @productdesc {highmaps}
+           * In Highmaps the context can also be a data class in case of a
+           * `colorAxis`.
+           *
+           * @sample {highcharts} highcharts/legend/labelformatter/
+           *         Add text
+           * @sample {highmaps} maps/legend/labelformatter/
+           *         Data classes with label formatter
+           *
+           * @type {Highcharts.FormatterCallbackFunction<Point|Series>}
+           */
+          labelFormatter: function () {
+            /** eslint-enable valid-jsdoc */
+            return this.name;
+          },
+          /**
+           * Line height for the legend items. Deprecated as of 2.1\. Instead,
+           * the line height for each item can be set using
+           * `itemStyle.lineHeight`, and the padding between items using
+           * `itemMarginTop` and `itemMarginBottom`.
+           *
+           * @sample {highcharts} highcharts/legend/lineheight/
+           *         Setting padding
+           *
+           * @deprecated
+           *
+           * @type      {number}
+           * @default   16
+           * @since     2.0
+           * @product   highcharts gantt
+           * @apioption legend.lineHeight
+           */
+          /**
+           * If the plot area sized is calculated automatically and the legend is
+           * not floating, the legend margin is the space between the legend and
+           * the axis labels or plot area.
+           *
+           * @sample {highcharts} highcharts/legend/margin-default/
+           *         12 pixels by default
+           * @sample {highcharts} highcharts/legend/margin-30/
+           *         30 pixels
+           *
+           * @type      {number}
+           * @default   12
+           * @since     2.1
+           * @apioption legend.margin
+           */
+          /**
+           * Maximum pixel height for the legend. When the maximum height is
+           * extended, navigation will show.
+           *
+           * @type      {number}
+           * @since     2.3.0
+           * @apioption legend.maxHeight
+           */
+          /**
+           * The color of the drawn border around the legend.
+           *
+           * @see In styled mode, the legend border stroke can be applied with the
+           *      `.highcharts-legend-box` class.
+           *
+           * @sample {highcharts} highcharts/legend/bordercolor/
+           *         Brown border
+           * @sample {highstock} stock/legend/align/
+           *         Various legend options
+           * @sample {highmaps} maps/legend/border-background/
+           *         Border and background options
+           *
+           * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+           */
+          borderColor: "#999999",
+          /**
+           * The border corner radius of the legend.
+           *
+           * @sample {highcharts} highcharts/legend/borderradius-default/
+           *         Square by default
+           * @sample {highcharts} highcharts/legend/borderradius-round/
+           *         5px rounded
+           * @sample {highmaps} maps/legend/border-background/
+           *         Border and background options
+           */
+          borderRadius: 0,
+          /**
+           * Options for the paging or navigation appearing when the legend is
+           * overflown. Navigation works well on screen, but not in static
+           * exported images. One way of working around that is to
+           * [increase the chart height in
+           * export](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/legend/navigation-enabled-false/).
+           */
+          navigation: {
+            /**
+             * How to animate the pages when navigating up or down. A value of
+             * `true` applies the default navigation given in the
+             * `chart.animation` option. Additional options can be given as an
+             * object containing values for easing and duration.
+             *
+             * @sample {highcharts} highcharts/legend/navigation/
+             *         Legend page navigation demonstrated
+             * @sample {highstock} highcharts/legend/navigation/
+             *         Legend page navigation demonstrated
+             *
+             * @type      {boolean|Partial<Highcharts.AnimationOptionsObject>}
+             * @default   true
+             * @since     2.2.4
+             * @apioption legend.navigation.animation
              */
-            SVGElement.prototype.toFront = function () {
-                var element = this.element;
-                element.parentNode.appendChild(element);
-                return this;
-            };
             /**
-             * Move an object and its children by x and y values.
-             *
-             * @function Highcharts.SVGElement#translate
+             * The pixel size of the up and down arrows in the legend paging
+             * navigation.
              *
-             * @param {number} x
-             *        The x value.
+             * @sample {highcharts} highcharts/legend/navigation/
+             *         Legend page navigation demonstrated
+             * @sample {highstock} highcharts/legend/navigation/
+             *         Legend page navigation demonstrated
              *
-             * @param {number} y
-             *        The y value.
-             *
-             * @return {Highcharts.SVGElement}
+             * @type      {number}
+             * @default   12
+             * @since     2.2.4
+             * @apioption legend.navigation.arrowSize
              */
-            SVGElement.prototype.translate = function (x, y) {
-                return this.attr({
-                    translateX: x,
-                    translateY: y
-                });
-            };
             /**
-             * Update the shadow elements with new attributes.
-             *
-             * @private
-             * @function Highcharts.SVGElement#updateShadows
-             *
-             * @param {string} key
-             * The attribute name.
-             *
-             * @param {number} value
-             * The value of the attribute.
+             * Whether to enable the legend navigation. In most cases, disabling
+             * the navigation results in an unwanted overflow.
              *
-             * @param {Function} setter
-             * The setter function, inherited from the parent wrapper.
-             */
-            SVGElement.prototype.updateShadows = function (key, value, setter) {
-                var shadows = this.shadows;
-                if (shadows) {
-                    var i = shadows.length;
-                    while (i--) {
-                        setter.call(shadows[i], key === 'height' ?
-                            Math.max(value - (shadows[i].cutHeight || 0), 0) :
-                            key === 'd' ? this.d : value, key, shadows[i]);
-                    }
-                }
-            };
-            /**
-             * Update the transform attribute based on internal properties. Deals with
-             * the custom `translateX`, `translateY`, `rotation`, `scaleX` and `scaleY`
-             * attributes and updates the SVG `transform` attribute.
+             * See also the [adapt chart to legend](
+             * https://www.highcharts.com/products/plugin-registry/single/8/Adapt-Chart-To-Legend)
+             * plugin for a solution to extend the chart height to make room for
+             * the legend, optionally in exported charts only.
              *
-             * @private
-             * @function Highcharts.SVGElement#updateTransform
+             * @type      {boolean}
+             * @default   true
+             * @since     4.2.4
+             * @apioption legend.navigation.enabled
              */
-            SVGElement.prototype.updateTransform = function () {
-                var wrapper = this,
-                    translateX = wrapper.translateX || 0,
-                    translateY = wrapper.translateY || 0,
-                    scaleX = wrapper.scaleX,
-                    scaleY = wrapper.scaleY,
-                    inverted = wrapper.inverted,
-                    rotation = wrapper.rotation,
-                    matrix = wrapper.matrix,
-                    element = wrapper.element,
-                    transform;
-                // Flipping affects translate as adjustment for flipping around the
-                // group's axis
-                if (inverted) {
-                    translateX += wrapper.width;
-                    translateY += wrapper.height;
-                }
-                // Apply translate. Nearly all transformed elements have translation,
-                // so instead of checking for translate = 0, do it always (#1767,
-                // #1846).
-                transform = ['translate(' + translateX + ',' + translateY + ')'];
-                // apply matrix
-                if (defined(matrix)) {
-                    transform.push('matrix(' + matrix.join(',') + ')');
-                }
-                // apply rotation
-                if (inverted) {
-                    transform.push('rotate(90) scale(-1,1)');
-                }
-                else if (rotation) { // text rotation
-                    transform.push('rotate(' + rotation + ' ' +
-                        pick(this.rotationOriginX, element.getAttribute('x'), 0) +
-                        ' ' +
-                        pick(this.rotationOriginY, element.getAttribute('y') || 0) + ')');
-                }
-                // apply scale
-                if (defined(scaleX) || defined(scaleY)) {
-                    transform.push('scale(' + pick(scaleX, 1) + ' ' + pick(scaleY, 1) + ')');
-                }
-                if (transform.length) {
-                    element.setAttribute('transform', transform.join(' '));
-                }
-            };
             /**
-             * @private
-             * @function Highcharts.SVGElement#visibilitySetter
+             * Text styles for the legend page navigation.
              *
-             * @param {string} value
+             * @see In styled mode, the navigation items are styled with the
+             *      `.highcharts-legend-navigation` class.
              *
-             * @param {string} key
+             * @sample {highcharts} highcharts/legend/navigation/
+             *         Legend page navigation demonstrated
+             * @sample {highstock} highcharts/legend/navigation/
+             *         Legend page navigation demonstrated
              *
-             * @param {Highcharts.SVGDOMElement} element
+             * @type      {Highcharts.CSSObject}
+             * @since     2.2.4
+             * @apioption legend.navigation.style
+             */
+            /**
+             * The color for the active up or down arrow in the legend page
+             * navigation.
+             *
+             * @see In styled mode, the active arrow be styled with the
+             *      `.highcharts-legend-nav-active` class.
+             *
+             * @sample  {highcharts} highcharts/legend/navigation/
+             *          Legend page navigation demonstrated
+             * @sample  {highstock} highcharts/legend/navigation/
+             *          Legend page navigation demonstrated
+             *
+             * @type  {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+             * @since 2.2.4
+             */
+            activeColor: "#003399",
+            /**
+             * The color of the inactive up or down arrow in the legend page
+             * navigation. .
+             *
+             * @see In styled mode, the inactive arrow be styled with the
+             *      `.highcharts-legend-nav-inactive` class.
+             *
+             * @sample {highcharts} highcharts/legend/navigation/
+             *         Legend page navigation demonstrated
+             * @sample {highstock} highcharts/legend/navigation/
+             *         Legend page navigation demonstrated
+             *
+             * @type  {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+             * @since 2.2.4
+             */
+            inactiveColor: "#cccccc",
+          },
+          /**
+           * The inner padding of the legend box.
+           *
+           * @sample {highcharts|highstock} highcharts/legend/padding-itemmargin/
+           *         Padding and item margins demonstrated
+           * @sample {highmaps} maps/legend/padding-itemmargin/
+           *         Padding and item margins demonstrated
+           *
+           * @type      {number}
+           * @default   8
+           * @since     2.2.0
+           * @apioption legend.padding
+           */
+          /**
+           * Whether to reverse the order of the legend items compared to the
+           * order of the series or points as defined in the configuration object.
+           *
+           * @see [yAxis.reversedStacks](#yAxis.reversedStacks),
+           *      [series.legendIndex](#series.legendIndex)
+           *
+           * @sample {highcharts} highcharts/legend/reversed/
+           *         Stacked bar with reversed legend
+           *
+           * @type      {boolean}
+           * @default   false
+           * @since     1.2.5
+           * @apioption legend.reversed
+           */
+          /**
+           * Whether to show the symbol on the right side of the text rather than
+           * the left side. This is common in Arabic and Hebraic.
+           *
+           * @sample {highcharts} highcharts/legend/rtl/
+           *         Symbol to the right
+           *
+           * @type      {boolean}
+           * @default   false
+           * @since     2.2
+           * @apioption legend.rtl
+           */
+          /**
+           * CSS styles for the legend area. In the 1.x versions the position
+           * of the legend area was determined by CSS. In 2.x, the position is
+           * determined by properties like `align`, `verticalAlign`, `x` and `y`,
+           * but the styles are still parsed for backwards compatibility.
+           *
+           * @deprecated
+           *
+           * @type      {Highcharts.CSSObject}
+           * @product   highcharts highstock
+           * @apioption legend.style
+           */
+          /**
+           * CSS styles for each legend item. Only a subset of CSS is supported,
+           * notably those options related to text. The default `textOverflow`
+           * property makes long texts truncate. Set it to `undefined` to wrap
+           * text instead. A `width` property can be added to control the text
+           * width.
+           *
+           * @see In styled mode, the legend items can be styled with the
+           *      `.highcharts-legend-item` class.
+           *
+           * @sample {highcharts} highcharts/legend/itemstyle/
+           *         Bold black text
+           * @sample {highmaps} maps/legend/itemstyle/
+           *         Item text styles
+           *
+           * @type    {Highcharts.CSSObject}
+           * @default {"color": "#333333", "cursor": "pointer", "fontSize": "12px", "fontWeight": "bold", "textOverflow": "ellipsis"}
+           */
+          itemStyle: {
+            /**
+             * @ignore
+             */
+            color: "#333333",
+            /**
+             * @ignore
+             */
+            cursor: "pointer",
+            /**
+             * @ignore
+             */
+            fontSize: "12px",
+            /**
+             * @ignore
+             */
+            fontWeight: "bold",
+            /**
+             * @ignore
+             */
+            textOverflow: "ellipsis",
+          },
+          /**
+           * CSS styles for each legend item in hover mode. Only a subset of
+           * CSS is supported, notably those options related to text. Properties
+           * are inherited from `style` unless overridden here.
+           *
+           * @see In styled mode, the hovered legend items can be styled with
+           *      the `.highcharts-legend-item:hover` pesudo-class.
+           *
+           * @sample {highcharts} highcharts/legend/itemhoverstyle/
+           *         Red on hover
+           * @sample {highmaps} maps/legend/itemstyle/
+           *         Item text styles
+           *
+           * @type    {Highcharts.CSSObject}
+           * @default {"color": "#000000"}
+           */
+          itemHoverStyle: {
+            /**
+             * @ignore
+             */
+            color: "#000000",
+          },
+          /**
+           * CSS styles for each legend item when the corresponding series or
+           * point is hidden. Only a subset of CSS is supported, notably those
+           * options related to text. Properties are inherited from `style`
+           * unless overridden here.
+           *
+           * @see In styled mode, the hidden legend items can be styled with
+           *      the `.highcharts-legend-item-hidden` class.
+           *
+           * @sample {highcharts} highcharts/legend/itemhiddenstyle/
+           *         Darker gray color
+           *
+           * @type    {Highcharts.CSSObject}
+           * @default {"color": "#cccccc"}
+           */
+          itemHiddenStyle: {
+            /**
+             * @ignore
+             */
+            color: "#cccccc",
+          },
+          /**
+           * Whether to apply a drop shadow to the legend. A `backgroundColor`
+           * also needs to be applied for this to take effect. The shadow can be
+           * an object configuration containing `color`, `offsetX`, `offsetY`,
+           * `opacity` and `width`.
+           *
+           * @sample {highcharts} highcharts/legend/shadow/
+           *         White background and drop shadow
+           * @sample {highstock} stock/legend/align/
+           *         Various legend options
+           * @sample {highmaps} maps/legend/border-background/
+           *         Border and background options
+           *
+           * @type {boolean|Highcharts.CSSObject}
+           */
+          shadow: false,
+          /**
+           * Default styling for the checkbox next to a legend item when
+           * `showCheckbox` is true.
+           *
+           * @type {Highcharts.CSSObject}
+           * @default {"width": "13px", "height": "13px", "position":"absolute"}
+           */
+          itemCheckboxStyle: {
+            /**
+             * @ignore
+             */
+            position: "absolute",
+            /**
+             * @ignore
+             */
+            width: "13px",
+            /**
+             * @ignore
+             */
+            height: "13px",
+          },
+          // itemWidth: undefined,
+          /**
+           * When this is true, the legend symbol width will be the same as
+           * the symbol height, which in turn defaults to the font size of the
+           * legend items.
+           *
+           * @since 5.0.0
+           */
+          squareSymbol: true,
+          /**
+           * The pixel height of the symbol for series types that use a rectangle
+           * in the legend. Defaults to the font size of legend items.
+           *
+           * @productdesc {highmaps}
+           * In Highmaps, when the symbol is the gradient of a vertical color
+           * axis, the height defaults to 200.
+           *
+           * @sample {highmaps} maps/legend/layout-vertical-sized/
+           *         Sized vertical gradient
+           * @sample {highmaps} maps/legend/padding-itemmargin/
+           *         No distance between data classes
+           *
+           * @type      {number}
+           * @since     3.0.8
+           * @apioption legend.symbolHeight
+           */
+          /**
+           * The border radius of the symbol for series types that use a rectangle
+           * in the legend. Defaults to half the `symbolHeight`.
+           *
+           * @sample {highcharts} highcharts/legend/symbolradius/
+           *         Round symbols
+           * @sample {highstock} highcharts/legend/symbolradius/
+           *         Round symbols
+           * @sample {highmaps} highcharts/legend/symbolradius/
+           *         Round symbols
+           *
+           * @type      {number}
+           * @since     3.0.8
+           * @apioption legend.symbolRadius
+           */
+          /**
+           * The pixel width of the legend item symbol. When the `squareSymbol`
+           * option is set, this defaults to the `symbolHeight`, otherwise 16.
+           *
+           * @productdesc {highmaps}
+           * In Highmaps, when the symbol is the gradient of a horizontal color
+           * axis, the width defaults to 200.
+           *
+           * @sample {highcharts} highcharts/legend/symbolwidth/
+           *         Greater symbol width and padding
+           * @sample {highmaps} maps/legend/padding-itemmargin/
+           *         Padding and item margins demonstrated
+           * @sample {highmaps} maps/legend/layout-vertical-sized/
+           *         Sized vertical gradient
+           *
+           * @type      {number}
+           * @apioption legend.symbolWidth
+           */
+          /**
+           * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html)
+           * to render the legend item texts.
+           *
+           * Prior to 4.1.7, when using HTML, [legend.navigation](
+           * #legend.navigation) was disabled.
+           *
+           * @type      {boolean}
+           * @default   false
+           * @apioption legend.useHTML
+           */
+          /**
+           * The width of the legend box. If a number is set, it translates to
+           * pixels. Since v7.0.2 it allows setting a percent string of the full
+           * chart width, for example `40%`.
+           *
+           * Defaults to the full chart width for legends below or above the
+           * chart, half the chart width for legends to the left and right.
+           *
+           * @sample {highcharts} highcharts/legend/width/
+           *         Aligned to the plot area
+           * @sample {highcharts} highcharts/legend/width-percent/
+           *         A percent of the chart width
+           *
+           * @type      {number|string}
+           * @since     2.0
+           * @apioption legend.width
+           */
+          /**
+           * The pixel padding between the legend item symbol and the legend
+           * item text.
+           *
+           * @sample {highcharts} highcharts/legend/symbolpadding/
+           *         Greater symbol width and padding
+           */
+          symbolPadding: 5,
+          /**
+           * The vertical alignment of the legend box. Can be one of `top`,
+           * `middle` or `bottom`. Vertical position can be further determined
+           * by the `y` option.
+           *
+           * In the case that the legend is aligned in a corner position, the
+           * `layout` option will determine whether to place it above/below
+           * or on the side of the plot area.
+           *
+           * When the [layout](#legend.layout) option is `proximate`, the
+           * `verticalAlign` option doesn't apply.
+           *
+           * @sample {highcharts} highcharts/legend/verticalalign/
+           *         Legend 100px from the top of the chart
+           * @sample {highstock} stock/legend/align/
+           *         Various legend options
+           * @sample {highmaps} maps/legend/alignment/
+           *         Legend alignment
+           *
+           * @type  {Highcharts.VerticalAlignValue}
+           * @since 2.0
+           */
+          verticalAlign: "bottom",
+          // width: undefined,
+          /**
+           * The x offset of the legend relative to its horizontal alignment
+           * `align` within chart.spacingLeft and chart.spacingRight. Negative
+           * x moves it to the left, positive x moves it to the right.
+           *
+           * @sample {highcharts} highcharts/legend/width/
+           *         Aligned to the plot area
+           *
+           * @since 2.0
+           */
+          x: 0,
+          /**
+           * The vertical offset of the legend relative to it's vertical alignment
+           * `verticalAlign` within chart.spacingTop and chart.spacingBottom.
+           *  Negative y moves it up, positive y moves it down.
+           *
+           * @sample {highcharts} highcharts/legend/verticalalign/
+           *         Legend 100px from the top of the chart
+           * @sample {highstock} stock/legend/align/
+           *         Various legend options
+           * @sample {highmaps} maps/legend/alignment/
+           *         Legend alignment
+           *
+           * @since 2.0
+           */
+          y: 0,
+          /**
+           * A title to be added on top of the legend.
+           *
+           * @sample {highcharts} highcharts/legend/title/
+           *         Legend title
+           * @sample {highmaps} maps/legend/alignment/
+           *         Legend with title
+           *
+           * @since 3.0
+           */
+          title: {
+            /**
+             * A text or HTML string for the title.
              *
-             * @return {void}
+             * @type      {string}
+             * @since     3.0
+             * @apioption legend.title.text
              */
-            SVGElement.prototype.visibilitySetter = function (value, key, element) {
-                // IE9-11 doesn't handle visibilty:inherit well, so we remove the
-                // attribute instead (#2881, #3909)
-                if (value === 'inherit') {
-                    element.removeAttribute(key);
-                }
-                else if (this[key] !== value) { // #6747
-                    element.setAttribute(key, value);
-                }
-                this[key] = value;
-            };
             /**
-             * @private
-             * @function Highcharts.SVGElement#xGetter
+             * Generic CSS styles for the legend title.
              *
-             * @param {string} key
+             * @see In styled mode, the legend title is styled with the
+             *      `.highcharts-legend-title` class.
              *
-             * @return {number|string|null}
+             * @type    {Highcharts.CSSObject}
+             * @default {"fontWeight": "bold"}
+             * @since   3.0
              */
-            SVGElement.prototype.xGetter = function (key) {
-                if (this.element.nodeName === 'circle') {
-                    if (key === 'x') {
-                        key = 'cx';
-                    }
-                    else if (key === 'y') {
-                        key = 'cy';
-                    }
-                }
-                return this._defaultGetter(key);
-            };
-            /**
-             * @private
-             * @function Highcharts.SVGElement#zIndexSetter
-             * @param {number} [value]
-             * @param {string} [key]
-             * @return {boolean}
-             */
-            SVGElement.prototype.zIndexSetter = function (value, key) {
-                var renderer = this.renderer,
-                    parentGroup = this.parentGroup,
-                    parentWrapper = parentGroup || renderer,
-                    parentNode = parentWrapper.element || renderer.box,
-                    childNodes,
-                    otherElement,
-                    otherZIndex,
-                    element = this.element,
-                    inserted = false,
-                    undefinedOtherZIndex,
-                    svgParent = parentNode === renderer.box,
-                    run = this.added,
-                    i;
-                if (defined(value)) {
-                    // So we can read it for other elements in the group
-                    element.setAttribute('data-z-index', value);
-                    value = +value;
-                    if (this[key] === value) {
-                        // Only update when needed (#3865)
-                        run = false;
-                    }
-                }
-                else if (defined(this[key])) {
-                    element.removeAttribute('data-z-index');
-                }
-                this[key] = value;
-                // Insert according to this and other elements' zIndex. Before .add() is
-                // called, nothing is done. Then on add, or by later calls to
-                // zIndexSetter, the node is placed on the right place in the DOM.
-                if (run) {
-                    value = this.zIndex;
-                    if (value && parentGroup) {
-                        parentGroup.handleZ = true;
-                    }
-                    childNodes = parentNode.childNodes;
-                    for (i = childNodes.length - 1; i >= 0 && !inserted; i--) {
-                        otherElement = childNodes[i];
-                        otherZIndex = otherElement.getAttribute('data-z-index');
-                        undefinedOtherZIndex = !defined(otherZIndex);
-                        if (otherElement !== element) {
-                            if (
-                            // Negative zIndex versus no zIndex:
-                            // On all levels except the highest. If the parent is
-                            // <svg>, then we don't want to put items before <desc>
-                            // or <defs>
-                            value < 0 &&
-                                undefinedOtherZIndex &&
-                                !svgParent &&
-                                !i) {
-                                parentNode.insertBefore(element, childNodes[i]);
-                                inserted = true;
-                            }
-                            else if (
-                            // Insert after the first element with a lower zIndex
-                            pInt(otherZIndex) <= value ||
-                                // If negative zIndex, add this before first undefined
-                                // zIndex element
-                                (undefinedOtherZIndex &&
-                                    (!defined(value) || value >= 0))) {
-                                parentNode.insertBefore(element, childNodes[i + 1] || null // null for oldIE export
-                                );
-                                inserted = true;
-                            }
-                        }
-                    }
-                    if (!inserted) {
-                        parentNode.insertBefore(element, childNodes[svgParent ? 3 : 0] || null // null for oldIE
-                        );
-                        inserted = true;
-                    }
-                }
-                return inserted;
-            };
-            return SVGElement;
-        }());
-        // Some shared setters and getters
-        SVGElement.prototype['stroke-widthSetter'] = SVGElement.prototype.strokeSetter;
-        SVGElement.prototype.yGetter = SVGElement.prototype.xGetter;
-        SVGElement.prototype.matrixSetter =
-            SVGElement.prototype.rotationOriginXSetter =
-                SVGElement.prototype.rotationOriginYSetter =
-                    SVGElement.prototype.rotationSetter =
-                        SVGElement.prototype.scaleXSetter =
-                            SVGElement.prototype.scaleYSetter =
-                                SVGElement.prototype.translateXSetter =
-                                    SVGElement.prototype.translateYSetter =
-                                        SVGElement.prototype.verticalAlignSetter = function (value, key) {
-                                            this[key] = value;
-                                            this.doTransform = true;
-                                        };
-        H.SVGElement = SVGElement;
+            style: {
+              /**
+               * @ignore
+               */
+              fontWeight: "bold",
+            },
+          },
+        },
+        /**
+         * The loading options control the appearance of the loading screen
+         * that covers the plot area on chart operations. This screen only
+         * appears after an explicit call to `chart.showLoading()`. It is a
+         * utility for developers to communicate to the end user that something
+         * is going on, for example while retrieving new data via an XHR connection.
+         * The "Loading..." text itself is not part of this configuration
+         * object, but part of the `lang` object.
+         */
+        loading: {
+          /**
+           * The duration in milliseconds of the fade out effect.
+           *
+           * @sample highcharts/loading/hideduration/
+           *         Fade in and out over a second
+           *
+           * @type      {number}
+           * @default   100
+           * @since     1.2.0
+           * @apioption loading.hideDuration
+           */
+          /**
+           * The duration in milliseconds of the fade in effect.
+           *
+           * @sample highcharts/loading/hideduration/
+           *         Fade in and out over a second
+           *
+           * @type      {number}
+           * @default   100
+           * @since     1.2.0
+           * @apioption loading.showDuration
+           */
+          /**
+           * CSS styles for the loading label `span`.
+           *
+           * @see In styled mode, the loading label is styled with the
+           *      `.highcharts-loading-inner` class.
+           *
+           * @sample {highcharts|highmaps} highcharts/loading/labelstyle/
+           *         Vertically centered
+           * @sample {highstock} stock/loading/general/
+           *         Label styles
+           *
+           * @type    {Highcharts.CSSObject}
+           * @default {"fontWeight": "bold", "position": "relative", "top": "45%"}
+           * @since   1.2.0
+           */
+          labelStyle: {
+            /**
+             * @ignore
+             */
+            fontWeight: "bold",
+            /**
+             * @ignore
+             */
+            position: "relative",
+            /**
+             * @ignore
+             */
+            top: "45%",
+          },
+          /**
+           * CSS styles for the loading screen that covers the plot area.
+           *
+           * In styled mode, the loading label is styled with the
+           * `.highcharts-loading` class.
+           *
+           * @sample  {highcharts|highmaps} highcharts/loading/style/
+           *          Gray plot area, white text
+           * @sample  {highstock} stock/loading/general/
+           *          Gray plot area, white text
+           *
+           * @type    {Highcharts.CSSObject}
+           * @default {"position": "absolute", "backgroundColor": "#ffffff", "opacity": 0.5, "textAlign": "center"}
+           * @since   1.2.0
+           */
+          style: {
+            /**
+             * @ignore
+             */
+            position: "absolute",
+            /**
+             * @ignore
+             */
+            backgroundColor: "#ffffff",
+            /**
+             * @ignore
+             */
+            opacity: 0.5,
+            /**
+             * @ignore
+             */
+            textAlign: "center",
+          },
+        },
+        /**
+         * Options for the tooltip that appears when the user hovers over a
+         * series or point.
+         *
+         * @declare Highcharts.TooltipOptions
+         */
+        tooltip: {
+          /**
+           * The color of the tooltip border. When `undefined`, the border takes
+           * the color of the corresponding series or point.
+           *
+           * @sample {highcharts} highcharts/tooltip/bordercolor-default/
+           *         Follow series by default
+           * @sample {highcharts} highcharts/tooltip/bordercolor-black/
+           *         Black border
+           * @sample {highstock} stock/tooltip/general/
+           *         Styled tooltip
+           * @sample {highmaps} maps/tooltip/background-border/
+           *         Background and border demo
+           *
+           * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+           * @apioption tooltip.borderColor
+           */
+          /**
+           * A CSS class name to apply to the tooltip's container div,
+           * allowing unique CSS styling for each chart.
+           *
+           * @type      {string}
+           * @apioption tooltip.className
+           */
+          /**
+           * Since 4.1, the crosshair definitions are moved to the Axis object
+           * in order for a better separation from the tooltip. See
+           * [xAxis.crosshair](#xAxis.crosshair).
+           *
+           * @sample {highcharts} highcharts/tooltip/crosshairs-x/
+           *         Enable a crosshair for the x value
+           *
+           * @deprecated
+           *
+           * @type      {*}
+           * @default   true
+           * @apioption tooltip.crosshairs
+           */
+          /**
+           * Distance from point to tooltip in pixels.
+           *
+           * @type      {number}
+           * @default   16
+           * @apioption tooltip.distance
+           */
+          /**
+           * Whether the tooltip should follow the mouse as it moves across
+           * columns, pie slices and other point types with an extent.
+           * By default it behaves this way for pie, polygon, map, sankey
+           * and wordcloud series by override in the `plotOptions`
+           * for those series types.
+           *
+           * For touch moves to behave the same way, [followTouchMove](
+           * #tooltip.followTouchMove) must be `true` also.
+           *
+           * @type      {boolean}
+           * @default   {highcharts} false
+           * @default   {highstock} false
+           * @default   {highmaps} true
+           * @since     3.0
+           * @apioption tooltip.followPointer
+           */
+          /**
+           * Whether the tooltip should update as the finger moves on a touch
+           * device. If this is `true` and [chart.panning](#chart.panning) is
+           * set,`followTouchMove` will take over one-finger touches, so the user
+           * needs to use two fingers for zooming and panning.
+           *
+           * Note the difference to [followPointer](#tooltip.followPointer) that
+           * only defines the _position_ of the tooltip. If `followPointer` is
+           * false in for example a column series, the tooltip will show above or
+           * below the column, but as `followTouchMove` is true, the tooltip will
+           * jump from column to column as the user swipes across the plot area.
+           *
+           * @type      {boolean}
+           * @default   {highcharts} true
+           * @default   {highstock} true
+           * @default   {highmaps} false
+           * @since     3.0.1
+           * @apioption tooltip.followTouchMove
+           */
+          /**
+           * Callback function to format the text of the tooltip from scratch. In
+           * case of single or [shared](#tooltip.shared) tooltips, a string should
+           * be returned. In case of [split](#tooltip.split) tooltips, it should
+           * return an array where the first item is the header, and subsequent
+           * items are mapped to the points. Return `false` to disable tooltip for
+           * a specific point on series.
+           *
+           * A subset of HTML is supported. Unless `useHTML` is true, the HTML of
+           * the tooltip is parsed and converted to SVG, therefore this isn't a
+           * complete HTML renderer. The following HTML tags are supported: `b`,
+           * `br`, `em`, `i`, `span`, `strong`. Spans can be styled with a `style`
+           * attribute, but only text-related CSS, that is shared with SVG, is
+           * handled.
+           *
+           * The available data in the formatter differ a bit depending on whether
+           * the tooltip is shared or split, or belongs to a single point. In a
+           * shared/split tooltip, all properties except `x`, which is common for
+           * all points, are kept in an array, `this.points`.
+           *
+           * Available data are:
+           *
+           * - **this.percentage (not shared) /**
+           *   **this.points[i].percentage (shared)**:
+           *   Stacked series and pies only. The point's percentage of the total.
+           *
+           * - **this.point (not shared) / this.points[i].point (shared)**:
+           *   The point object. The point name, if defined, is available through
+           *   `this.point.name`.
+           *
+           * - **this.points**:
+           *   In a shared tooltip, this is an array containing all other
+           *   properties for each point.
+           *
+           * - **this.series (not shared) / this.points[i].series (shared)**:
+           *   The series object. The series name is available through
+           *   `this.series.name`.
+           *
+           * - **this.total (not shared) / this.points[i].total (shared)**:
+           *   Stacked series only. The total value at this point's x value.
+           *
+           * - **this.x**:
+           *   The x value. This property is the same regardless of the tooltip
+           *   being shared or not.
+           *
+           * - **this.y (not shared) / this.points[i].y (shared)**:
+           *   The y value.
+           *
+           * @sample {highcharts} highcharts/tooltip/formatter-simple/
+           *         Simple string formatting
+           * @sample {highcharts} highcharts/tooltip/formatter-shared/
+           *         Formatting with shared tooltip
+           * @sample {highcharts|highstock} highcharts/tooltip/formatter-split/
+           *         Formatting with split tooltip
+           * @sample highcharts/tooltip/formatter-conditional-default/
+           *         Extending default formatter
+           * @sample {highstock} stock/tooltip/formatter/
+           *         Formatting with shared tooltip
+           * @sample {highmaps} maps/tooltip/formatter/
+           *         String formatting
+           *
+           * @type      {Highcharts.TooltipFormatterCallbackFunction}
+           * @apioption tooltip.formatter
+           */
+          /**
+           * Callback function to format the text of the tooltip for
+           * visible null points.
+           * Works analogously to [formatter](#tooltip.formatter).
+           *
+           * @sample highcharts/plotoptions/series-nullformat
+           *         Format data label and tooltip for null point.
+           *
+           * @type      {Highcharts.TooltipFormatterCallbackFunction}
+           * @apioption tooltip.nullFormatter
+           */
+          /**
+           * The number of milliseconds to wait until the tooltip is hidden when
+           * mouse out from a point or chart.
+           *
+           * @type      {number}
+           * @default   500
+           * @since     3.0
+           * @apioption tooltip.hideDelay
+           */
+          /**
+           * Whether to allow the tooltip to render outside the chart's SVG
+           * element box. By default (`false`), the tooltip is rendered within the
+           * chart's SVG element, which results in the tooltip being aligned
+           * inside the chart area. For small charts, this may result in clipping
+           * or overlapping. When `true`, a separate SVG element is created and
+           * overlaid on the page, allowing the tooltip to be aligned inside the
+           * page itself.
+           *
+           * Defaults to `true` if `chart.scrollablePlotArea` is activated,
+           * otherwise `false`.
+           *
+           * @sample highcharts/tooltip/outside
+           *         Small charts with tooltips outside
+           *
+           * @type      {boolean|undefined}
+           * @default   undefined
+           * @since     6.1.1
+           * @apioption tooltip.outside
+           */
+          /**
+           * A callback function for formatting the HTML output for a single point
+           * in the tooltip. Like the `pointFormat` string, but with more
+           * flexibility.
+           *
+           * @type      {Highcharts.FormatterCallbackFunction<Highcharts.Point>}
+           * @since     4.1.0
+           * @context   Highcharts.Point
+           * @apioption tooltip.pointFormatter
+           */
+          /**
+           * A callback function to place the tooltip in a default position. The
+           * callback receives three parameters: `labelWidth`, `labelHeight` and
+           * `point`, where point contains values for `plotX` and `plotY` telling
+           * where the reference point is in the plot area. Add `chart.plotLeft`
+           * and `chart.plotTop` to get the full coordinates.
+           *
+           * Since v7, when [tooltip.split](#tooltip.split) option is enabled,
+           * positioner is called for each of the boxes separately, including
+           * xAxis header. xAxis header is not a point, instead `point` argument
+           * contains info:
+           * `{ plotX: Number, plotY: Number, isHeader: Boolean }`
+           *
+           *
+           * The return should be an object containing x and y values, for example
+           * `{ x: 100, y: 100 }`.
+           *
+           * @sample {highcharts} highcharts/tooltip/positioner/
+           *         A fixed tooltip position
+           * @sample {highstock} stock/tooltip/positioner/
+           *         A fixed tooltip position on top of the chart
+           * @sample {highmaps} maps/tooltip/positioner/
+           *         A fixed tooltip position
+           * @sample {highstock} stock/tooltip/split-positioner/
+           *         Split tooltip with fixed positions
+           * @sample {highstock} stock/tooltip/positioner-scrollable-plotarea/
+           *         Scrollable plot area combined with tooltip positioner
+           *
+           * @type      {Highcharts.TooltipPositionerCallbackFunction}
+           * @since     2.2.4
+           * @apioption tooltip.positioner
+           */
+          /**
+           * The name of a symbol to use for the border around the tooltip. Can
+           * be one of: `"callout"`, `"circle"`, or `"square"`. When
+           * [tooltip.split](#tooltip.split)
+           * option is enabled, shape is applied to all boxes except header, which
+           * is controlled by
+           * [tooltip.headerShape](#tooltip.headerShape).
+           *
+           * Custom callbacks for symbol path generation can also be added to
+           * `Highcharts.SVGRenderer.prototype.symbols` the same way as for
+           * [series.marker.symbol](plotOptions.line.marker.symbol).
+           *
+           * @type      {Highcharts.TooltipShapeValue}
+           * @default   callout
+           * @since     4.0
+           * @apioption tooltip.shape
+           */
+          /**
+           * The name of a symbol to use for the border around the tooltip
+           * header. Applies only when [tooltip.split](#tooltip.split) is
+           * enabled.
+           *
+           * Custom callbacks for symbol path generation can also be added to
+           * `Highcharts.SVGRenderer.prototype.symbols` the same way as for
+           * [series.marker.symbol](plotOptions.line.marker.symbol).
+           *
+           * @see [tooltip.shape](#tooltip.shape)
+           *
+           * @sample {highstock} stock/tooltip/split-positioner/
+           *         Different shapes for header and split boxes
+           *
+           * @type       {Highcharts.TooltipShapeValue}
+           * @default    callout
+           * @validvalue ["callout", "square"]
+           * @since      7.0
+           * @apioption  tooltip.headerShape
+           */
+          /**
+           * When the tooltip is shared, the entire plot area will capture mouse
+           * movement or touch events. Tooltip texts for series types with ordered
+           * data (not pie, scatter, flags etc) will be shown in a single bubble.
+           * This is recommended for single series charts and for tablet/mobile
+           * optimized charts.
+           *
+           * See also [tooltip.split](#tooltip.split), that is better suited for
+           * charts with many series, especially line-type series. The
+           * `tooltip.split` option takes precedence over `tooltip.shared`.
+           *
+           * @sample {highcharts} highcharts/tooltip/shared-false/
+           *         False by default
+           * @sample {highcharts} highcharts/tooltip/shared-true/
+           *         True
+           * @sample {highcharts} highcharts/tooltip/shared-x-crosshair/
+           *         True with x axis crosshair
+           * @sample {highcharts} highcharts/tooltip/shared-true-mixed-types/
+           *         True with mixed series types
+           *
+           * @type      {boolean}
+           * @default   false
+           * @since     2.1
+           * @product   highcharts highstock
+           * @apioption tooltip.shared
+           */
+          /**
+           * Split the tooltip into one label per series, with the header close
+           * to the axis. This is recommended over [shared](#tooltip.shared)
+           * tooltips for charts with multiple line series, generally making them
+           * easier to read. This option takes precedence over `tooltip.shared`.
+           *
+           * @productdesc {highstock} In Highstock, tooltips are split by default
+           * since v6.0.0. Stock charts typically contain multi-dimension points
+           * and multiple panes, making split tooltips the preferred layout over
+           * the previous `shared` tooltip.
+           *
+           * @sample highcharts/tooltip/split/
+           *         Split tooltip
+           * @sample {highcharts|highstock} highcharts/tooltip/formatter-split/
+           *         Split tooltip and custom formatter callback
+           *
+           * @type      {boolean}
+           * @default   {highcharts} false
+           * @default   {highstock} true
+           * @since     5.0.0
+           * @product   highcharts highstock
+           * @apioption tooltip.split
+           */
+          /**
+           * Prevents the tooltip from switching or closing, when touched or
+           * pointed.
+           *
+           * @sample highcharts/tooltip/stickoncontact/
+           *         Tooltip sticks on pointer contact
+           *
+           * @type      {boolean}
+           * @since     8.0.1
+           * @apioption tooltip.stickOnContact
+           */
+          /**
+           * Use HTML to render the contents of the tooltip instead of SVG. Using
+           * HTML allows advanced formatting like tables and images in the
+           * tooltip. It is also recommended for rtl languages as it works around
+           * rtl bugs in early Firefox.
+           *
+           * @sample {highcharts|highstock} highcharts/tooltip/footerformat/
+           *         A table for value alignment
+           * @sample {highcharts|highstock} highcharts/tooltip/fullhtml/
+           *         Full HTML tooltip
+           * @sample {highmaps} maps/tooltip/usehtml/
+           *         Pure HTML tooltip
+           *
+           * @type      {boolean}
+           * @default   false
+           * @since     2.2
+           * @apioption tooltip.useHTML
+           */
+          /**
+           * How many decimals to show in each series' y value. This is
+           * overridable in each series' tooltip options object. The default is to
+           * preserve all decimals.
+           *
+           * @sample {highcharts|highstock} highcharts/tooltip/valuedecimals/
+           *         Set decimals, prefix and suffix for the value
+           * @sample {highmaps} maps/tooltip/valuedecimals/
+           *         Set decimals, prefix and suffix for the value
+           *
+           * @type      {number}
+           * @since     2.2
+           * @apioption tooltip.valueDecimals
+           */
+          /**
+           * A string to prepend to each series' y value. Overridable in each
+           * series' tooltip options object.
+           *
+           * @sample {highcharts|highstock} highcharts/tooltip/valuedecimals/
+           *         Set decimals, prefix and suffix for the value
+           * @sample {highmaps} maps/tooltip/valuedecimals/
+           *         Set decimals, prefix and suffix for the value
+           *
+           * @type      {string}
+           * @since     2.2
+           * @apioption tooltip.valuePrefix
+           */
+          /**
+           * A string to append to each series' y value. Overridable in each
+           * series' tooltip options object.
+           *
+           * @sample {highcharts|highstock} highcharts/tooltip/valuedecimals/
+           *         Set decimals, prefix and suffix for the value
+           * @sample {highmaps} maps/tooltip/valuedecimals/
+           *         Set decimals, prefix and suffix for the value
+           *
+           * @type      {string}
+           * @since     2.2
+           * @apioption tooltip.valueSuffix
+           */
+          /**
+           * The format for the date in the tooltip header if the X axis is a
+           * datetime axis. The default is a best guess based on the smallest
+           * distance between points in the chart.
+           *
+           * @sample {highcharts} highcharts/tooltip/xdateformat/
+           *         A different format
+           *
+           * @type      {string}
+           * @product   highcharts highstock gantt
+           * @apioption tooltip.xDateFormat
+           */
+          /**
+           * How many decimals to show for the `point.change` value when the
+           * `series.compare` option is set. This is overridable in each series'
+           * tooltip options object. The default is to preserve all decimals.
+           *
+           * @type      {number}
+           * @since     1.0.1
+           * @product   highstock
+           * @apioption tooltip.changeDecimals
+           */
+          /**
+           * Enable or disable the tooltip.
+           *
+           * @sample {highcharts} highcharts/tooltip/enabled/
+           *         Disabled
+           * @sample {highcharts} highcharts/plotoptions/series-point-events-mouseover/
+           *         Disable tooltip and show values on chart instead
+           */
+          enabled: true,
+          /**
+           * Enable or disable animation of the tooltip.
+           *
+           * @type       {boolean}
+           * @default    true
+           * @since      2.3.0
+           */
+          animation: svg,
+          /**
+           * The radius of the rounded border corners.
+           *
+           * @sample {highcharts} highcharts/tooltip/bordercolor-default/
+           *         5px by default
+           * @sample {highcharts} highcharts/tooltip/borderradius-0/
+           *         Square borders
+           * @sample {highmaps} maps/tooltip/background-border/
+           *         Background and border demo
+           */
+          borderRadius: 3,
+          /**
+           * For series on a datetime axes, the date format in the tooltip's
+           * header will by default be guessed based on the closest data points.
+           * This member gives the default string representations used for
+           * each unit. For an overview of the replacement codes, see
+           * [dateFormat](/class-reference/Highcharts#dateFormat).
+           *
+           * @see [xAxis.dateTimeLabelFormats](#xAxis.dateTimeLabelFormats)
+           *
+           * @type    {Highcharts.Dictionary<string>}
+           * @product highcharts highstock gantt
+           */
+          dateTimeLabelFormats: {
+            /** @internal */
+            millisecond: "%A, %b %e, %H:%M:%S.%L",
+            /** @internal */
+            second: "%A, %b %e, %H:%M:%S",
+            /** @internal */
+            minute: "%A, %b %e, %H:%M",
+            /** @internal */
+            hour: "%A, %b %e, %H:%M",
+            /** @internal */
+            day: "%A, %b %e, %Y",
+            /** @internal */
+            week: "Week from %A, %b %e, %Y",
+            /** @internal */
+            month: "%B %Y",
+            /** @internal */
+            year: "%Y",
+          },
+          /**
+           * A string to append to the tooltip format.
+           *
+           * @sample {highcharts} highcharts/tooltip/footerformat/
+           *         A table for value alignment
+           * @sample {highmaps} maps/tooltip/format/
+           *         Format demo
+           *
+           * @since 2.2
+           */
+          footerFormat: "",
+          /**
+           * Padding inside the tooltip, in pixels.
+           *
+           * @since      5.0.0
+           */
+          padding: 8,
+          /**
+           * Proximity snap for graphs or single points. It defaults to 10 for
+           * mouse-powered devices and 25 for touch devices.
+           *
+           * Note that in most cases the whole plot area captures the mouse
+           * movement, and in these cases `tooltip.snap` doesn't make sense. This
+           * applies when [stickyTracking](#plotOptions.series.stickyTracking)
+           * is `true` (default) and when the tooltip is [shared](#tooltip.shared)
+           * or [split](#tooltip.split).
+           *
+           * @sample {highcharts} highcharts/tooltip/bordercolor-default/
+           *         10 px by default
+           * @sample {highcharts} highcharts/tooltip/snap-50/
+           *         50 px on graph
+           *
+           * @type    {number}
+           * @default 10/25
+           * @since   1.2.0
+           * @product highcharts highstock
+           */
+          snap: isTouchDevice ? 25 : 10,
+          /**
+           * The HTML of the tooltip header line. Variables are enclosed by
+           * curly brackets. Available variables are `point.key`, `series.name`,
+           * `series.color` and other members from the `point` and `series`
+           * objects. The `point.key` variable contains the category name, x
+           * value or datetime string depending on the type of axis. For datetime
+           * axes, the `point.key` date format can be set using
+           * `tooltip.xDateFormat`.
+           *
+           * @sample {highcharts} highcharts/tooltip/footerformat/
+           *         An HTML table in the tooltip
+           * @sample {highstock} highcharts/tooltip/footerformat/
+           *         An HTML table in the tooltip
+           * @sample {highmaps} maps/tooltip/format/
+           *         Format demo
+           *
+           * @type       {string}
+           * @apioption  tooltip.headerFormat
+           */
+          headerFormat: '<span style="font-size: 10px">{point.key}</span><br/>',
+          /**
+           * The HTML of the null point's line in the tooltip. Works analogously
+           * to [pointFormat](#tooltip.pointFormat).
+           *
+           * @sample {highcharts} highcharts/plotoptions/series-nullformat
+           *         Format data label and tooltip for null point.
+           *
+           * @type      {string}
+           * @apioption tooltip.nullFormat
+           */
+          /**
+           * The HTML of the point's line in the tooltip. Variables are enclosed
+           * by curly brackets. Available variables are `point.x`, `point.y`,
+           * `series.name` and `series.color` and other properties on the same
+           * form. Furthermore, `point.y` can be extended by the
+           * `tooltip.valuePrefix` and `tooltip.valueSuffix` variables. This can
+           * also be overridden for each series, which makes it a good hook for
+           * displaying units.
+           *
+           * In styled mode, the dot is colored by a class name rather
+           * than the point color.
+           *
+           * @sample {highcharts} highcharts/tooltip/pointformat/
+           *         A different point format with value suffix
+           * @sample {highmaps} maps/tooltip/format/
+           *         Format demo
+           *
+           * @type       {string}
+           * @since      2.2
+           * @apioption  tooltip.pointFormat
+           */
+          pointFormat:
+            '<span style="color:{point.color}">\u25CF</span> {series.name}: <b>{point.y}</b><br/>',
+          /**
+           * The background color or gradient for the tooltip.
+           *
+           * In styled mode, the stroke width is set in the
+           * `.highcharts-tooltip-box` class.
+           *
+           * @sample {highcharts} highcharts/tooltip/backgroundcolor-solid/
+           *         Yellowish background
+           * @sample {highcharts} highcharts/tooltip/backgroundcolor-gradient/
+           *         Gradient
+           * @sample {highcharts} highcharts/css/tooltip-border-background/
+           *         Tooltip in styled mode
+           * @sample {highstock} stock/tooltip/general/
+           *         Custom tooltip
+           * @sample {highstock} highcharts/css/tooltip-border-background/
+           *         Tooltip in styled mode
+           * @sample {highmaps} maps/tooltip/background-border/
+           *         Background and border demo
+           * @sample {highmaps} highcharts/css/tooltip-border-background/
+           *         Tooltip in styled mode
+           *
+           * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+           */
+          backgroundColor: color("#f7f7f7").setOpacity(0.85).get(),
+          /**
+           * The pixel width of the tooltip border.
+           *
+           * In styled mode, the stroke width is set in the
+           * `.highcharts-tooltip-box` class.
+           *
+           * @sample {highcharts} highcharts/tooltip/bordercolor-default/
+           *         2px by default
+           * @sample {highcharts} highcharts/tooltip/borderwidth/
+           *         No border (shadow only)
+           * @sample {highcharts} highcharts/css/tooltip-border-background/
+           *         Tooltip in styled mode
+           * @sample {highstock} stock/tooltip/general/
+           *         Custom tooltip
+           * @sample {highstock} highcharts/css/tooltip-border-background/
+           *         Tooltip in styled mode
+           * @sample {highmaps} maps/tooltip/background-border/
+           *         Background and border demo
+           * @sample {highmaps} highcharts/css/tooltip-border-background/
+           *         Tooltip in styled mode
+           */
+          borderWidth: 1,
+          /**
+           * Whether to apply a drop shadow to the tooltip.
+           *
+           * @sample {highcharts} highcharts/tooltip/bordercolor-default/
+           *         True by default
+           * @sample {highcharts} highcharts/tooltip/shadow/
+           *         False
+           * @sample {highmaps} maps/tooltip/positioner/
+           *         Fixed tooltip position, border and shadow disabled
+           *
+           * @type {boolean|Highcharts.ShadowOptionsObject}
+           */
+          shadow: true,
+          /**
+           * CSS styles for the tooltip. The tooltip can also be styled through
+           * the CSS class `.highcharts-tooltip`.
+           *
+           * Note that the default `pointerEvents` style makes the tooltip ignore
+           * mouse events, so in order to use clickable tooltips, this value must
+           * be set to `auto`.
+           *
+           * @sample {highcharts} highcharts/tooltip/style/
+           *         Greater padding, bold text
+           *
+           * @type {Highcharts.CSSObject}
+           */
+          style: {
+            /** @internal */
+            color: "#333333",
+            /** @internal */
+            cursor: "default",
+            /** @internal */
+            fontSize: "12px",
+            /** @internal */
+            whiteSpace: "nowrap",
+          },
+        },
+        /**
+         * Highchart by default puts a credits label in the lower right corner
+         * of the chart. This can be changed using these options.
+         */
+        credits: {
+          /**
+           * Credits for map source to be concatenated with conventional credit
+           * text. By default this is a format string that collects copyright
+           * information from the map if available.
+           *
+           * @see [mapTextFull](#credits.mapTextFull)
+           * @see [text](#credits.text)
+           *
+           * @type      {string}
+           * @default   \u00a9 <a href="{geojson.copyrightUrl}">{geojson.copyrightShort}</a>
+           * @since     4.2.2
+           * @product   highmaps
+           * @apioption credits.mapText
+           */
+          /**
+           * Detailed credits for map source to be displayed on hover of credits
+           * text. By default this is a format string that collects copyright
+           * information from the map if available.
+           *
+           * @see [mapText](#credits.mapText)
+           * @see [text](#credits.text)
+           *
+           * @type      {string}
+           * @default   {geojson.copyright}
+           * @since     4.2.2
+           * @product   highmaps
+           * @apioption credits.mapTextFull
+           */
+          /**
+           * Whether to show the credits text.
+           *
+           * @sample {highcharts} highcharts/credits/enabled-false/
+           *         Credits disabled
+           * @sample {highstock} stock/credits/enabled/
+           *         Credits disabled
+           * @sample {highmaps} maps/credits/enabled-false/
+           *         Credits disabled
+           */
+          enabled: true,
+          /**
+           * The URL for the credits label.
+           *
+           * @sample {highcharts} highcharts/credits/href/
+           *         Custom URL and text
+           * @sample {highmaps} maps/credits/customized/
+           *         Custom URL and text
+           */
+          href: "https://www.highcharts.com?credits",
+          /**
+           * Position configuration for the credits label.
+           *
+           * @sample {highcharts} highcharts/credits/position-left/
+           *         Left aligned
+           * @sample {highcharts} highcharts/credits/position-left/
+           *         Left aligned
+           * @sample {highmaps} maps/credits/customized/
+           *         Left aligned
+           * @sample {highmaps} maps/credits/customized/
+           *         Left aligned
+           *
+           * @type    {Highcharts.AlignObject}
+           * @since   2.1
+           */
+          position: {
+            /** @internal */
+            align: "right",
+            /** @internal */
+            x: -10,
+            /** @internal */
+            verticalAlign: "bottom",
+            /** @internal */
+            y: -5,
+          },
+          /**
+           * CSS styles for the credits label.
+           *
+           * @see In styled mode, credits styles can be set with the
+           *      `.highcharts-credits` class.
+           *
+           * @type {Highcharts.CSSObject}
+           */
+          style: {
+            /** @internal */
+            cursor: "pointer",
+            /** @internal */
+            color: "#999999",
+            /** @internal */
+            fontSize: "9px",
+          },
+          /**
+           * The text for the credits label.
+           *
+           * @productdesc {highmaps}
+           * If a map is loaded as GeoJSON, the text defaults to
+           * `Highcharts @ {map-credits}`. Otherwise, it defaults to
+           * `Highcharts.com`.
+           *
+           * @sample {highcharts} highcharts/credits/href/
+           *         Custom URL and text
+           * @sample {highmaps} maps/credits/customized/
+           *         Custom URL and text
+           */
+          text: "Highcharts.com",
+        },
+      };
+      /* eslint-disable spaced-comment */
 
-        return H.SVGElement;
-    });
-    _registerModule(_modules, 'Core/Renderer/SVG/SVGLabel.js', [_modules['Core/Renderer/SVG/SVGElement.js'], _modules['Core/Utilities.js']], function (SVGElement, U) {
+      ("");
+      /**
+       * Global `Time` object with default options. Since v6.0.5, time settings can be
+       * applied individually for each chart. If no individual settings apply, this
+       * `Time` object is shared by all instances.
+       *
+       * @name Highcharts.time
+       * @type {Highcharts.Time}
+       */
+      H.time = new Time(merge(H.defaultOptions.global, H.defaultOptions.time));
+      /**
+       * Formats a JavaScript date timestamp (milliseconds since Jan 1st 1970) into a
+       * human readable date string. The format is a subset of the formats for PHP's
+       * [strftime](https://www.php.net/manual/en/function.strftime.php) function.
+       * Additional formats can be given in the {@link Highcharts.dateFormats} hook.
+       *
+       * Since v6.0.5, all internal dates are formatted through the
+       * {@link Highcharts.Chart#time} instance to respect chart-level time settings.
+       * The `Highcharts.dateFormat` function only reflects global time settings set
+       * with `setOptions`.
+       *
+       * Supported format keys:
+       * - `%a`: Short weekday, like 'Mon'
+       * - `%A`: Long weekday, like 'Monday'
+       * - `%d`: Two digit day of the month, 01 to 31
+       * - `%e`: Day of the month, 1 through 31
+       * - `%w`: Day of the week, 0 through 6
+       * - `%b`: Short month, like 'Jan'
+       * - `%B`: Long month, like 'January'
+       * - `%m`: Two digit month number, 01 through 12
+       * - `%y`: Two digits year, like 09 for 2009
+       * - `%Y`: Four digits year, like 2009
+       * - `%H`: Two digits hours in 24h format, 00 through 23
+       * - `%k`: Hours in 24h format, 0 through 23
+       * - `%I`: Two digits hours in 12h format, 00 through 11
+       * - `%l`: Hours in 12h format, 1 through 12
+       * - `%M`: Two digits minutes, 00 through 59
+       * - `%p`: Upper case AM or PM
+       * - `%P`: Lower case AM or PM
+       * - `%S`: Two digits seconds, 00 through 59
+       * - `%L`: Milliseconds (naming from Ruby)
+       *
+       * @function Highcharts.dateFormat
+       *
+       * @param {string} format
+       *        The desired format where various time representations are prefixed
+       *        with `%`.
+       *
+       * @param {number} timestamp
+       *        The JavaScript timestamp.
+       *
+       * @param {boolean} [capitalize=false]
+       *        Upper case first letter in the return.
+       *
+       * @return {string}
+       *         The formatted date.
+       */
+      H.dateFormat = function (format, timestamp, capitalize) {
+        return H.time.dateFormat(format, timestamp, capitalize);
+      };
+      var optionsModule = {
+        dateFormat: H.dateFormat,
+        defaultOptions: H.defaultOptions,
+        time: H.time,
+      };
+
+      return optionsModule;
+    }
+  );
+  _registerModule(
+    _modules,
+    "Core/Axis/Axis.js",
+    [
+      _modules["Core/Animation/AnimationUtilities.js"],
+      _modules["Core/Color/Color.js"],
+      _modules["Core/Globals.js"],
+      _modules["Core/Axis/Tick.js"],
+      _modules["Core/Utilities.js"],
+      _modules["Core/Options.js"],
+    ],
+    function (A, Color, H, Tick, U, O) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      var animObject = A.animObject;
+      var addEvent = U.addEvent,
+        arrayMax = U.arrayMax,
+        arrayMin = U.arrayMin,
+        clamp = U.clamp,
+        correctFloat = U.correctFloat,
+        defined = U.defined,
+        destroyObjectProperties = U.destroyObjectProperties,
+        error = U.error,
+        extend = U.extend,
+        fireEvent = U.fireEvent,
+        format = U.format,
+        getMagnitude = U.getMagnitude,
+        isArray = U.isArray,
+        isFunction = U.isFunction,
+        isNumber = U.isNumber,
+        isString = U.isString,
+        merge = U.merge,
+        normalizeTickInterval = U.normalizeTickInterval,
+        objectEach = U.objectEach,
+        pick = U.pick,
+        relativeLength = U.relativeLength,
+        removeEvent = U.removeEvent,
+        splat = U.splat,
+        syncTimeout = U.syncTimeout;
+      /**
+       * Options for the path on the Axis to be calculated.
+       * @interface Highcharts.AxisPlotLinePathOptionsObject
+       */ /**
+       * Axis value.
+       * @name Highcharts.AxisPlotLinePathOptionsObject#value
+       * @type {number|undefined}
+       */ /**
+       * Line width used for calculation crisp line coordinates. Defaults to 1.
+       * @name Highcharts.AxisPlotLinePathOptionsObject#lineWidth
+       * @type {number|undefined}
+       */ /**
+       * If `false`, the function will return null when it falls outside the axis
+       * bounds. If `true`, the function will return a path aligned to the plot area
+       * sides if it falls outside. If `pass`, it will return a path outside.
+       * @name Highcharts.AxisPlotLinePathOptionsObject#force
+       * @type {string|boolean|undefined}
+       */ /**
+       * Used in Highstock. When `true`, plot paths (crosshair, plotLines, gridLines)
+       * will be rendered on all axes when defined on the first axis.
+       * @name Highcharts.AxisPlotLinePathOptionsObject#acrossPanes
+       * @type {boolean|undefined}
+       */ /**
+       * Use old coordinates (for resizing and rescaling).
+       * If not set, defaults to `false`.
+       * @name Highcharts.AxisPlotLinePathOptionsObject#old
+       * @type {boolean|undefined}
+       */ /**
+       * If given, return the plot line path of a pixel position on the axis.
+       * @name Highcharts.AxisPlotLinePathOptionsObject#translatedValue
+       * @type {number|undefined}
+       */ /**
+       * Used in Polar axes. Reverse the positions for concatenation of polygonal
+       * plot bands
+       * @name Highcharts.AxisPlotLinePathOptionsObject#reverse
+       * @type {boolean|undefined}
+       */
+      /**
+       * Options for crosshairs on axes.
+       *
+       * @product highstock
+       *
+       * @typedef {Highcharts.XAxisCrosshairOptions|Highcharts.YAxisCrosshairOptions} Highcharts.AxisCrosshairOptions
+       */
+      /**
+       * @typedef {"navigator"|"pan"|"rangeSelectorButton"|"rangeSelectorInput"|"scrollbar"|"traverseUpButton"|"zoom"} Highcharts.AxisExtremesTriggerValue
+       */
+      /**
+       * @callback Highcharts.AxisEventCallbackFunction
+       *
+       * @param {Highcharts.Axis} this
+       */
+      /**
+       * @callback Highcharts.AxisLabelsFormatterCallbackFunction
+       *
+       * @param {Highcharts.AxisLabelsFormatterContextObject<number>} this
+       *
+       * @param {Highcharts.AxisLabelsFormatterContextObject<string>} that
+       *
+       * @return {string}
+       */
+      /**
+       * @interface Highcharts.AxisLabelsFormatterContextObject<T>
+       */ /**
+       * @name Highcharts.AxisLabelsFormatterContextObject<T>#axis
+       * @type {Highcharts.Axis}
+       */ /**
+       * @name Highcharts.AxisLabelsFormatterContextObject<T>#chart
+       * @type {Highcharts.Chart}
+       */ /**
+       * @name Highcharts.AxisLabelsFormatterContextObject<T>#isFirst
+       * @type {boolean}
+       */ /**
+       * @name Highcharts.AxisLabelsFormatterContextObject<T>#isLast
+       * @type {boolean}
+       */ /**
+       * @name Highcharts.AxisLabelsFormatterContextObject<T>#pos
+       * @type {number}
+       */ /**
+       * This can be either a numeric value or a category string.
+       * @name Highcharts.AxisLabelsFormatterContextObject<T>#value
+       * @type {T}
+       */
+      /**
+       * Options for axes.
+       *
+       * @typedef {Highcharts.XAxisOptions|Highcharts.YAxisOptions|Highcharts.ZAxisOptions} Highcharts.AxisOptions
+       */
+      /**
+       * @callback Highcharts.AxisPointBreakEventCallbackFunction
+       *
+       * @param {Highcharts.Axis} this
+       *
+       * @param {Highcharts.AxisPointBreakEventObject} evt
+       */
+      /**
+       * @interface Highcharts.AxisPointBreakEventObject
+       */ /**
+       * @name Highcharts.AxisPointBreakEventObject#brk
+       * @type {Highcharts.Dictionary<number>}
+       */ /**
+       * @name Highcharts.AxisPointBreakEventObject#point
+       * @type {Highcharts.Point}
+       */ /**
+       * @name Highcharts.AxisPointBreakEventObject#preventDefault
+       * @type {Function}
+       */ /**
+       * @name Highcharts.AxisPointBreakEventObject#target
+       * @type {Highcharts.SVGElement}
+       */ /**
+       * @name Highcharts.AxisPointBreakEventObject#type
+       * @type {"pointBreak"|"pointInBreak"}
+       */
+      /**
+       * @callback Highcharts.AxisSetExtremesEventCallbackFunction
+       *
+       * @param {Highcharts.Axis} this
+       *
+       * @param {Highcharts.AxisSetExtremesEventObject} evt
+       */
+      /**
+       * @interface Highcharts.AxisSetExtremesEventObject
+       * @extends Highcharts.ExtremesObject
+       */ /**
+       * @name Highcharts.AxisSetExtremesEventObject#preventDefault
+       * @type {Function}
+       */ /**
+       * @name Highcharts.AxisSetExtremesEventObject#target
+       * @type {Highcharts.SVGElement}
+       */ /**
+       * @name Highcharts.AxisSetExtremesEventObject#trigger
+       * @type {Highcharts.AxisExtremesTriggerValue|string}
+       */ /**
+       * @name Highcharts.AxisSetExtremesEventObject#type
+       * @type {"setExtremes"}
+       */
+      /**
+       * @callback Highcharts.AxisTickPositionerCallbackFunction
+       *
+       * @param {Highcharts.Axis} this
+       *
+       * @return {Highcharts.AxisTickPositionsArray}
+       */
+      /**
+       * @interface Highcharts.AxisTickPositionsArray
+       * @augments Array<number>
+       */
+      /**
+       * @typedef {"high"|"low"|"middle"} Highcharts.AxisTitleAlignValue
+       */
+      /**
+       * @typedef {Highcharts.XAxisTitleOptions|Highcharts.YAxisTitleOptions|Highcharts.ZAxisTitleOptions} Highcharts.AxisTitleOptions
+       */
+      /**
+       * @typedef {"linear"|"logarithmic"|"datetime"|"category"|"treegrid"} Highcharts.AxisTypeValue
+       */
+      /**
+       * The returned object literal from the {@link Highcharts.Axis#getExtremes}
+       * function.
+       *
+       * @interface Highcharts.ExtremesObject
+       */ /**
+       * The maximum value of the axis' associated series.
+       * @name Highcharts.ExtremesObject#dataMax
+       * @type {number}
+       */ /**
+       * The minimum value of the axis' associated series.
+       * @name Highcharts.ExtremesObject#dataMin
+       * @type {number}
+       */ /**
+       * The maximum axis value, either automatic or set manually. If the `max` option
+       * is not set, `maxPadding` is 0 and `endOnTick` is false, this value will be
+       * the same as `dataMax`.
+       * @name Highcharts.ExtremesObject#max
+       * @type {number}
+       */ /**
+       * The minimum axis value, either automatic or set manually. If the `min` option
+       * is not set, `minPadding` is 0 and `startOnTick` is false, this value will be
+       * the same as `dataMin`.
+       * @name Highcharts.ExtremesObject#min
+       * @type {number}
+       */ /**
+       * The user defined maximum, either from the `max` option or from a zoom or
+       * `setExtremes` action.
+       * @name Highcharts.ExtremesObject#userMax
+       * @type {number}
+       */ /**
+       * The user defined minimum, either from the `min` option or from a zoom or
+       * `setExtremes` action.
+       * @name Highcharts.ExtremesObject#userMin
+       * @type {number}
+       */
+      /**
+       * Formatter function for the text of a crosshair label.
+       *
+       * @callback Highcharts.XAxisCrosshairLabelFormatterCallbackFunction
+       *
+       * @param {Highcharts.Axis} this
+       *        Axis context
+       *
+       * @param {number} value
+       *        Y value of the data point
+       *
+       * @return {string}
+       */
+      var defaultOptions = O.defaultOptions;
+      var deg2rad = H.deg2rad;
+      /**
+       * Create a new axis object. Called internally when instanciating a new chart or
+       * adding axes by {@link Highcharts.Chart#addAxis}.
+       *
+       * A chart can have from 0 axes (pie chart) to multiples. In a normal, single
+       * series cartesian chart, there is one X axis and one Y axis.
+       *
+       * The X axis or axes are referenced by {@link Highcharts.Chart.xAxis}, which is
+       * an array of Axis objects. If there is only one axis, it can be referenced
+       * through `chart.xAxis[0]`, and multiple axes have increasing indices. The same
+       * pattern goes for Y axes.
+       *
+       * If you need to get the axes from a series object, use the `series.xAxis` and
+       * `series.yAxis` properties. These are not arrays, as one series can only be
+       * associated to one X and one Y axis.
+       *
+       * A third way to reference the axis programmatically is by `id`. Add an `id` in
+       * the axis configuration options, and get the axis by
+       * {@link Highcharts.Chart#get}.
+       *
+       * Configuration options for the axes are given in options.xAxis and
+       * options.yAxis.
+       *
+       * @class
+       * @name Highcharts.Axis
+       *
+       * @param {Highcharts.Chart} chart
+       * The Chart instance to apply the axis on.
+       *
+       * @param {Highcharts.AxisOptions} userOptions
+       * Axis options.
+       */
+      var Axis = /** @class */ (function () {
         /* *
          *
-         *  (c) 2010-2020 Torstein Honsi
+         *  Constructors
          *
-         *  License: www.highcharts.com/license
+         * */
+        function Axis(chart, userOptions) {
+          this.alternateBands = void 0;
+          this.bottom = void 0;
+          this.categories = void 0;
+          this.chart = void 0;
+          this.closestPointRange = void 0;
+          this.coll = void 0;
+          this.hasNames = void 0;
+          this.hasVisibleSeries = void 0;
+          this.height = void 0;
+          this.isLinked = void 0;
+          this.labelEdge = void 0; // @todo
+          this.labelFormatter = void 0;
+          this.left = void 0;
+          this.len = void 0;
+          this.max = void 0;
+          this.maxLabelLength = void 0;
+          this.min = void 0;
+          this.minorTickInterval = void 0;
+          this.minorTicks = void 0;
+          this.minPixelPadding = void 0;
+          this.names = void 0;
+          this.offset = void 0;
+          this.oldMax = void 0;
+          this.oldMin = void 0;
+          this.options = void 0;
+          this.overlap = void 0;
+          this.paddedTicks = void 0;
+          this.plotLinesAndBands = void 0;
+          this.plotLinesAndBandsGroups = void 0;
+          this.pointRange = void 0;
+          this.pointRangePadding = void 0;
+          this.pos = void 0;
+          this.positiveValuesOnly = void 0;
+          this.right = void 0;
+          this.series = void 0;
+          this.side = void 0;
+          this.tickAmount = void 0;
+          this.tickInterval = void 0;
+          this.tickmarkOffset = void 0;
+          this.tickPositions = void 0;
+          this.tickRotCorr = void 0;
+          this.ticks = void 0;
+          this.top = void 0;
+          this.transA = void 0;
+          this.transB = void 0;
+          this.translationSlope = void 0;
+          this.userOptions = void 0;
+          this.visible = void 0;
+          this.width = void 0;
+          this.zoomEnabled = void 0;
+          this.init(chart, userOptions);
+        }
+        /* *
          *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+         *  Functions
          *
          * */
-        var __extends = (this && this.__extends) || (function () {
-                var extendStatics = function (d,
-            b) {
-                    extendStatics = Object.setPrototypeOf ||
-                        ({ __proto__: [] } instanceof Array && function (d,
-            b) { d.__proto__ = b; }) ||
-                        function (d,
-            b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
-                return extendStatics(d, b);
-            };
-            return function (d, b) {
-                extendStatics(d, b);
-                function __() { this.constructor = d; }
-                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
-            };
-        })();
-        var defined = U.defined,
-            extend = U.extend,
-            isNumber = U.isNumber,
-            merge = U.merge,
-            removeEvent = U.removeEvent;
         /**
-         * SVG label to render text.
-         * @private
-         * @class
-         * @name Highcharts.SVGLabel
-         * @augments Highcharts.SVGElement
-         */
-        var SVGLabel = /** @class */ (function (_super) {
-                __extends(SVGLabel, _super);
-            /* *
-             *
-             *  Constructors
-             *
-             * */
-            function SVGLabel(renderer, str, x, y, shape, anchorX, anchorY, useHTML, baseline, className) {
-                var _this = _super.call(this) || this;
-                _this.init(renderer, 'g');
-                _this.textStr = str;
-                _this.x = x;
-                _this.y = y;
-                _this.anchorX = anchorX;
-                _this.anchorY = anchorY;
-                _this.baseline = baseline;
-                _this.className = className;
-                if (className !== 'button') {
-                    _this.addClass('highcharts-label');
-                }
-                if (className) {
-                    _this.addClass('highcharts-' + className);
-                }
-                _this.text = renderer.text('', 0, 0, useHTML)
-                    .attr({
-                    zIndex: 1
-                });
-                // Validate the shape argument
-                var hasBGImage;
-                if (typeof shape === 'string') {
-                    hasBGImage = /^url\((.*?)\)$/.test(shape);
-                    if (_this.renderer.symbols[shape] || hasBGImage) {
-                        _this.symbolKey = shape;
-                    }
-                }
-                _this.bBox = SVGLabel.emptyBBox;
-                _this.padding = 3;
-                _this.paddingLeft = 0;
-                _this.baselineOffset = 0;
-                _this.needsBox = renderer.styledMode || hasBGImage;
-                _this.deferredAttr = {};
-                _this.alignFactor = 0;
-                return _this;
-            }
-            /* *
-             *
-             *  Functions
-             *
-             * */
-            SVGLabel.prototype.alignSetter = function (value) {
-                var alignFactor = {
-                        left: 0,
-                        center: 0.5,
-                        right: 1
-                    }[value];
-                if (alignFactor !== this.alignFactor) {
-                    this.alignFactor = alignFactor;
-                    // Bounding box exists, means we're dynamically changing
-                    if (this.bBox && isNumber(this.xSetting)) {
-                        this.attr({ x: this.xSetting }); // #5134
-                    }
-                }
-            };
-            SVGLabel.prototype.anchorXSetter = function (value, key) {
-                this.anchorX = value;
-                this.boxAttr(key, Math.round(value) - this.getCrispAdjust() - this.xSetting);
-            };
-            SVGLabel.prototype.anchorYSetter = function (value, key) {
-                this.anchorY = value;
-                this.boxAttr(key, value - this.ySetting);
-            };
-            /*
-             * Set a box attribute, or defer it if the box is not yet created
-             */
-            SVGLabel.prototype.boxAttr = function (key, value) {
-                if (this.box) {
-                    this.box.attr(key, value);
-                }
-                else {
-                    this.deferredAttr[key] = value;
-                }
-            };
-            /*
-             * Pick up some properties and apply them to the text instead of the
-             * wrapper.
-             */
-            SVGLabel.prototype.css = function (styles) {
-                if (styles) {
-                    var textStyles = {},
-                        isWidth,
-                        isFontStyle;
-                    // Create a copy to avoid altering the original object
-                    // (#537)
-                    styles = merge(styles);
-                    SVGLabel.textProps.forEach(function (prop) {
-                        if (typeof styles[prop] !== 'undefined') {
-                            textStyles[prop] = styles[prop];
-                            delete styles[prop];
-                        }
-                    });
-                    this.text.css(textStyles);
-                    isWidth = 'width' in textStyles;
-                    isFontStyle = 'fontSize' in textStyles ||
-                        'fontWeight' in textStyles;
-                    // Update existing text, box (#9400, #12163)
-                    if (isWidth || isFontStyle) {
-                        this.updateBoxSize();
-                        // Keep updated (#9400, #12163)
-                        if (isFontStyle) {
-                            this.updateTextPadding();
-                        }
-                    }
-                }
-                return SVGElement.prototype.css.call(this, styles);
-            };
-            /*
-             * Destroy and release memory.
-             */
-            SVGLabel.prototype.destroy = function () {
-                // Added by button implementation
-                removeEvent(this.element, 'mouseenter');
-                removeEvent(this.element, 'mouseleave');
-                if (this.text) {
-                    this.text.destroy();
-                }
-                if (this.box) {
-                    this.box = this.box.destroy();
-                }
-                // Call base implementation to destroy the rest
-                SVGElement.prototype.destroy.call(this);
-                return void 0;
-            };
-            SVGLabel.prototype.fillSetter = function (value, key) {
-                if (value) {
-                    this.needsBox = true;
-                }
-                // for animation getter (#6776)
-                this.fill = value;
-                this.boxAttr(key, value);
-            };
-            /*
-             * Return the bounding box of the box, not the group.
-             */
-            SVGLabel.prototype.getBBox = function () {
-                var bBox = this.bBox;
-                var padding = this.padding;
-                return {
-                    width: bBox.width + 2 * padding,
-                    height: bBox.height + 2 * padding,
-                    x: bBox.x - padding,
-                    y: bBox.y - padding
-                };
-            };
-            SVGLabel.prototype.getCrispAdjust = function () {
-                return this.renderer.styledMode && this.box ?
-                    this.box.strokeWidth() % 2 / 2 :
-                    (this['stroke-width'] ? parseInt(this['stroke-width'], 10) : 0) % 2 / 2;
-            };
-            SVGLabel.prototype.heightSetter = function (value) {
-                this.heightSetting = value;
-            };
-            // Event handling. In case of useHTML, we need to make sure that events
-            // are captured on the span as well, and that mouseenter/mouseleave
-            // between the SVG group and the HTML span are not treated as real
-            // enter/leave events. #13310.
-            SVGLabel.prototype.on = function (eventType, handler) {
-                var label = this;
-                var text = label.text;
-                var span = text && text.element.tagName === 'SPAN' ? text : void 0;
-                var selectiveHandler;
-                if (span) {
-                    selectiveHandler = function (e) {
-                        if ((eventType === 'mouseenter' ||
-                            eventType === 'mouseleave') &&
-                            e.relatedTarget instanceof Element &&
-                            (label.element.contains(e.relatedTarget) ||
-                                span.element.contains(e.relatedTarget))) {
-                            return;
-                        }
-                        handler.call(label.element, e);
-                    };
-                    span.on(eventType, selectiveHandler);
-                }
-                SVGElement.prototype.on.call(label, eventType, selectiveHandler || handler);
-                return label;
-            };
-            /*
-             * After the text element is added, get the desired size of the border
-             * box and add it before the text in the DOM.
-             */
-            SVGLabel.prototype.onAdd = function () {
-                var str = this.textStr;
-                this.text.add(this);
-                this.attr({
-                    // Alignment is available now  (#3295, 0 not rendered if given
-                    // as a value)
-                    text: (defined(str) ? str : ''),
-                    x: this.x,
-                    y: this.y
-                });
-                if (this.box && defined(this.anchorX)) {
-                    this.attr({
-                        anchorX: this.anchorX,
-                        anchorY: this.anchorY
-                    });
-                }
-            };
-            SVGLabel.prototype.paddingSetter = function (value) {
-                if (defined(value) && value !== this.padding) {
-                    this.padding = value;
-                    this.updateTextPadding();
-                }
-            };
-            SVGLabel.prototype.paddingLeftSetter = function (value) {
-                if (defined(value) && value !== this.paddingLeft) {
-                    this.paddingLeft = value;
-                    this.updateTextPadding();
-                }
-            };
-            SVGLabel.prototype.rSetter = function (value, key) {
-                this.boxAttr(key, value);
-            };
-            SVGLabel.prototype.shadow = function (b) {
-                if (b && !this.renderer.styledMode) {
-                    this.updateBoxSize();
-                    if (this.box) {
-                        this.box.shadow(b);
-                    }
-                }
-                return this;
-            };
-            SVGLabel.prototype.strokeSetter = function (value, key) {
-                // for animation getter (#6776)
-                this.stroke = value;
-                this.boxAttr(key, value);
-            };
-            SVGLabel.prototype['stroke-widthSetter'] = function (value, key) {
-                if (value) {
-                    this.needsBox = true;
-                }
-                this['stroke-width'] = value;
-                this.boxAttr(key, value);
-            };
-            SVGLabel.prototype['text-alignSetter'] = function (value) {
-                this.textAlign = value;
-            };
-            SVGLabel.prototype.textSetter = function (text) {
-                if (typeof text !== 'undefined') {
-                    // Must use .attr to ensure transforms are done (#10009)
-                    this.text.attr({ text: text });
-                }
-                this.updateBoxSize();
-                this.updateTextPadding();
-            };
-            /*
-             * This function runs after the label is added to the DOM (when the bounding
-             * box is available), and after the text of the label is updated to detect
-             * the new bounding box and reflect it in the border box.
-             */
-            SVGLabel.prototype.updateBoxSize = function () {
-                var style = this.text.element.style,
-                    crispAdjust,
-                    attribs = {};
-                var padding = this.padding;
-                var paddingLeft = this.paddingLeft;
-                // #12165 error when width is null (auto)
-                // #12163 when fontweight: bold, recalculate bBox withot cache
-                // #3295 && 3514 box failure when string equals 0
-                var bBox = ((!isNumber(this.widthSetting) || !isNumber(this.heightSetting) || this.textAlign) &&
-                        defined(this.text.textStr)) ?
-                        this.text.getBBox() : SVGLabel.emptyBBox;
-                this.width = ((this.widthSetting || bBox.width || 0) +
-                    2 * padding +
-                    paddingLeft);
-                this.height = (this.heightSetting || bBox.height || 0) + 2 * padding;
-                // Update the label-scoped y offset. Math.min because of inline
-                // style (#9400)
-                this.baselineOffset = padding + Math.min(this.renderer.fontMetrics(style && style.fontSize, this.text).b, 
-                // When the height is 0, there is no bBox, so go with the font
-                // metrics. Highmaps CSS demos.
-                bBox.height || Infinity);
-                if (this.needsBox) {
-                    // Create the border box if it is not already present
-                    if (!this.box) {
-                        // Symbol definition exists (#5324)
-                        var box = this.box = this.symbolKey ?
-                                this.renderer.symbol(this.symbolKey) :
-                                this.renderer.rect();
-                        box.addClass(// Don't use label className for buttons
-                        (this.className === 'button' ? '' : 'highcharts-label-box') +
-                            (this.className ? ' highcharts-' + this.className + '-box' : ''));
-                        box.add(this);
-                        crispAdjust = this.getCrispAdjust();
-                        attribs.x = crispAdjust;
-                        attribs.y = (this.baseline ? -this.baselineOffset : 0) + crispAdjust;
-                    }
-                    // Apply the box attributes
-                    attribs.width = Math.round(this.width);
-                    attribs.height = Math.round(this.height);
-                    this.box.attr(extend(attribs, this.deferredAttr));
-                    this.deferredAttr = {};
-                }
-                this.bBox = bBox;
-            };
-            /*
-             * This function runs after setting text or padding, but only if padding
-             * is changed.
-             */
-            SVGLabel.prototype.updateTextPadding = function () {
-                var text = this.text;
-                // Determine y based on the baseline
-                var textY = this.baseline ? 0 : this.baselineOffset;
-                var textX = this.paddingLeft + this.padding;
-                // compensate for alignment
-                if (defined(this.widthSetting) &&
-                    this.bBox &&
-                    (this.textAlign === 'center' || this.textAlign === 'right')) {
-                    textX += { center: 0.5, right: 1 }[this.textAlign] *
-                        (this.widthSetting - this.bBox.width);
-                }
-                // update if anything changed
-                if (textX !== text.x || textY !== text.y) {
-                    text.attr('x', textX);
-                    // #8159 - prevent misplaced data labels in treemap
-                    // (useHTML: true)
-                    if (text.hasBoxWidthChanged) {
-                        this.bBox = text.getBBox(true);
-                        this.updateBoxSize();
-                    }
-                    if (typeof textY !== 'undefined') {
-                        text.attr('y', textY);
-                    }
-                }
-                // record current values
-                text.x = textX;
-                text.y = textY;
-            };
-            SVGLabel.prototype.widthSetter = function (value) {
-                // width:auto => null
-                this.widthSetting = isNumber(value) ? value : void 0;
-            };
-            SVGLabel.prototype.xSetter = function (value) {
-                this.x = value; // for animation getter
-                if (this.alignFactor) {
-                    value -= this.alignFactor * ((this.widthSetting || this.bBox.width) +
-                        2 * this.padding);
-                    // Force animation even when setting to the same value (#7898)
-                    this['forceAnimate:x'] = true;
-                }
-                this.xSetting = Math.round(value);
-                this.attr('translateX', this.xSetting);
-            };
-            SVGLabel.prototype.ySetter = function (value) {
-                this.ySetting = this.y = Math.round(value);
-                this.attr('translateY', this.ySetting);
-            };
-            /* *
-             *
-             *  Static Properties
-             *
-             * */
-            SVGLabel.emptyBBox = { width: 0, height: 0, x: 0, y: 0 };
-            /* *
-             *
-             *  Properties
-             *
-             * */
-            /**
-             * For labels, these CSS properties are applied to the `text` node directly.
-             *
-             * @private
-             * @name Highcharts.SVGLabel#textProps
-             * @type {Array<string>}
-             */
-            SVGLabel.textProps = [
-                'color', 'cursor', 'direction', 'fontFamily', 'fontSize', 'fontStyle',
-                'fontWeight', 'lineHeight', 'textAlign', 'textDecoration',
-                'textOutline', 'textOverflow', 'width'
-            ];
-            return SVGLabel;
-        }(SVGElement));
-
-        return SVGLabel;
-    });
-    _registerModule(_modules, 'Core/Renderer/SVG/SVGRenderer.js', [_modules['Core/Color/Color.js'], _modules['Core/Globals.js'], _modules['Core/Renderer/SVG/SVGElement.js'], _modules['Core/Renderer/SVG/SVGLabel.js'], _modules['Core/Utilities.js']], function (Color, H, SVGElement, SVGLabel, U) {
-        /* *
+         * Overrideable function to initialize the axis.
          *
-         *  (c) 2010-2020 Torstein Honsi
+         * @see {@link Axis}
          *
-         *  License: www.highcharts.com/license
+         * @function Highcharts.Axis#init
          *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+         * @param {Highcharts.Chart} chart
+         * The Chart instance to apply the axis on.
          *
-         * */
-        var addEvent = U.addEvent,
-            attr = U.attr,
-            createElement = U.createElement,
-            css = U.css,
-            defined = U.defined,
-            destroyObjectProperties = U.destroyObjectProperties,
-            extend = U.extend,
-            isArray = U.isArray,
-            isNumber = U.isNumber,
-            isObject = U.isObject,
-            isString = U.isString,
-            merge = U.merge,
-            objectEach = U.objectEach,
-            pick = U.pick,
-            pInt = U.pInt,
-            splat = U.splat,
-            uniqueKey = U.uniqueKey;
-        /**
-         * A clipping rectangle that can be applied to one or more {@link SVGElement}
-         * instances. It is instanciated with the {@link SVGRenderer#clipRect} function
-         * and applied with the {@link SVGElement#clip} function.
+         * @param {Highcharts.AxisOptions} userOptions
+         * Axis options.
          *
-         * @example
-         * var circle = renderer.circle(100, 100, 100)
-         *     .attr({ fill: 'red' })
-         *     .add();
-         * var clipRect = renderer.clipRect(100, 100, 100, 100);
+         * @fires Highcharts.Axis#event:afterInit
+         * @fires Highcharts.Axis#event:init
+         */
+        Axis.prototype.init = function (chart, userOptions) {
+          var isXAxis = userOptions.isX,
+            axis = this;
+          /**
+           * The Chart that the axis belongs to.
+           *
+           * @name Highcharts.Axis#chart
+           * @type {Highcharts.Chart}
+           */
+          axis.chart = chart;
+          /**
+           * Whether the axis is horizontal.
+           *
+           * @name Highcharts.Axis#horiz
+           * @type {boolean|undefined}
+           */
+          axis.horiz = chart.inverted && !axis.isZAxis ? !isXAxis : isXAxis;
+          /**
+           * Whether the axis is the x-axis.
+           *
+           * @name Highcharts.Axis#isXAxis
+           * @type {boolean|undefined}
+           */
+          axis.isXAxis = isXAxis;
+          /**
+           * The collection where the axis belongs, for example `xAxis`, `yAxis`
+           * or `colorAxis`. Corresponds to properties on Chart, for example
+           * {@link Chart.xAxis}.
+           *
+           * @name Highcharts.Axis#coll
+           * @type {string}
+           */
+          axis.coll = axis.coll || (isXAxis ? "xAxis" : "yAxis");
+          fireEvent(this, "init", { userOptions: userOptions });
+          axis.opposite = userOptions.opposite; // needed in setOptions
+          /**
+           * The side on which the axis is rendered. 0 is top, 1 is right, 2
+           * is bottom and 3 is left.
+           *
+           * @name Highcharts.Axis#side
+           * @type {number}
+           */
+          axis.side =
+            userOptions.side ||
+            (axis.horiz
+              ? axis.opposite
+                ? 0
+                : 2 // top : bottom
+              : axis.opposite
+              ? 1
+              : 3); // right : left
+          /**
+           * Current options for the axis after merge of defaults and user's
+           * options.
+           *
+           * @name Highcharts.Axis#options
+           * @type {Highcharts.AxisOptions}
+           */
+          axis.setOptions(userOptions);
+          var options = this.options,
+            type = options.type;
+          axis.labelFormatter =
+            options.labels.formatter ||
+            // can be overwritten by dynamic format
+            axis.defaultLabelFormatter;
+          /**
+           * User's options for this axis without defaults.
+           *
+           * @name Highcharts.Axis#userOptions
+           * @type {Highcharts.AxisOptions}
+           */
+          axis.userOptions = userOptions;
+          axis.minPixelPadding = 0;
+          /**
+           * Whether the axis is reversed. Based on the `axis.reversed`,
+           * option, but inverted charts have reversed xAxis by default.
+           *
+           * @name Highcharts.Axis#reversed
+           * @type {boolean}
+           */
+          axis.reversed = options.reversed;
+          axis.visible = options.visible !== false;
+          axis.zoomEnabled = options.zoomEnabled !== false;
+          // Initial categories
+          axis.hasNames = type === "category" || options.categories === true;
+          /**
+           * If categories are present for the axis, names are used instead of
+           * numbers for that axis.
+           *
+           * Since Highcharts 3.0, categories can also be extracted by giving each
+           * point a name and setting axis type to `category`. However, if you
+           * have multiple series, best practice remains defining the `categories`
+           * array.
+           *
+           * @see [xAxis.categories](/highcharts/xAxis.categories)
+           *
+           * @name Highcharts.Axis#categories
+           * @type {Array<string>}
+           * @readonly
+           */
+          axis.categories = options.categories || axis.hasNames;
+          if (!axis.names) {
+            // Preserve on update (#3830)
+            axis.names = [];
+            axis.names.keys = {};
+          }
+          // Placeholder for plotlines and plotbands groups
+          axis.plotLinesAndBandsGroups = {};
+          // Shorthand types
+          axis.positiveValuesOnly = !!axis.logarithmic;
+          // Flag, if axis is linked to another axis
+          axis.isLinked = defined(options.linkedTo);
+          /**
+           * List of major ticks mapped by postition on axis.
+           *
+           * @see {@link Highcharts.Tick}
+           *
+           * @name Highcharts.Axis#ticks
+           * @type {Highcharts.Dictionary<Highcharts.Tick>}
+           */
+          axis.ticks = {};
+          axis.labelEdge = [];
+          /**
+           * List of minor ticks mapped by position on the axis.
+           *
+           * @see {@link Highcharts.Tick}
+           *
+           * @name Highcharts.Axis#minorTicks
+           * @type {Highcharts.Dictionary<Highcharts.Tick>}
+           */
+          axis.minorTicks = {};
+          // List of plotLines/Bands
+          axis.plotLinesAndBands = [];
+          // Alternate bands
+          axis.alternateBands = {};
+          // Axis metrics
+          axis.len = 0;
+          axis.minRange = axis.userMinRange =
+            options.minRange || options.maxZoom;
+          axis.range = options.range;
+          axis.offset = options.offset || 0;
+          /**
+           * The maximum value of the axis. In a logarithmic axis, this is the
+           * logarithm of the real value, and the real value can be obtained from
+           * {@link Axis#getExtremes}.
+           *
+           * @name Highcharts.Axis#max
+           * @type {number|null}
+           */
+          axis.max = null;
+          /**
+           * The minimum value of the axis. In a logarithmic axis, this is the
+           * logarithm of the real value, and the real value can be obtained from
+           * {@link Axis#getExtremes}.
+           *
+           * @name Highcharts.Axis#min
+           * @type {number|null}
+           */
+          axis.min = null;
+          /**
+           * The processed crosshair options.
+           *
+           * @name Highcharts.Axis#crosshair
+           * @type {boolean|Highcharts.AxisCrosshairOptions}
+           */
+          axis.crosshair = pick(
+            options.crosshair,
+            splat(chart.options.tooltip.crosshairs)[isXAxis ? 0 : 1],
+            false
+          );
+          var events = axis.options.events;
+          // Register. Don't add it again on Axis.update().
+          if (chart.axes.indexOf(axis) === -1) {
+            //
+            if (isXAxis) {
+              // #2713
+              chart.axes.splice(chart.xAxis.length, 0, axis);
+            } else {
+              chart.axes.push(axis);
+            }
+            chart[axis.coll].push(axis);
+          }
+          /**
+           * All series associated to the axis.
+           *
+           * @name Highcharts.Axis#series
+           * @type {Array<Highcharts.Series>}
+           */
+          axis.series = axis.series || []; // populated by Series
+          // Reversed axis
+          if (
+            chart.inverted &&
+            !axis.isZAxis &&
+            isXAxis &&
+            typeof axis.reversed === "undefined"
+          ) {
+            axis.reversed = true;
+          }
+          axis.labelRotation = axis.options.labels.rotation;
+          // register event listeners
+          objectEach(events, function (event, eventType) {
+            if (isFunction(event)) {
+              addEvent(axis, eventType, event);
+            }
+          });
+          fireEvent(this, "afterInit");
+        };
+        /**
+         * Merge and set options.
          *
-         * // Leave only the lower right quarter visible
-         * circle.clip(clipRect);
+         * @private
+         * @function Highcharts.Axis#setOptions
          *
-         * @typedef {Highcharts.SVGElement} Highcharts.ClipRectElement
-         */
-        /**
-         * The font metrics.
+         * @param {Highcharts.AxisOptions} userOptions
+         * Axis options.
          *
-         * @interface Highcharts.FontMetricsObject
-         */ /**
-        * The baseline relative to the top of the box.
-        *
-        * @name Highcharts.FontMetricsObject#b
-        * @type {number}
-        */ /**
-        * The font size.
-        *
-        * @name Highcharts.FontMetricsObject#f
-        * @type {number}
-        */ /**
-        * The line height.
-        *
-        * @name Highcharts.FontMetricsObject#h
-        * @type {number}
-        */
-        /**
-         * An object containing `x` and `y` properties for the position of an element.
-         *
-         * @interface Highcharts.PositionObject
-         */ /**
-        * X position of the element.
-        * @name Highcharts.PositionObject#x
-        * @type {number}
-        */ /**
-        * Y position of the element.
-        * @name Highcharts.PositionObject#y
-        * @type {number}
-        */
-        /**
-         * A rectangle.
-         *
-         * @interface Highcharts.RectangleObject
-         */ /**
-        * Height of the rectangle.
-        * @name Highcharts.RectangleObject#height
-        * @type {number}
-        */ /**
-        * Width of the rectangle.
-        * @name Highcharts.RectangleObject#width
-        * @type {number}
-        */ /**
-        * Horizontal position of the rectangle.
-        * @name Highcharts.RectangleObject#x
-        * @type {number}
-        */ /**
-        * Vertical position of the rectangle.
-        * @name Highcharts.RectangleObject#y
-        * @type {number}
-        */
-        /**
-         * The shadow options.
-         *
-         * @interface Highcharts.ShadowOptionsObject
-         */ /**
-        * The shadow color.
-        * @name    Highcharts.ShadowOptionsObject#color
-        * @type    {Highcharts.ColorString|undefined}
-        * @default #000000
-        */ /**
-        * The horizontal offset from the element.
-        *
-        * @name    Highcharts.ShadowOptionsObject#offsetX
-        * @type    {number|undefined}
-        * @default 1
-        */ /**
-        * The vertical offset from the element.
-        * @name    Highcharts.ShadowOptionsObject#offsetY
-        * @type    {number|undefined}
-        * @default 1
-        */ /**
-        * The shadow opacity.
-        *
-        * @name    Highcharts.ShadowOptionsObject#opacity
-        * @type    {number|undefined}
-        * @default 0.15
-        */ /**
-        * The shadow width or distance from the element.
-        * @name    Highcharts.ShadowOptionsObject#width
-        * @type    {number|undefined}
-        * @default 3
-        */
-        /**
-         * @interface Highcharts.SizeObject
-         */ /**
-        * @name Highcharts.SizeObject#height
-        * @type {number}
-        */ /**
-        * @name Highcharts.SizeObject#width
-        * @type {number}
-        */
+         * @fires Highcharts.Axis#event:afterSetOptions
+         */
+        Axis.prototype.setOptions = function (userOptions) {
+          this.options = merge(
+            Axis.defaultOptions,
+            this.coll === "yAxis" && Axis.defaultYAxisOptions,
+            [
+              Axis.defaultTopAxisOptions,
+              Axis.defaultRightAxisOptions,
+              Axis.defaultBottomAxisOptions,
+              Axis.defaultLeftAxisOptions,
+            ][this.side],
+            merge(
+              // if set in setOptions (#1053):
+              defaultOptions[this.coll],
+              userOptions
+            )
+          );
+          fireEvent(this, "afterSetOptions", { userOptions: userOptions });
+        };
         /**
-         * Serialized form of an SVG definition, including children. Some key
-         * property names are reserved: tagName, textContent, and children.
+         * The default label formatter. The context is a special config object for
+         * the label. In apps, use the
+         * [labels.formatter](https://api.highcharts.com/highcharts/xAxis.labels.formatter)
+         * instead, except when a modification is needed.
          *
-         * @interface Highcharts.SVGDefinitionObject
-         */ /**
-        * @name Highcharts.SVGDefinitionObject#[key:string]
-        * @type {boolean|number|string|Array<Highcharts.SVGDefinitionObject>|undefined}
-        */ /**
-        * @name Highcharts.SVGDefinitionObject#children
-        * @type {Array<Highcharts.SVGDefinitionObject>|undefined}
-        */ /**
-        * @name Highcharts.SVGDefinitionObject#tagName
-        * @type {string|undefined}
-        */ /**
-        * @name Highcharts.SVGDefinitionObject#textContent
-        * @type {string|undefined}
-        */
-        /**
-         * Array of path commands, that will go into the `d` attribute of an SVG
-         * element.
+         * @function Highcharts.Axis#defaultLabelFormatter
          *
-         * @typedef {Array<(Array<Highcharts.SVGPathCommand>|Array<Highcharts.SVGPathCommand,number>|Array<Highcharts.SVGPathCommand,number,number>|Array<Highcharts.SVGPathCommand,number,number,number,number>|Array<Highcharts.SVGPathCommand,number,number,number,number,number,number>|Array<Highcharts.SVGPathCommand,number,number,number,number,number,number,number>)>} Highcharts.SVGPathArray
-         */
+         * @param {Highcharts.AxisLabelsFormatterContextObject<number>|Highcharts.AxisLabelsFormatterContextObject<string>} this
+         * Formatter context of axis label.
+         *
+         * @return {string}
+         * The formatted label content.
+         */
+        Axis.prototype.defaultLabelFormatter = function () {
+          var axis = this.axis,
+            value = isNumber(this.value) ? this.value : NaN,
+            time = axis.chart.time,
+            categories = axis.categories,
+            dateTimeLabelFormat = this.dateTimeLabelFormat,
+            lang = defaultOptions.lang,
+            numericSymbols = lang.numericSymbols,
+            numSymMagnitude = lang.numericSymbolMagnitude || 1000,
+            i = numericSymbols && numericSymbols.length,
+            multi,
+            ret,
+            formatOption = axis.options.labels.format,
+            // make sure the same symbol is added for all labels on a linear
+            // axis
+            numericSymbolDetector = axis.logarithmic
+              ? Math.abs(value)
+              : axis.tickInterval;
+          var chart = this.chart;
+          var numberFormatter = chart.numberFormatter;
+          if (formatOption) {
+            ret = format(formatOption, this, chart);
+          } else if (categories) {
+            ret = "" + this.value;
+          } else if (dateTimeLabelFormat) {
+            // datetime axis
+            ret = time.dateFormat(dateTimeLabelFormat, value);
+          } else if (i && numericSymbolDetector >= 1000) {
+            // Decide whether we should add a numeric symbol like k (thousands)
+            // or M (millions). If we are to enable this in tooltip or other
+            // places as well, we can move this logic to the numberFormatter and
+            // enable it by a parameter.
+            while (i-- && typeof ret === "undefined") {
+              multi = Math.pow(numSymMagnitude, i + 1);
+              if (
+                // Only accept a numeric symbol when the distance is more
+                // than a full unit. So for example if the symbol is k, we
+                // don't accept numbers like 0.5k.
+                numericSymbolDetector >= multi &&
+                // Accept one decimal before the symbol. Accepts 0.5k but
+                // not 0.25k. How does this work with the previous?
+                (value * 10) % multi === 0 &&
+                numericSymbols[i] !== null &&
+                value !== 0
+              ) {
+                // #5480
+                ret = numberFormatter(value / multi, -1) + numericSymbols[i];
+              }
+            }
+          }
+          if (typeof ret === "undefined") {
+            if (Math.abs(value) >= 10000) {
+              // add thousands separators
+              ret = numberFormatter(value, -1);
+            } else {
+              // small numbers
+              ret = numberFormatter(value, -1, void 0, ""); // #2466
+            }
+          }
+          return ret;
+        };
         /**
-         * Possible path commands in an SVG path array. Valid values are `A`, `C`, `H`,
-         * `L`, `M`, `Q`, `S`, `T`, `V`, `Z`.
+         * Get the minimum and maximum for the series of each axis. The function
+         * analyzes the axis series and updates `this.dataMin` and `this.dataMax`.
          *
-         * @typedef {string} Highcharts.SVGPathCommand
-         * @validvalue ["a","c","h","l","m","q","s","t","v","z","A","C","H","L","M","Q","S","T","V","Z"]
-         */
+         * @private
+         * @function Highcharts.Axis#getSeriesExtremes
+         *
+         * @fires Highcharts.Axis#event:afterGetSeriesExtremes
+         * @fires Highcharts.Axis#event:getSeriesExtremes
+         */
+        Axis.prototype.getSeriesExtremes = function () {
+          var axis = this,
+            chart = axis.chart,
+            xExtremes;
+          fireEvent(this, "getSeriesExtremes", null, function () {
+            axis.hasVisibleSeries = false;
+            // Reset properties in case we're redrawing (#3353)
+            axis.dataMin = axis.dataMax = axis.threshold = null;
+            axis.softThreshold = !axis.isXAxis;
+            if (axis.stacking) {
+              axis.stacking.buildStacks();
+            }
+            // loop through this axis' series
+            axis.series.forEach(function (series) {
+              if (series.visible || !chart.options.chart.ignoreHiddenSeries) {
+                var seriesOptions = series.options,
+                  xData,
+                  threshold = seriesOptions.threshold,
+                  seriesDataMin,
+                  seriesDataMax;
+                axis.hasVisibleSeries = true;
+                // Validate threshold in logarithmic axes
+                if (axis.positiveValuesOnly && threshold <= 0) {
+                  threshold = null;
+                }
+                // Get dataMin and dataMax for X axes
+                if (axis.isXAxis) {
+                  xData = series.xData;
+                  if (xData.length) {
+                    var isPositive = function (number) {
+                      return number > 0;
+                    };
+                    xData = axis.logarithmic
+                      ? xData.filter(axis.validatePositiveValue)
+                      : xData;
+                    xExtremes = series.getXExtremes(xData);
+                    // If xData contains values which is not numbers,
+                    // then filter them out. To prevent performance hit,
+                    // we only do this after we have already found
+                    // seriesDataMin because in most cases all data is
+                    // valid. #5234.
+                    seriesDataMin = xExtremes.min;
+                    seriesDataMax = xExtremes.max;
+                    if (
+                      !isNumber(seriesDataMin) &&
+                      // #5010:
+                      !(seriesDataMin instanceof Date)
+                    ) {
+                      xData = xData.filter(isNumber);
+                      xExtremes = series.getXExtremes(xData);
+                      // Do it again with valid data
+                      seriesDataMin = xExtremes.min;
+                      seriesDataMax = xExtremes.max;
+                    }
+                    if (xData.length) {
+                      axis.dataMin = Math.min(
+                        pick(axis.dataMin, seriesDataMin),
+                        seriesDataMin
+                      );
+                      axis.dataMax = Math.max(
+                        pick(axis.dataMax, seriesDataMax),
+                        seriesDataMax
+                      );
+                    }
+                  }
+                  // Get dataMin and dataMax for Y axes, as well as handle
+                  // stacking and processed data
+                } else {
+                  // Get this particular series extremes
+                  var dataExtremes = series.applyExtremes();
+                  // Get the dataMin and dataMax so far. If percentage is
+                  // used, the min and max are always 0 and 100. If
+                  // seriesDataMin and seriesDataMax is null, then series
+                  // doesn't have active y data, we continue with nulls
+                  if (isNumber(dataExtremes.dataMin)) {
+                    seriesDataMin = dataExtremes.dataMin;
+                    axis.dataMin = Math.min(
+                      pick(axis.dataMin, seriesDataMin),
+                      seriesDataMin
+                    );
+                  }
+                  if (isNumber(dataExtremes.dataMax)) {
+                    seriesDataMax = dataExtremes.dataMax;
+                    axis.dataMax = Math.max(
+                      pick(axis.dataMax, seriesDataMax),
+                      seriesDataMax
+                    );
+                  }
+                  // Adjust to threshold
+                  if (defined(threshold)) {
+                    axis.threshold = threshold;
+                  }
+                  // If any series has a hard threshold, it takes
+                  // precedence
+                  if (!seriesOptions.softThreshold || axis.positiveValuesOnly) {
+                    axis.softThreshold = false;
+                  }
+                }
+              }
+            });
+          });
+          fireEvent(this, "afterGetSeriesExtremes");
+        };
         /**
-         * An extendable collection of functions for defining symbol paths. Symbols are
-         * used internally for point markers, button and label borders and backgrounds,
-         * or custom shapes. Extendable by adding to {@link SVGRenderer#symbols}.
+         * Translate from axis value to pixel position on the chart, or back. Use
+         * the `toPixels` and `toValue` functions in applications.
          *
-         * @interface Highcharts.SymbolDictionary
-         */ /**
-        * @name Highcharts.SymbolDictionary#[key:string]
-        * @type {Function|undefined}
-        */ /**
-        * @name Highcharts.SymbolDictionary#arc
-        * @type {Function|undefined}
-        */ /**
-        * @name Highcharts.SymbolDictionary#callout
-        * @type {Function|undefined}
-        */ /**
-        * @name Highcharts.SymbolDictionary#circle
-        * @type {Function|undefined}
-        */ /**
-        * @name Highcharts.SymbolDictionary#diamond
-        * @type {Function|undefined}
-        */ /**
-        * @name Highcharts.SymbolDictionary#square
-        * @type {Function|undefined}
-        */ /**
-        * @name Highcharts.SymbolDictionary#triangle
-        * @type {Function|undefined}
-        */
-        /**
-         * Can be one of `arc`, `callout`, `circle`, `diamond`, `square`, `triangle`,
-         * and `triangle-down`. Symbols are used internally for point markers, button
-         * and label borders and backgrounds, or custom shapes. Extendable by adding to
-         * {@link SVGRenderer#symbols}.
+         * @private
+         * @function Highcharts.Axis#translate
+         *
+         * @param {number} val
+         * TO-DO: parameter description
+         *
+         * @param {boolean|null} [backwards]
+         * TO-DO: parameter description
+         *
+         * @param {boolean|null} [cvsCoord]
+         * TO-DO: parameter description
+         *
+         * @param {boolean|null} [old]
+         * TO-DO: parameter description
+         *
+         * @param {boolean} [handleLog]
+         * TO-DO: parameter description
+         *
+         * @param {number} [pointPlacement]
+         * TO-DO: parameter description
+         *
+         * @return {number|undefined}
+         */
+        Axis.prototype.translate = function (
+          val,
+          backwards,
+          cvsCoord,
+          old,
+          handleLog,
+          pointPlacement
+        ) {
+          var axis = this.linkedParent || this, // #1417
+            sign = 1,
+            cvsOffset = 0,
+            localA = old ? axis.oldTransA : axis.transA,
+            localMin = old ? axis.oldMin : axis.min,
+            returnValue = 0,
+            minPixelPadding = axis.minPixelPadding,
+            doPostTranslate =
+              (axis.isOrdinal ||
+                (axis.brokenAxis && axis.brokenAxis.hasBreaks) ||
+                (axis.logarithmic && handleLog)) &&
+              axis.lin2val;
+          if (!localA) {
+            localA = axis.transA;
+          }
+          // In vertical axes, the canvas coordinates start from 0 at the top like
+          // in SVG.
+          if (cvsCoord) {
+            sign *= -1; // canvas coordinates inverts the value
+            cvsOffset = axis.len;
+          }
+          // Handle reversed axis
+          if (axis.reversed) {
+            sign *= -1;
+            cvsOffset -= sign * (axis.sector || axis.len);
+          }
+          // From pixels to value
+          if (backwards) {
+            // reverse translation
+            val = val * sign + cvsOffset;
+            val -= minPixelPadding;
+            // from chart pixel to value:
+            returnValue = val / localA + localMin;
+            if (doPostTranslate) {
+              // log and ordinal axes
+              returnValue = axis.lin2val(returnValue);
+            }
+            // From value to pixels
+          } else {
+            if (doPostTranslate) {
+              // log and ordinal axes
+              val = axis.val2lin(val);
+            }
+            returnValue = isNumber(localMin)
+              ? sign * (val - localMin) * localA +
+                cvsOffset +
+                sign * minPixelPadding +
+                (isNumber(pointPlacement) ? localA * pointPlacement : 0)
+              : void 0;
+          }
+          return returnValue;
+        };
+        /**
+         * Translate a value in terms of axis units into pixels within the chart.
+         *
+         * @function Highcharts.Axis#toPixels
          *
-         * @typedef {"arc"|"callout"|"circle"|"diamond"|"square"|"triangle"|"triangle-down"} Highcharts.SymbolKeyValue
+         * @param {number} value
+         * A value in terms of axis units.
+         *
+         * @param {boolean} paneCoordinates
+         * Whether to return the pixel coordinate relative to the chart or just the
+         * axis/pane itself.
+         *
+         * @return {number}
+         * Pixel position of the value on the chart or axis.
          */
+        Axis.prototype.toPixels = function (value, paneCoordinates) {
+          return (
+            this.translate(value, false, !this.horiz, null, true) +
+            (paneCoordinates ? 0 : this.pos)
+          );
+        };
         /**
-         * Additional options, depending on the actual symbol drawn.
+         * Translate a pixel position along the axis to a value in terms of axis
+         * units.
          *
-         * @interface Highcharts.SymbolOptionsObject
-         */ /**
-        * The anchor X position for the `callout` symbol. This is where the chevron
-        * points to.
-        *
-        * @name Highcharts.SymbolOptionsObject#anchorX
-        * @type {number|undefined}
-        */ /**
-        * The anchor Y position for the `callout` symbol. This is where the chevron
-        * points to.
-        *
-        * @name Highcharts.SymbolOptionsObject#anchorY
-        * @type {number|undefined}
-        */ /**
-        * The end angle of an `arc` symbol.
-        *
-        * @name Highcharts.SymbolOptionsObject#end
-        * @type {number|undefined}
-        */ /**
-        * Whether to draw `arc` symbol open or closed.
-        *
-        * @name Highcharts.SymbolOptionsObject#open
-        * @type {boolean|undefined}
-        */ /**
-        * The radius of an `arc` symbol, or the border radius for the `callout` symbol.
-        *
-        * @name Highcharts.SymbolOptionsObject#r
-        * @type {number|undefined}
-        */ /**
-        * The start angle of an `arc` symbol.
-        *
-        * @name Highcharts.SymbolOptionsObject#start
-        * @type {number|undefined}
-        */
-        /* eslint-disable no-invalid-this, valid-jsdoc */
-        var charts = H.charts,
-            deg2rad = H.deg2rad,
-            doc = H.doc,
-            isFirefox = H.isFirefox,
-            isMS = H.isMS,
-            isWebKit = H.isWebKit,
-            noop = H.noop,
-            svg = H.svg,
-            SVG_NS = H.SVG_NS,
-            symbolSizes = H.symbolSizes,
-            win = H.win;
-        /**
-         * Allows direct access to the Highcharts rendering layer in order to draw
-         * primitive shapes like circles, rectangles, paths or text directly on a chart,
-         * or independent from any chart. The SVGRenderer represents a wrapper object
-         * for SVG in modern browsers. Through the VMLRenderer, part of the `oldie.js`
-         * module, it also brings vector graphics to IE <= 8.
-         *
-         * An existing chart's renderer can be accessed through {@link Chart.renderer}.
-         * The renderer can also be used completely decoupled from a chart.
-         *
-         * @sample highcharts/members/renderer-on-chart
-         *         Annotating a chart programmatically.
-         * @sample highcharts/members/renderer-basic
-         *         Independent SVG drawing.
+         * @function Highcharts.Axis#toValue
          *
-         * @example
-         * // Use directly without a chart object.
-         * var renderer = new Highcharts.Renderer(parentNode, 600, 400);
+         * @param {number} pixel
+         * The pixel value coordinate.
          *
-         * @class
-         * @name Highcharts.SVGRenderer
+         * @param {boolean} [paneCoordinates=false]
+         * Whether the input pixel is relative to the chart or just the axis/pane
+         * itself.
          *
-         * @param {Highcharts.HTMLDOMElement} container
-         *        Where to put the SVG in the web page.
+         * @return {number}
+         * The axis value.
+         */
+        Axis.prototype.toValue = function (pixel, paneCoordinates) {
+          return this.translate(
+            pixel - (paneCoordinates ? 0 : this.pos),
+            true,
+            !this.horiz,
+            null,
+            true
+          );
+        };
+        /**
+         * Create the path for a plot line that goes from the given value on
+         * this axis, across the plot to the opposite side. Also used internally for
+         * grid lines and crosshairs.
+         *
+         * @function Highcharts.Axis#getPlotLinePath
+         *
+         * @param {Highcharts.AxisPlotLinePathOptionsObject} options
+         * Options for the path.
+         *
+         * @return {Highcharts.SVGPathArray|null}
+         * The SVG path definition for the plot line.
+         */
+        Axis.prototype.getPlotLinePath = function (options) {
+          var axis = this,
+            chart = axis.chart,
+            axisLeft = axis.left,
+            axisTop = axis.top,
+            old = options.old,
+            value = options.value,
+            translatedValue = options.translatedValue,
+            lineWidth = options.lineWidth,
+            force = options.force,
+            x1,
+            y1,
+            x2,
+            y2,
+            cHeight = (old && chart.oldChartHeight) || chart.chartHeight,
+            cWidth = (old && chart.oldChartWidth) || chart.chartWidth,
+            skip,
+            transB = axis.transB,
+            evt;
+          // eslint-disable-next-line valid-jsdoc
+          /**
+           * Check if x is between a and b. If not, either move to a/b
+           * or skip, depending on the force parameter.
+           * @private
+           */
+          function between(x, a, b) {
+            if ((force !== "pass" && x < a) || x > b) {
+              if (force) {
+                x = clamp(x, a, b);
+              } else {
+                skip = true;
+              }
+            }
+            return x;
+          }
+          evt = {
+            value: value,
+            lineWidth: lineWidth,
+            old: old,
+            force: force,
+            acrossPanes: options.acrossPanes,
+            translatedValue: translatedValue,
+          };
+          fireEvent(this, "getPlotLinePath", evt, function (e) {
+            translatedValue = pick(
+              translatedValue,
+              axis.translate(value, null, null, old)
+            );
+            // Keep the translated value within sane bounds, and avoid Infinity
+            // to fail the isNumber test (#7709).
+            translatedValue = clamp(translatedValue, -1e5, 1e5);
+            x1 = x2 = Math.round(translatedValue + transB);
+            y1 = y2 = Math.round(cHeight - translatedValue - transB);
+            if (!isNumber(translatedValue)) {
+              // no min or max
+              skip = true;
+              force = false; // #7175, don't force it when path is invalid
+            } else if (axis.horiz) {
+              y1 = axisTop;
+              y2 = cHeight - axis.bottom;
+              x1 = x2 = between(x1, axisLeft, axisLeft + axis.width);
+            } else {
+              x1 = axisLeft;
+              x2 = cWidth - axis.right;
+              y1 = y2 = between(y1, axisTop, axisTop + axis.height);
+            }
+            e.path =
+              skip && !force
+                ? null
+                : chart.renderer.crispLine(
+                    [
+                      ["M", x1, y1],
+                      ["L", x2, y2],
+                    ],
+                    lineWidth || 1
+                  );
+          });
+          return evt.path;
+        };
+        /**
+         * Internal function to et the tick positions of a linear axis to round
+         * values like whole tens or every five.
+         *
+         * @function Highcharts.Axis#getLinearTickPositions
+         *
+         * @param {number} tickInterval
+         * The normalized tick interval.
+         *
+         * @param {number} min
+         * Axis minimum.
+         *
+         * @param {number} max
+         * Axis maximum.
+         *
+         * @return {Array<number>}
+         * An array of axis values where ticks should be placed.
+         */
+        Axis.prototype.getLinearTickPositions = function (
+          tickInterval,
+          min,
+          max
+        ) {
+          var pos,
+            lastPos,
+            roundedMin = correctFloat(
+              Math.floor(min / tickInterval) * tickInterval
+            ),
+            roundedMax = correctFloat(
+              Math.ceil(max / tickInterval) * tickInterval
+            ),
+            tickPositions = [],
+            precision;
+          // When the precision is higher than what we filter out in
+          // correctFloat, skip it (#6183).
+          if (correctFloat(roundedMin + tickInterval) === roundedMin) {
+            precision = 20;
+          }
+          // For single points, add a tick regardless of the relative position
+          // (#2662, #6274)
+          if (this.single) {
+            return [min];
+          }
+          // Populate the intermediate values
+          pos = roundedMin;
+          while (pos <= roundedMax) {
+            // Place the tick on the rounded value
+            tickPositions.push(pos);
+            // Always add the raw tickInterval, not the corrected one.
+            pos = correctFloat(pos + tickInterval, precision);
+            // If the interval is not big enough in the current min - max range
+            // to actually increase the loop variable, we need to break out to
+            // prevent endless loop. Issue #619
+            if (pos === lastPos) {
+              break;
+            }
+            // Record the last value
+            lastPos = pos;
+          }
+          return tickPositions;
+        };
+        /**
+         * Resolve the new minorTicks/minorTickInterval options into the legacy
+         * loosely typed minorTickInterval option.
          *
-         * @param {number} width
-         *        The width of the SVG.
+         * @function Highcharts.Axis#getMinorTickInterval
          *
-         * @param {number} height
-         *        The height of the SVG.
+         * @return {number|"auto"|null}
+         */
+        Axis.prototype.getMinorTickInterval = function () {
+          var options = this.options;
+          if (options.minorTicks === true) {
+            return pick(options.minorTickInterval, "auto");
+          }
+          if (options.minorTicks === false) {
+            return null;
+          }
+          return options.minorTickInterval;
+        };
+        /**
+         * Internal function to return the minor tick positions. For logarithmic
+         * axes, the same logic as for major ticks is reused.
+         *
+         * @function Highcharts.Axis#getMinorTickPositions
+         *
+         * @return {Array<number>}
+         * An array of axis values where ticks should be placed.
+         */
+        Axis.prototype.getMinorTickPositions = function () {
+          var axis = this,
+            options = axis.options,
+            tickPositions = axis.tickPositions,
+            minorTickInterval = axis.minorTickInterval,
+            minorTickPositions = [],
+            pos,
+            pointRangePadding = axis.pointRangePadding || 0,
+            min = axis.min - pointRangePadding, // #1498
+            max = axis.max + pointRangePadding, // #1498
+            range = max - min;
+          // If minor ticks get too dense, they are hard to read, and may cause
+          // long running script. So we don't draw them.
+          if (range && range / minorTickInterval < axis.len / 3) {
+            // #3875
+            var logarithmic_1 = axis.logarithmic;
+            if (logarithmic_1) {
+              // For each interval in the major ticks, compute the minor ticks
+              // separately.
+              this.paddedTicks.forEach(function (_pos, i, paddedTicks) {
+                if (i) {
+                  minorTickPositions.push.apply(
+                    minorTickPositions,
+                    logarithmic_1.getLogTickPositions(
+                      minorTickInterval,
+                      paddedTicks[i - 1],
+                      paddedTicks[i],
+                      true
+                    )
+                  );
+                }
+              });
+            } else if (
+              axis.dateTime &&
+              this.getMinorTickInterval() === "auto"
+            ) {
+              // #1314
+              minorTickPositions = minorTickPositions.concat(
+                axis.getTimeTicks(
+                  axis.dateTime.normalizeTimeTickInterval(minorTickInterval),
+                  min,
+                  max,
+                  options.startOfWeek
+                )
+              );
+            } else {
+              for (
+                pos = min + ((tickPositions[0] - min) % minorTickInterval);
+                pos <= max;
+                pos += minorTickInterval
+              ) {
+                // Very, very, tight grid lines (#5771)
+                if (pos === minorTickPositions[0]) {
+                  break;
+                }
+                minorTickPositions.push(pos);
+              }
+            }
+          }
+          if (minorTickPositions.length !== 0) {
+            axis.trimTicks(minorTickPositions); // #3652 #3743 #1498 #6330
+          }
+          return minorTickPositions;
+        };
+        /**
+         * Adjust the min and max for the minimum range. Keep in mind that the
+         * series data is not yet processed, so we don't have information on data
+         * cropping and grouping, or updated `axis.pointRange` or
+         * `series.pointRange`. The data can't be processed until we have finally
+         * established min and max.
          *
-         * @param {Highcharts.CSSObject} [style]
-         *        The box style, if not in styleMode
+         * @private
+         * @function Highcharts.Axis#adjustForMinRange
+         */
+        Axis.prototype.adjustForMinRange = function () {
+          var axis = this,
+            options = axis.options,
+            min = axis.min,
+            max = axis.max,
+            log = axis.logarithmic,
+            zoomOffset,
+            spaceAvailable,
+            closestDataRange,
+            i,
+            distance,
+            xData,
+            loopLength,
+            minArgs,
+            maxArgs,
+            minRange;
+          // Set the automatic minimum range based on the closest point distance
+          if (axis.isXAxis && typeof axis.minRange === "undefined" && !log) {
+            if (defined(options.min) || defined(options.max)) {
+              axis.minRange = null; // don't do this again
+            } else {
+              // Find the closest distance between raw data points, as opposed
+              // to closestPointRange that applies to processed points
+              // (cropped and grouped)
+              axis.series.forEach(function (series) {
+                xData = series.xData;
+                loopLength = series.xIncrement ? 1 : xData.length - 1;
+                for (i = loopLength; i > 0; i--) {
+                  distance = xData[i] - xData[i - 1];
+                  if (
+                    typeof closestDataRange === "undefined" ||
+                    distance < closestDataRange
+                  ) {
+                    closestDataRange = distance;
+                  }
+                }
+              });
+              axis.minRange = Math.min(
+                closestDataRange * 5,
+                axis.dataMax - axis.dataMin
+              );
+            }
+          }
+          // if minRange is exceeded, adjust
+          if (max - min < axis.minRange) {
+            spaceAvailable = axis.dataMax - axis.dataMin >= axis.minRange;
+            minRange = axis.minRange;
+            zoomOffset = (minRange - max + min) / 2;
+            // if min and max options have been set, don't go beyond it
+            minArgs = [min - zoomOffset, pick(options.min, min - zoomOffset)];
+            // If space is available, stay within the data range
+            if (spaceAvailable) {
+              minArgs[2] = axis.logarithmic
+                ? axis.logarithmic.log2lin(axis.dataMin)
+                : axis.dataMin;
+            }
+            min = arrayMax(minArgs);
+            maxArgs = [min + minRange, pick(options.max, min + minRange)];
+            // If space is availabe, stay within the data range
+            if (spaceAvailable) {
+              maxArgs[2] = log ? log.log2lin(axis.dataMax) : axis.dataMax;
+            }
+            max = arrayMin(maxArgs);
+            // now if the max is adjusted, adjust the min back
+            if (max - min < minRange) {
+              minArgs[0] = max - minRange;
+              minArgs[1] = pick(options.min, max - minRange);
+              min = arrayMax(minArgs);
+            }
+          }
+          // Record modified extremes
+          axis.min = min;
+          axis.max = max;
+        };
+        // eslint-disable-next-line valid-jsdoc
+        /**
+         * Find the closestPointRange across all series.
          *
-         * @param {boolean} [forExport=false]
-         *        Whether the rendered content is intended for export.
+         * @private
+         * @function Highcharts.Axis#getClosest
+         */
+        Axis.prototype.getClosest = function () {
+          var ret;
+          if (this.categories) {
+            ret = 1;
+          } else {
+            this.series.forEach(function (series) {
+              var seriesClosest = series.closestPointRange,
+                visible =
+                  series.visible ||
+                  !series.chart.options.chart.ignoreHiddenSeries;
+              if (
+                !series.noSharedTooltip &&
+                defined(seriesClosest) &&
+                visible
+              ) {
+                ret = defined(ret)
+                  ? Math.min(ret, seriesClosest)
+                  : seriesClosest;
+              }
+            });
+          }
+          return ret;
+        };
+        /**
+         * When a point name is given and no x, search for the name in the existing
+         * categories, or if categories aren't provided, search names or create a
+         * new category (#2522).
+         * @private
+         * @function Highcharts.Axis#nameToX
          *
-         * @param {boolean} [allowHTML=true]
-         *        Whether the renderer is allowed to include HTML text, which will be
-         *        projected on top of the SVG.
+         * @param {Highcharts.Point} point
+         * The point to inspect.
          *
-         * @param {boolean} [styledMode=false]
-         *        Whether the renderer belongs to a chart that is in styled mode.
-         *        If it does, it will avoid setting presentational attributes in
-         *        some cases, but not when set explicitly through `.attr` and `.css`
-         *        etc.
-         */
-        var SVGRenderer = /** @class */ (function () {
-                /* *
-                 *
-                 *  Constructors
-                 *
-                 * */
-                function SVGRenderer(container, width, height, style, forExport, allowHTML, styledMode) {
-                    /* *
-                     *
-                     *  Properties
-                     *
-                     * */
-                    this.alignedObjects = void 0;
-                /**
-                 * The root `svg` node of the renderer.
-                 *
-                 * @name Highcharts.SVGRenderer#box
-                 * @type {Highcharts.SVGDOMElement}
-                 */
-                this.box = void 0;
-                /**
-                 * The wrapper for the root `svg` node of the renderer.
-                 *
-                 * @name Highcharts.SVGRenderer#boxWrapper
-                 * @type {Highcharts.SVGElement}
-                 */
-                this.boxWrapper = void 0;
-                this.cache = void 0;
-                this.cacheKeys = void 0;
-                this.chartIndex = void 0;
-                /**
-                 * A pointer to the `defs` node of the root SVG.
-                 *
-                 * @name Highcharts.SVGRenderer#defs
-                 * @type {Highcharts.SVGElement}
-                 */
-                this.defs = void 0;
-                this.globalAnimation = void 0;
-                this.gradients = void 0;
-                this.height = void 0;
-                this.imgCount = void 0;
-                this.isSVG = void 0;
-                this.style = void 0;
-                /**
-                 * Page url used for internal references.
-                 *
-                 * @private
-                 * @name Highcharts.SVGRenderer#url
-                 * @type {string}
-                 */
-                this.url = void 0;
-                this.width = void 0;
-                this.init(container, width, height, style, forExport, allowHTML, styledMode);
+         * @return {number}
+         * The X value that the point is given.
+         */
+        Axis.prototype.nameToX = function (point) {
+          var explicitCategories = isArray(this.categories),
+            names = explicitCategories ? this.categories : this.names,
+            nameX = point.options.x,
+            x;
+          point.series.requireSorting = false;
+          if (!defined(nameX)) {
+            nameX =
+              this.options.uniqueNames === false
+                ? point.series.autoIncrement()
+                : explicitCategories
+                ? names.indexOf(point.name)
+                : pick(names.keys[point.name], -1);
+          }
+          if (nameX === -1) {
+            // Not found in currenct categories
+            if (!explicitCategories) {
+              x = names.length;
             }
-            /* *
-             *
-             *  Functions
-             *
-             * */
-            /**
-             * Initialize the SVGRenderer. Overridable initializer function that takes
-             * the same parameters as the constructor.
-             *
-             * @function Highcharts.SVGRenderer#init
-             *
-             * @param {Highcharts.HTMLDOMElement} container
-             * Where to put the SVG in the web page.
-             *
-             * @param {number} width
-             * The width of the SVG.
-             *
-             * @param {number} height
-             * The height of the SVG.
-             *
-             * @param {Highcharts.CSSObject} [style]
-             * The box style, if not in styleMode
-             *
-             * @param {boolean} [forExport=false]
-             * Whether the rendered content is intended for export.
-             *
-             * @param {boolean} [allowHTML=true]
-             * Whether the renderer is allowed to include HTML text, which will be
-             * projected on top of the SVG.
-             *
-             * @param {boolean} [styledMode=false]
-             * Whether the renderer belongs to a chart that is in styled mode. If it
-             * does, it will avoid setting presentational attributes in some cases, but
-             * not when set explicitly through `.attr` and `.css` etc.
-             */
-            SVGRenderer.prototype.init = function (container, width, height, style, forExport, allowHTML, styledMode) {
-                var renderer = this,
-                    boxWrapper,
-                    element,
-                    desc;
-                boxWrapper = renderer.createElement('svg')
-                    .attr({
-                    version: '1.1',
-                    'class': 'highcharts-root'
-                });
-                if (!styledMode) {
-                    boxWrapper.css(this.getStyle(style));
-                }
-                element = boxWrapper.element;
-                container.appendChild(element);
-                // Always use ltr on the container, otherwise text-anchor will be
-                // flipped and text appear outside labels, buttons, tooltip etc (#3482)
-                attr(container, 'dir', 'ltr');
-                // For browsers other than IE, add the namespace attribute (#1978)
-                if (container.innerHTML.indexOf('xmlns') === -1) {
-                    attr(element, 'xmlns', this.SVG_NS);
-                }
-                // object properties
-                renderer.isSVG = true;
-                this.box = element;
-                this.boxWrapper = boxWrapper;
-                renderer.alignedObjects = [];
-                // #24, #672, #1070
-                this.url = ((isFirefox || isWebKit) &&
-                    doc.getElementsByTagName('base').length) ?
-                    win.location.href
-                        .split('#')[0] // remove the hash
-                        .replace(/<[^>]*>/g, '') // wing cut HTML
-                        // escape parantheses and quotes
-                        .replace(/([\('\)])/g, '\\$1')
-                        // replace spaces (needed for Safari only)
-                        .replace(/ /g, '%20') :
-                    '';
-                // Add description
-                desc = this.createElement('desc').add();
-                desc.element.appendChild(doc.createTextNode('Created with Highcharts 8.2.2'));
-                renderer.defs = this.createElement('defs').add();
-                renderer.allowHTML = allowHTML;
-                renderer.forExport = forExport;
-                renderer.styledMode = styledMode;
-                renderer.gradients = {}; // Object where gradient SvgElements are stored
-                renderer.cache = {}; // Cache for numerical bounding boxes
-                renderer.cacheKeys = [];
-                renderer.imgCount = 0;
-                renderer.setSize(width, height, false);
-                // Issue 110 workaround:
-                // In Firefox, if a div is positioned by percentage, its pixel position
-                // may land between pixels. The container itself doesn't display this,
-                // but an SVG element inside this container will be drawn at subpixel
-                // precision. In order to draw sharp lines, this must be compensated
-                // for. This doesn't seem to work inside iframes though (like in
-                // jsFiddle).
-                var subPixelFix,
-                    rect;
-                if (isFirefox && container.getBoundingClientRect) {
-                    subPixelFix = function () {
-                        css(container, { left: 0, top: 0 });
-                        rect = container.getBoundingClientRect();
-                        css(container, {
-                            left: (Math.ceil(rect.left) - rect.left) + 'px',
-                            top: (Math.ceil(rect.top) - rect.top) + 'px'
-                        });
-                    };
-                    // run the fix now
-                    subPixelFix();
-                    // run it on resize
-                    renderer.unSubPixelFix = addEvent(win, 'resize', subPixelFix);
+          } else {
+            x = nameX;
+          }
+          // Write the last point's name to the names array
+          if (typeof x !== "undefined") {
+            this.names[x] = point.name;
+            // Backwards mapping is much faster than array searching (#7725)
+            this.names.keys[point.name] = x;
+          }
+          return x;
+        };
+        /**
+         * When changes have been done to series data, update the axis.names.
+         *
+         * @private
+         * @function Highcharts.Axis#updateNames
+         */
+        Axis.prototype.updateNames = function () {
+          var axis = this,
+            names = this.names,
+            i = names.length;
+          if (i > 0) {
+            Object.keys(names.keys).forEach(function (key) {
+              delete names.keys[key];
+            });
+            names.length = 0;
+            this.minRange = this.userMinRange; // Reset
+            (this.series || []).forEach(function (series) {
+              // Reset incrementer (#5928)
+              series.xIncrement = null;
+              // When adding a series, points are not yet generated
+              if (!series.points || series.isDirtyData) {
+                // When we're updating the series with data that is longer
+                // than it was, and cropThreshold is passed, we need to make
+                // sure that the axis.max is increased _before_ running the
+                // premature processData. Otherwise this early iteration of
+                // processData will crop the points to axis.max, and the
+                // names array will be too short (#5857).
+                axis.max = Math.max(axis.max, series.xData.length - 1);
+                series.processData();
+                series.generatePoints();
+              }
+              series.data.forEach(function (point, i) {
+                var x;
+                if (
+                  point &&
+                  point.options &&
+                  typeof point.name !== "undefined" // #9562
+                ) {
+                  x = axis.nameToX(point);
+                  if (typeof x !== "undefined" && x !== point.x) {
+                    point.x = x;
+                    series.xData[i] = x;
+                  }
                 }
-            };
-            /**
-             * General method for adding a definition to the SVG `defs` tag. Can be used
-             * for gradients, fills, filters etc. Styled mode only. A hook for adding
-             * general definitions to the SVG's defs tag. Definitions can be referenced
-             * from the CSS by its `id`. Read more in
-             * [gradients, shadows and patterns](https://www.highcharts.com/docs/chart-design-and-style/gradients-shadows-and-patterns).
-             * Styled mode only.
-             *
-             * @function Highcharts.SVGRenderer#definition
-             *
-             * @param {Highcharts.SVGDefinitionObject} def
-             * A serialized form of an SVG definition, including children.
-             *
-             * @return {Highcharts.SVGElement}
-             * The inserted node.
-             */
-            SVGRenderer.prototype.definition = function (def) {
-                var ren = this;
-                /**
-                 * @private
-                 * @param {Highcharts.SVGDefinitionObject} config - SVG definition
-                 * @param {Highcharts.SVGElement} [parent] - parent node
-                 */
-                function recurse(config, parent) {
-                    var ret;
-                    splat(config).forEach(function (item) {
-                        var node = ren.createElement(item.tagName),
-                            attr = {};
-                        // Set attributes
-                        objectEach(item, function (val, key) {
-                            if (key !== 'tagName' &&
-                                key !== 'children' &&
-                                key !== 'textContent') {
-                                attr[key] = val;
-                            }
-                        });
-                        node.attr(attr);
-                        // Add to the tree
-                        node.add(parent || ren.defs);
-                        // Add text content
-                        if (item.textContent) {
-                            node.element.appendChild(doc.createTextNode(item.textContent));
-                        }
-                        // Recurse
-                        recurse(item.children || [], node);
-                        ret = node;
-                    });
-                    // Return last node added (on top level it's the only one)
-                    return ret;
-                }
-                return recurse(def);
-            };
-            /**
-             * Get the global style setting for the renderer.
-             *
-             * @private
-             * @function Highcharts.SVGRenderer#getStyle
-             *
-             * @param {Highcharts.CSSObject} style
-             * Style settings.
-             *
-             * @return {Highcharts.CSSObject}
-             * The style settings mixed with defaults.
-             */
-            SVGRenderer.prototype.getStyle = function (style) {
-                this.style = extend({
-                    fontFamily: '"Lucida Grande", "Lucida Sans Unicode", ' +
-                        'Arial, Helvetica, sans-serif',
-                    fontSize: '12px'
-                }, style);
-                return this.style;
-            };
-            /**
-             * Apply the global style on the renderer, mixed with the default styles.
-             *
-             * @function Highcharts.SVGRenderer#setStyle
-             *
-             * @param {Highcharts.CSSObject} style
-             * CSS to apply.
-             */
-            SVGRenderer.prototype.setStyle = function (style) {
-                this.boxWrapper.css(this.getStyle(style));
-            };
-            /**
-             * Detect whether the renderer is hidden. This happens when one of the
-             * parent elements has `display: none`. Used internally to detect when we
-             * needto render preliminarily in another div to get the text bounding boxes
-             * right.
-             *
-             * @function Highcharts.SVGRenderer#isHidden
-             *
-             * @return {boolean}
-             * True if it is hidden.
-             */
-            SVGRenderer.prototype.isHidden = function () {
-                return !this.boxWrapper.getBBox().width;
-            };
-            /**
-             * Destroys the renderer and its allocated members.
-             *
-             * @function Highcharts.SVGRenderer#destroy
-             *
-             * @return {null}
-             */
-            SVGRenderer.prototype.destroy = function () {
-                var renderer = this,
-                    rendererDefs = renderer.defs;
-                renderer.box = null;
-                renderer.boxWrapper = renderer.boxWrapper.destroy();
-                // Call destroy on all gradient elements
-                destroyObjectProperties(renderer.gradients || {});
-                renderer.gradients = null;
-                // Defs are null in VMLRenderer
-                // Otherwise, destroy them here.
-                if (rendererDefs) {
-                    renderer.defs = rendererDefs.destroy();
-                }
-                // Remove sub pixel fix handler (#982)
-                if (renderer.unSubPixelFix) {
-                    renderer.unSubPixelFix();
-                }
-                renderer.alignedObjects = null;
-                return null;
-            };
-            /**
-             * Create a wrapper for an SVG element. Serves as a factory for
-             * {@link SVGElement}, but this function is itself mostly called from
-             * primitive factories like {@link SVGRenderer#path}, {@link
-             * SVGRenderer#rect} or {@link SVGRenderer#text}.
-             *
-             * @function Highcharts.SVGRenderer#createElement
-             *
-             * @param {string} nodeName
-             * The node name, for example `rect`, `g` etc.
-             *
-             * @return {Highcharts.SVGElement}
-             * The generated SVGElement.
-             */
-            SVGRenderer.prototype.createElement = function (nodeName) {
-                var wrapper = new this.Element();
-                wrapper.init(this, nodeName);
-                return wrapper;
-            };
-            /**
-             * Get converted radial gradient attributes according to the radial
-             * reference. Used internally from the {@link SVGElement#colorGradient}
-             * function.
-             *
-             * @private
-             * @function Highcharts.SVGRenderer#getRadialAttr
-             */
-            SVGRenderer.prototype.getRadialAttr = function (radialReference, gradAttr) {
-                return {
-                    cx: (radialReference[0] - radialReference[2] / 2) +
-                        gradAttr.cx * radialReference[2],
-                    cy: (radialReference[1] - radialReference[2] / 2) +
-                        gradAttr.cy * radialReference[2],
-                    r: gradAttr.r * radialReference[2]
-                };
-            };
-            /**
-             * Truncate the text node contents to a given length. Used when the css
-             * width is set. If the `textOverflow` is `ellipsis`, the text is truncated
-             * character by character to the given length. If not, the text is
-             * word-wrapped line by line.
-             *
-             * @private
-             * @function Highcharts.SVGRenderer#truncate
-             *
-             * @return {boolean}
-             * True if tspan is too long.
-             */
-            SVGRenderer.prototype.truncate = function (wrapper, tspan, text, words, startAt, width, getString) {
-                var renderer = this,
-                    rotation = wrapper.rotation,
-                    str, 
-                    // Word wrap can not be truncated to shorter than one word, ellipsis
-                    // text can be completely blank.
-                    minIndex = words ? 1 : 0,
-                    maxIndex = (text || words).length,
-                    currentIndex = maxIndex, 
-                    // Cache the lengths to avoid checking the same twice
-                    lengths = [],
-                    updateTSpan = function (s) {
-                        if (tspan.firstChild) {
-                            tspan.removeChild(tspan.firstChild);
-                    }
-                    if (s) {
-                        tspan.appendChild(doc.createTextNode(s));
-                    }
-                }, getSubStringLength = function (charEnd, concatenatedEnd) {
-                    // charEnd is useed when finding the character-by-character
-                    // break for ellipsis, concatenatedEnd is used for word-by-word
-                    // break for word wrapping.
-                    var end = concatenatedEnd || charEnd;
-                    if (typeof lengths[end] === 'undefined') {
-                        // Modern browsers
-                        if (tspan.getSubStringLength) {
-                            // Fails with DOM exception on unit-tests/legend/members
-                            // of unknown reason. Desired width is 0, text content
-                            // is "5" and end is 1.
-                            try {
-                                lengths[end] = startAt +
-                                    tspan.getSubStringLength(0, words ? end + 1 : end);
-                            }
-                            catch (e) {
-                                '';
-                            }
-                            // Legacy
-                        }
-                        else if (renderer.getSpanWidth) { // #9058 jsdom
-                            updateTSpan(getString(text || words, charEnd));
-                            lengths[end] = startAt +
-                                renderer.getSpanWidth(wrapper, tspan);
-                        }
-                    }
-                    return lengths[end];
-                }, actualWidth, truncated;
-                wrapper.rotation = 0; // discard rotation when computing box
-                actualWidth = getSubStringLength(tspan.textContent.length);
-                truncated = startAt + actualWidth > width;
-                if (truncated) {
-                    // Do a binary search for the index where to truncate the text
-                    while (minIndex <= maxIndex) {
-                        currentIndex = Math.ceil((minIndex + maxIndex) / 2);
-                        // When checking words for word-wrap, we need to build the
-                        // string and measure the subStringLength at the concatenated
-                        // word length.
-                        if (words) {
-                            str = getString(words, currentIndex);
-                        }
-                        actualWidth = getSubStringLength(currentIndex, str && str.length - 1);
-                        if (minIndex === maxIndex) {
-                            // Complete
-                            minIndex = maxIndex + 1;
-                        }
-                        else if (actualWidth > width) {
-                            // Too large. Set max index to current.
-                            maxIndex = currentIndex - 1;
-                        }
-                        else {
-                            // Within width. Set min index to current.
-                            minIndex = currentIndex;
-                        }
-                    }
-                    // If max index was 0 it means the shortest possible text was also
-                    // too large. For ellipsis that means only the ellipsis, while for
-                    // word wrap it means the whole first word.
-                    if (maxIndex === 0) {
-                        // Remove ellipsis
-                        updateTSpan('');
-                        // If the new text length is one less than the original, we don't
-                        // need the ellipsis
-                    }
-                    else if (!(text && maxIndex === text.length - 1)) {
-                        updateTSpan(str || getString(text || words, currentIndex));
-                    }
-                }
-                // When doing line wrapping, prepare for the next line by removing the
-                // items from this line.
-                if (words) {
-                    words.splice(0, currentIndex);
-                }
-                wrapper.actualWidth = actualWidth;
-                wrapper.rotation = rotation; // Apply rotation again.
-                return truncated;
-            };
-            /**
-             * Parse a simple HTML string into SVG tspans. Called internally when text
-             * is set on an SVGElement. The function supports a subset of HTML tags, CSS
-             * text features like `width`, `text-overflow`, `white-space`, and also
-             * attributes like `href` and `style`.
-             *
-             * @private
-             * @function Highcharts.SVGRenderer#buildText
-             *
-             * @param {Highcharts.SVGElement} wrapper
-             * The parent SVGElement.
-             */
-            SVGRenderer.prototype.buildText = function (wrapper) {
-                var textNode = wrapper.element, renderer = this, forExport = renderer.forExport, textStr = pick(wrapper.textStr, '').toString(), hasMarkup = textStr.indexOf('<') !== -1, lines, childNodes = textNode.childNodes, truncated, parentX = attr(textNode, 'x'), textStyles = wrapper.styles, width = wrapper.textWidth, textLineHeight = textStyles && textStyles.lineHeight, textOutline = textStyles && textStyles.textOutline, ellipsis = textStyles && textStyles.textOverflow === 'ellipsis', noWrap = textStyles && textStyles.whiteSpace === 'nowrap', fontSize = textStyles && textStyles.fontSize, textCache, isSubsequentLine, i = childNodes.length, tempParent = width && !wrapper.added && this.box, getLineHeight = function (tspan) {
-                        var fontSizeStyle;
-                    if (!renderer.styledMode) {
-                        fontSizeStyle =
-                            /(px|em)$/.test(tspan && tspan.style.fontSize) ?
-                                tspan.style.fontSize :
-                                (fontSize || renderer.style.fontSize || 12);
-                    }
-                    return textLineHeight ?
-                        pInt(textLineHeight) :
-                        renderer.fontMetrics(fontSizeStyle, 
-                        // Get the computed size from parent if not explicit
-                        (tspan.getAttribute('style') ? tspan : textNode)).h;
-                }, unescapeEntities = function (inputStr, except) {
-                    objectEach(renderer.escapes, function (value, key) {
-                        if (!except || except.indexOf(value) === -1) {
-                            inputStr = inputStr.toString().replace(new RegExp(value, 'g'), key);
-                        }
-                    });
-                    return inputStr;
-                }, parseAttribute = function (s, attr) {
-                    var start,
-                        delimiter;
-                    start = s.indexOf('<');
-                    s = s.substring(start, s.indexOf('>') - start);
-                    start = s.indexOf(attr + '=');
-                    if (start !== -1) {
-                        start = start + attr.length + 1;
-                        delimiter = s.charAt(start);
-                        if (delimiter === '"' || delimiter === "'") { // eslint-disable-line quotes
-                            s = s.substring(start + 1);
-                            return s.substring(0, s.indexOf(delimiter));
-                        }
-                    }
-                };
-                var regexMatchBreaks = /<br.*?>/g;
-                // The buildText code is quite heavy, so if we're not changing something
-                // that affects the text, skip it (#6113).
-                textCache = [
-                    textStr,
-                    ellipsis,
-                    noWrap,
-                    textLineHeight,
-                    textOutline,
-                    fontSize,
-                    width
-                ].join(',');
-                if (textCache === wrapper.textCache) {
-                    return;
-                }
-                wrapper.textCache = textCache;
-                // Remove old text
-                while (i--) {
-                    textNode.removeChild(childNodes[i]);
-                }
-                // Skip tspans, add text directly to text node. The forceTSpan is a hook
-                // used in text outline hack.
-                if (!hasMarkup &&
-                    !textOutline &&
-                    !ellipsis &&
-                    !width &&
-                    (textStr.indexOf(' ') === -1 ||
-                        (noWrap && !regexMatchBreaks.test(textStr)))) {
-                    textNode.appendChild(doc.createTextNode(unescapeEntities(textStr)));
-                    // Complex strings, add more logic
-                }
-                else {
-                    if (tempParent) {
-                        // attach it to the DOM to read offset width
-                        tempParent.appendChild(textNode);
-                    }
-                    if (hasMarkup) {
-                        lines = renderer.styledMode ? (textStr
-                            .replace(/<(b|strong)>/g, '<span class="highcharts-strong">')
-                            .replace(/<(i|em)>/g, '<span class="highcharts-emphasized">')) : (textStr
-                            .replace(/<(b|strong)>/g, '<span style="font-weight:bold">')
-                            .replace(/<(i|em)>/g, '<span style="font-style:italic">'));
-                        lines = lines
-                            .replace(/<a/g, '<span')
-                            .replace(/<\/(b|strong|i|em|a)>/g, '</span>')
-                            .split(regexMatchBreaks);
-                    }
-                    else {
-                        lines = [textStr];
-                    }
-                    // Trim empty lines (#5261)
-                    lines = lines.filter(function (line) {
-                        return line !== '';
-                    });
-                    // build the lines
-                    lines.forEach(function (line, lineNo) {
-                        var spans,
-                            spanNo = 0,
-                            lineLength = 0;
-                        line = line
-                            // Trim to prevent useless/costly process on the spaces
-                            // (#5258)
-                            .replace(/^\s+|\s+$/g, '')
-                            .replace(/<span/g, '|||<span')
-                            .replace(/<\/span>/g, '</span>|||');
-                        spans = line.split('|||');
-                        spans.forEach(function buildTextSpans(span) {
-                            if (span !== '' || spans.length === 1) {
-                                var attributes = {},
-                                    tspan = doc.createElementNS(renderer.SVG_NS, 'tspan'),
-                                    a,
-                                    classAttribute,
-                                    styleAttribute, // #390
-                                    hrefAttribute;
-                                classAttribute = parseAttribute(span, 'class');
-                                if (classAttribute) {
-                                    attr(tspan, 'class', classAttribute);
-                                }
-                                styleAttribute = parseAttribute(span, 'style');
-                                if (styleAttribute) {
-                                    styleAttribute = styleAttribute.replace(/(;| |^)color([ :])/, '$1fill$2');
-                                    attr(tspan, 'style', styleAttribute);
-                                }
-                                // For anchors, wrap the tspan in an <a> tag and apply
-                                // the href attribute as is (#13559). Not for export
-                                // (#1529)
-                                hrefAttribute = parseAttribute(span, 'href');
-                                if (hrefAttribute && !forExport) {
-                                    if (
-                                    // Stop JavaScript links, vulnerable to XSS
-                                    hrefAttribute.split(':')[0].toLowerCase()
-                                        .indexOf('javascript') === -1) {
-                                        a = doc.createElementNS(renderer.SVG_NS, 'a');
-                                        attr(a, 'href', hrefAttribute);
-                                        attr(tspan, 'class', 'highcharts-anchor');
-                                        a.appendChild(tspan);
-                                        if (!renderer.styledMode) {
-                                            css(tspan, { cursor: 'pointer' });
-                                        }
-                                    }
-                                }
-                                // Strip away unsupported HTML tags (#7126)
-                                span = unescapeEntities(span.replace(/<[a-zA-Z\/](.|\n)*?>/g, '') || ' ');
-                                // Nested tags aren't supported, and cause crash in
-                                // Safari (#1596)
-                                if (span !== ' ') {
-                                    // add the text node
-                                    tspan.appendChild(doc.createTextNode(span));
-                                    // First span in a line, align it to the left
-                                    if (!spanNo) {
-                                        if (lineNo && parentX !== null) {
-                                            attributes.x = parentX;
-                                        }
-                                    }
-                                    else {
-                                        attributes.dx = 0; // #16
-                                    }
-                                    // add attributes
-                                    attr(tspan, attributes);
-                                    // Append it
-                                    textNode.appendChild(a || tspan);
-                                    // first span on subsequent line, add the line
-                                    // height
-                                    if (!spanNo && isSubsequentLine) {
-                                        // allow getting the right offset height in
-                                        // exporting in IE
-                                        if (!svg && forExport) {
-                                            css(tspan, { display: 'block' });
-                                        }
-                                        // Set the line height based on the font size of
-                                        // either the text element or the tspan element
-                                        attr(tspan, 'dy', getLineHeight(tspan));
-                                    }
-                                    // Check width and apply soft breaks or ellipsis
-                                    if (width) {
-                                        var words = span.replace(/([^\^])-/g, '$1- ').split(' '), // #1273
-                                            hasWhiteSpace = !noWrap && (spans.length > 1 ||
-                                                lineNo ||
-                                                words.length > 1),
-                                            wrapLineNo = 0,
-                                            dy = getLineHeight(tspan);
-                                        if (ellipsis) {
-                                            truncated = renderer.truncate(wrapper, tspan, span, void 0, 0, 
-                                            // Target width
-                                            Math.max(0, 
-                                            // Substract the font face to make
-                                            // room for the ellipsis itself
-                                            width - parseInt(fontSize || 12, 10)), 
-                                            // Build the text to test for
-                                            function (text, currentIndex) {
-                                                return text.substring(0, currentIndex) + '\u2026';
-                                            });
-                                        }
-                                        else if (hasWhiteSpace) {
-                                            while (words.length) {
-                                                // For subsequent lines, create tspans
-                                                // with the same style attributes as the
-                                                // parent text node.
-                                                if (words.length &&
-                                                    !noWrap &&
-                                                    wrapLineNo > 0) {
-                                                    tspan = doc.createElementNS(SVG_NS, 'tspan');
-                                                    attr(tspan, {
-                                                        dy: dy,
-                                                        x: parentX
-                                                    });
-                                                    if (styleAttribute) { // #390
-                                                        attr(tspan, 'style', styleAttribute);
-                                                    }
-                                                    // Start by appending the full
-                                                    // remaining text
-                                                    tspan.appendChild(doc.createTextNode(words.join(' ')
-                                                        .replace(/- /g, '-')));
-                                                    textNode.appendChild(tspan);
-                                                }
-                                                // For each line, truncate the remaining
-                                                // words into the line length.
-                                                renderer.truncate(wrapper, tspan, null, words, wrapLineNo === 0 ? lineLength : 0, width, 
-                                                // Build the text to test for
-                                                function (text, currentIndex) {
-                                                    return words
-                                                        .slice(0, currentIndex)
-                                                        .join(' ')
-                                                        .replace(/- /g, '-');
-                                                });
-                                                lineLength = wrapper.actualWidth;
-                                                wrapLineNo++;
-                                            }
-                                        }
-                                    }
-                                    spanNo++;
-                                }
-                            }
-                        });
-                        // To avoid beginning lines that doesn't add to the textNode
-                        // (#6144)
-                        isSubsequentLine = (isSubsequentLine ||
-                            textNode.childNodes.length);
-                    });
-                    if (ellipsis && truncated) {
-                        wrapper.attr('title', unescapeEntities(wrapper.textStr || '', ['&lt;', '&gt;']) // #7179
-                        );
-                    }
-                    if (tempParent) {
-                        tempParent.removeChild(textNode);
-                    }
-                    // Apply the text outline
-                    if (isString(textOutline) && wrapper.applyTextOutline) {
-                        wrapper.applyTextOutline(textOutline);
-                    }
-                }
-            };
-            /**
-             * Returns white for dark colors and black for bright colors.
-             *
-             * @function Highcharts.SVGRenderer#getContrast
-             *
-             * @param {Highcharts.ColorString} rgba
-             * The color to get the contrast for.
-             *
-             * @return {Highcharts.ColorString}
-             * The contrast color, either `#000000` or `#FFFFFF`.
-             */
-            SVGRenderer.prototype.getContrast = function (rgba) {
-                rgba = Color.parse(rgba).rgba;
-                // The threshold may be discussed. Here's a proposal for adding
-                // different weight to the color channels (#6216)
-                rgba[0] *= 1; // red
-                rgba[1] *= 1.2; // green
-                rgba[2] *= 0.5; // blue
-                return rgba[0] + rgba[1] + rgba[2] >
-                    1.8 * 255 ?
-                    '#000000' :
-                    '#FFFFFF';
-            };
-            /**
-             * Create a button with preset states.
-             *
-             * @function Highcharts.SVGRenderer#button
-             *
-             * @param {string} text
-             * The text or HTML to draw.
-             *
-             * @param {number} x
-             * The x position of the button's left side.
-             *
-             * @param {number} y
-             * The y position of the button's top side.
-             *
-             * @param {Highcharts.EventCallbackFunction<Highcharts.SVGElement>} callback
-             * The function to execute on button click or touch.
-             *
-             * @param {Highcharts.SVGAttributes} [normalState]
-             * SVG attributes for the normal state.
-             *
-             * @param {Highcharts.SVGAttributes} [hoverState]
-             * SVG attributes for the hover state.
-             *
-             * @param {Highcharts.SVGAttributes} [pressedState]
-             * SVG attributes for the pressed state.
-             *
-             * @param {Highcharts.SVGAttributes} [disabledState]
-             * SVG attributes for the disabled state.
-             *
-             * @param {Highcharts.SymbolKeyValue} [shape=rect]
-             * The shape type.
-             *
-             * @param {boolean} [useHTML=false]
-             * Wether to use HTML to render the label.
-             *
-             * @return {Highcharts.SVGElement}
-             * The button element.
-             */
-            SVGRenderer.prototype.button = function (text, x, y, callback, normalState, hoverState, pressedState, disabledState, shape, useHTML) {
-                var label = this.label(text,
-                    x,
-                    y,
-                    shape,
-                    void 0,
-                    void 0,
-                    useHTML,
-                    void 0, 'button'),
-                    curState = 0,
-                    styledMode = this.styledMode, 
-                    // Make a copy of normalState (#13798)
-                    // (reference to options.rangeSelector.buttonTheme)
-                    normalState = normalState ? merge(normalState) : normalState,
-                    userNormalStyle = normalState && normalState.style || {};
-                // Remove stylable attributes
-                if (normalState && normalState.style) {
-                    delete normalState.style;
-                }
-                // Default, non-stylable attributes
-                label.attr(merge({ padding: 8, r: 2 }, normalState));
-                if (!styledMode) {
-                    // Presentational
-                    var normalStyle,
-                        hoverStyle,
-                        pressedStyle,
-                        disabledStyle;
-                    // Normal state - prepare the attributes
-                    normalState = merge({
-                        fill: '#f7f7f7',
-                        stroke: '#cccccc',
-                        'stroke-width': 1,
-                        style: {
-                            color: '#333333',
-                            cursor: 'pointer',
-                            fontWeight: 'normal'
-                        }
-                    }, {
-                        style: userNormalStyle
-                    }, normalState);
-                    normalStyle = normalState.style;
-                    delete normalState.style;
-                    // Hover state
-                    hoverState = merge(normalState, {
-                        fill: '#e6e6e6'
-                    }, hoverState);
-                    hoverStyle = hoverState.style;
-                    delete hoverState.style;
-                    // Pressed state
-                    pressedState = merge(normalState, {
-                        fill: '#e6ebf5',
-                        style: {
-                            color: '#000000',
-                            fontWeight: 'bold'
-                        }
-                    }, pressedState);
-                    pressedStyle = pressedState.style;
-                    delete pressedState.style;
-                    // Disabled state
-                    disabledState = merge(normalState, {
-                        style: {
-                            color: '#cccccc'
-                        }
-                    }, disabledState);
-                    disabledStyle = disabledState.style;
-                    delete disabledState.style;
-                }
-                // Add the events. IE9 and IE10 need mouseover and mouseout to funciton
-                // (#667).
-                addEvent(label.element, isMS ? 'mouseover' : 'mouseenter', function () {
-                    if (curState !== 3) {
-                        label.setState(1);
-                    }
-                });
-                addEvent(label.element, isMS ? 'mouseout' : 'mouseleave', function () {
-                    if (curState !== 3) {
-                        label.setState(curState);
-                    }
-                });
-                label.setState = function (state) {
-                    // Hover state is temporary, don't record it
-                    if (state !== 1) {
-                        label.state = curState = state;
-                    }
-                    // Update visuals
-                    label
-                        .removeClass(/highcharts-button-(normal|hover|pressed|disabled)/)
-                        .addClass('highcharts-button-' +
-                        ['normal', 'hover', 'pressed', 'disabled'][state || 0]);
-                    if (!styledMode) {
-                        label
-                            .attr([
-                            normalState,
-                            hoverState,
-                            pressedState,
-                            disabledState
-                        ][state || 0])
-                            .css([
-                            normalStyle,
-                            hoverStyle,
-                            pressedStyle,
-                            disabledStyle
-                        ][state || 0]);
-                    }
-                };
-                // Presentational attributes
-                if (!styledMode) {
-                    label
-                        .attr(normalState)
-                        .css(extend({ cursor: 'default' }, normalStyle));
-                }
-                return label
-                    .on('click', function (e) {
-                    if (curState !== 3) {
-                        callback.call(label, e);
-                    }
-                });
-            };
-            /**
-             * Make a straight line crisper by not spilling out to neighbour pixels.
-             *
-             * @function Highcharts.SVGRenderer#crispLine
-             *
-             * @param {Highcharts.SVGPathArray} points
-             *        The original points on the format `[['M', 0, 0], ['L', 100, 0]]`.
-             *
-             * @param {number} width
-             *        The width of the line.
-             *
-             * @param {string} roundingFunction
-             *        The rounding function name on the `Math` object, can be one of
-             *        `round`, `floor` or `ceil`.
-             *
-             * @return {Highcharts.SVGPathArray}
-             *         The original points array, but modified to render crisply.
-             */
-            SVGRenderer.prototype.crispLine = function (points, width, roundingFunction) {
-                if (roundingFunction === void 0) { roundingFunction = 'round'; }
-                var start = points[0];
-                var end = points[1];
-                // Normalize to a crisp line
-                if (start[1] === end[1]) {
-                    // Substract due to #1129. Now bottom and left axis gridlines behave
-                    // the same.
-                    start[1] = end[1] =
-                        Math[roundingFunction](start[1]) - (width % 2 / 2);
-                }
-                if (start[2] === end[2]) {
-                    start[2] = end[2] =
-                        Math[roundingFunction](start[2]) + (width % 2 / 2);
-                }
-                return points;
-            };
-            /**
-             * Draw a path, wraps the SVG `path` element.
-             *
-             * @sample highcharts/members/renderer-path-on-chart/
-             *         Draw a path in a chart
-             * @sample highcharts/members/renderer-path/
-             *         Draw a path independent from a chart
-             *
-             * @example
-             * var path = renderer.path(['M', 10, 10, 'L', 30, 30, 'z'])
-             *     .attr({ stroke: '#ff00ff' })
-             *     .add();
-             *
-             * @function Highcharts.SVGRenderer#path
-             *
-             * @param {Highcharts.SVGPathArray} [path]
-             * An SVG path definition in array form.
-             *
-             * @return {Highcharts.SVGElement}
-             * The generated wrapper element.
-             *
-             */ /**
-            * Draw a path, wraps the SVG `path` element.
-            *
-            * @function Highcharts.SVGRenderer#path
-            *
-            * @param {Highcharts.SVGAttributes} [attribs]
-            * The initial attributes.
-            *
-            * @return {Highcharts.SVGElement}
-            * The generated wrapper element.
-            */
-            SVGRenderer.prototype.path = function (path) {
-                var attribs = (this.styledMode ? {} : {
-                        fill: 'none'
-                    });
-                if (isArray(path)) {
-                    attribs.d = path;
-                }
-                else if (isObject(path)) { // attributes
-                    extend(attribs, path);
-                }
-                return this.createElement('path').attr(attribs);
-            };
-            /**
-             * Draw a circle, wraps the SVG `circle` element.
-             *
-             * @sample highcharts/members/renderer-circle/
-             *         Drawing a circle
-             *
-             * @function Highcharts.SVGRenderer#circle
-             *
-             * @param {number} [x]
-             * The center x position.
-             *
-             * @param {number} [y]
-             * The center y position.
-             *
-             * @param {number} [r]
-             * The radius.
-             *
-             * @return {Highcharts.SVGElement}
-             * The generated wrapper element.
-             */ /**
-            * Draw a circle, wraps the SVG `circle` element.
-            *
-            * @function Highcharts.SVGRenderer#circle
-            *
-            * @param {Highcharts.SVGAttributes} [attribs]
-            * The initial attributes.
-            *
-            * @return {Highcharts.SVGElement}
-            * The generated wrapper element.
-            */
-            SVGRenderer.prototype.circle = function (x, y, r) {
-                var attribs = (isObject(x) ?
-                        x :
-                        typeof x === 'undefined' ? {} : { x: x, y: y, r: r }), wrapper = this.createElement('circle');
-                // Setting x or y translates to cx and cy
-                wrapper.xSetter = wrapper.ySetter = function (value, key, element) {
-                    element.setAttribute('c' + key, value);
-                };
-                return wrapper.attr(attribs);
-            };
-            /**
-             * Draw and return an arc.
-             *
-             * @sample highcharts/members/renderer-arc/
-             *         Drawing an arc
-             *
-             * @function Highcharts.SVGRenderer#arc
-             *
-             * @param {number} [x=0]
-             * Center X position.
-             *
-             * @param {number} [y=0]
-             * Center Y position.
-             *
-             * @param {number} [r=0]
-             * The outer radius' of the arc.
-             *
-             * @param {number} [innerR=0]
-             * Inner radius like used in donut charts.
-             *
-             * @param {number} [start=0]
-             * The starting angle of the arc in radians, where 0 is to the right and
-             * `-Math.PI/2` is up.
-             *
-             * @param {number} [end=0]
-             * The ending angle of the arc in radians, where 0 is to the right and
-             * `-Math.PI/2` is up.
-             *
-             * @return {Highcharts.SVGElement}
-             * The generated wrapper element.
-             */ /**
-            * Draw and return an arc. Overloaded function that takes arguments object.
-            *
-            * @function Highcharts.SVGRenderer#arc
-            *
-            * @param {Highcharts.SVGAttributes} attribs
-            * Initial SVG attributes.
-            *
-            * @return {Highcharts.SVGElement}
-            * The generated wrapper element.
-            */
-            SVGRenderer.prototype.arc = function (x, y, r, innerR, start, end) {
-                var arc,
-                    options;
-                if (isObject(x)) {
-                    options = x;
-                    y = options.y;
-                    r = options.r;
-                    innerR = options.innerR;
-                    start = options.start;
-                    end = options.end;
-                    x = options.x;
+              });
+            });
+          }
+        };
+        /**
+         * Update translation information.
+         *
+         * @private
+         * @function Highcharts.Axis#setAxisTranslation
+         *
+         * @param {boolean} [saveOld]
+         * TO-DO: parameter description
+         *
+         * @fires Highcharts.Axis#event:afterSetAxisTranslation
+         */
+        Axis.prototype.setAxisTranslation = function (saveOld) {
+          var axis = this,
+            range = axis.max - axis.min,
+            pointRange = axis.axisPointRange || 0,
+            closestPointRange,
+            minPointOffset = 0,
+            pointRangePadding = 0,
+            linkedParent = axis.linkedParent,
+            ordinalCorrection,
+            hasCategories = !!axis.categories,
+            transA = axis.transA,
+            isXAxis = axis.isXAxis;
+          // Adjust translation for padding. Y axis with categories need to go
+          // through the same (#1784).
+          if (isXAxis || hasCategories || pointRange) {
+            // Get the closest points
+            closestPointRange = axis.getClosest();
+            if (linkedParent) {
+              minPointOffset = linkedParent.minPointOffset;
+              pointRangePadding = linkedParent.pointRangePadding;
+            } else {
+              axis.series.forEach(function (series) {
+                var seriesPointRange = hasCategories
+                    ? 1
+                    : isXAxis
+                    ? pick(series.options.pointRange, closestPointRange, 0)
+                    : axis.axisPointRange || 0, // #2806
+                  pointPlacement = series.options.pointPlacement;
+                pointRange = Math.max(pointRange, seriesPointRange);
+                if (!axis.single || hasCategories) {
+                  // TODO: series should internally set x- and y-
+                  // pointPlacement to simplify this logic.
+                  var isPointPlacementAxis = series.is("xrange")
+                    ? !isXAxis
+                    : isXAxis;
+                  // minPointOffset is the value padding to the left of
+                  // the axis in order to make room for points with a
+                  // pointRange, typically columns. When the
+                  // pointPlacement option is 'between' or 'on', this
+                  // padding does not apply.
+                  minPointOffset = Math.max(
+                    minPointOffset,
+                    isPointPlacementAxis && isString(pointPlacement)
+                      ? 0
+                      : seriesPointRange / 2
+                  );
+                  // Determine the total padding needed to the length of
+                  // the axis to make room for the pointRange. If the
+                  // series' pointPlacement is 'on', no padding is added.
+                  pointRangePadding = Math.max(
+                    pointRangePadding,
+                    isPointPlacementAxis && pointPlacement === "on"
+                      ? 0
+                      : seriesPointRange
+                  );
+                }
+              });
+            }
+            // Record minPointOffset and pointRangePadding
+            ordinalCorrection =
+              axis.ordinal && axis.ordinal.slope && closestPointRange
+                ? axis.ordinal.slope / closestPointRange
+                : 1; // #988, #1853
+            axis.minPointOffset = minPointOffset =
+              minPointOffset * ordinalCorrection;
+            axis.pointRangePadding = pointRangePadding =
+              pointRangePadding * ordinalCorrection;
+            // pointRange means the width reserved for each point, like in a
+            // column chart
+            axis.pointRange = Math.min(
+              pointRange,
+              axis.single && hasCategories ? 1 : range
+            );
+            // closestPointRange means the closest distance between points. In
+            // columns it is mostly equal to pointRange, but in lines pointRange
+            // is 0 while closestPointRange is some other value
+            if (isXAxis) {
+              axis.closestPointRange = closestPointRange;
+            }
+          }
+          // Secondary values
+          if (saveOld) {
+            axis.oldTransA = transA;
+          }
+          axis.translationSlope =
+            axis.transA =
+            transA =
+              axis.staticScale || axis.len / (range + pointRangePadding || 1);
+          // Translation addend
+          axis.transB = axis.horiz ? axis.left : axis.bottom;
+          axis.minPixelPadding = transA * minPointOffset;
+          fireEvent(this, "afterSetAxisTranslation");
+        };
+        /**
+         * @private
+         * @function Highcharts.Axis#minFromRange
+         *
+         * @return {number}
+         */
+        Axis.prototype.minFromRange = function () {
+          var axis = this;
+          return axis.max - axis.range;
+        };
+        /**
+         * Set the tick positions to round values and optionally extend the extremes
+         * to the nearest tick.
+         *
+         * @private
+         * @function Highcharts.Axis#setTickInterval
+         *
+         * @param {boolean} secondPass
+         * TO-DO: parameter description
+         *
+         * @fires Highcharts.Axis#event:foundExtremes
+         */
+        Axis.prototype.setTickInterval = function (secondPass) {
+          var axis = this,
+            chart = axis.chart,
+            log = axis.logarithmic,
+            options = axis.options,
+            isXAxis = axis.isXAxis,
+            isLinked = axis.isLinked,
+            maxPadding = options.maxPadding,
+            minPadding = options.minPadding,
+            length,
+            linkedParentExtremes,
+            tickIntervalOption = options.tickInterval,
+            minTickInterval,
+            tickPixelIntervalOption = options.tickPixelInterval,
+            categories = axis.categories,
+            threshold = isNumber(axis.threshold) ? axis.threshold : null,
+            softThreshold = axis.softThreshold,
+            thresholdMin,
+            thresholdMax,
+            hardMin,
+            hardMax;
+          if (!axis.dateTime && !categories && !isLinked) {
+            this.getTickAmount();
+          }
+          // Min or max set either by zooming/setExtremes or initial options
+          hardMin = pick(axis.userMin, options.min);
+          hardMax = pick(axis.userMax, options.max);
+          // Linked axis gets the extremes from the parent axis
+          if (isLinked) {
+            axis.linkedParent = chart[axis.coll][options.linkedTo];
+            linkedParentExtremes = axis.linkedParent.getExtremes();
+            axis.min = pick(
+              linkedParentExtremes.min,
+              linkedParentExtremes.dataMin
+            );
+            axis.max = pick(
+              linkedParentExtremes.max,
+              linkedParentExtremes.dataMax
+            );
+            if (options.type !== axis.linkedParent.options.type) {
+              // Can't link axes of different type
+              error(11, 1, chart);
+            }
+            // Initial min and max from the extreme data values
+          } else {
+            // Adjust to hard threshold
+            if (softThreshold && defined(threshold)) {
+              if (axis.dataMin >= threshold) {
+                thresholdMin = threshold;
+                minPadding = 0;
+              } else if (axis.dataMax <= threshold) {
+                thresholdMax = threshold;
+                maxPadding = 0;
+              }
+            }
+            axis.min = pick(hardMin, thresholdMin, axis.dataMin);
+            axis.max = pick(hardMax, thresholdMax, axis.dataMax);
+          }
+          if (log) {
+            if (
+              axis.positiveValuesOnly &&
+              !secondPass &&
+              Math.min(axis.min, pick(axis.dataMin, axis.min)) <= 0
+            ) {
+              // #978
+              // Can't plot negative values on log axis
+              error(10, 1, chart);
+            }
+            // The correctFloat cures #934, float errors on full tens. But it
+            // was too aggressive for #4360 because of conversion back to lin,
+            // therefore use precision 15.
+            axis.min = correctFloat(log.log2lin(axis.min), 16);
+            axis.max = correctFloat(log.log2lin(axis.max), 16);
+          }
+          // handle zoomed range
+          if (axis.range && defined(axis.max)) {
+            // #618, #6773:
+            axis.userMin =
+              axis.min =
+              hardMin =
+                Math.max(axis.dataMin, axis.minFromRange());
+            axis.userMax = hardMax = axis.max;
+            axis.range = null; // don't use it when running setExtremes
+          }
+          // Hook for Highstock Scroller. Consider combining with beforePadding.
+          fireEvent(axis, "foundExtremes");
+          // Hook for adjusting this.min and this.max. Used by bubble series.
+          if (axis.beforePadding) {
+            axis.beforePadding();
+          }
+          // adjust min and max for the minimum range
+          axis.adjustForMinRange();
+          // Pad the values to get clear of the chart's edges. To avoid
+          // tickInterval taking the padding into account, we do this after
+          // computing tick interval (#1337).
+          if (
+            !categories &&
+            !axis.axisPointRange &&
+            !(axis.stacking && axis.stacking.usePercentage) &&
+            !isLinked &&
+            defined(axis.min) &&
+            defined(axis.max)
+          ) {
+            length = axis.max - axis.min;
+            if (length) {
+              if (!defined(hardMin) && minPadding) {
+                axis.min -= length * minPadding;
+              }
+              if (!defined(hardMax) && maxPadding) {
+                axis.max += length * maxPadding;
+              }
+            }
+          }
+          // Handle options for floor, ceiling, softMin and softMax (#6359)
+          if (!isNumber(axis.userMin)) {
+            if (isNumber(options.softMin) && options.softMin < axis.min) {
+              axis.min = hardMin = options.softMin; // #6894
+            }
+            if (isNumber(options.floor)) {
+              axis.min = Math.max(axis.min, options.floor);
+            }
+          }
+          if (!isNumber(axis.userMax)) {
+            if (isNumber(options.softMax) && options.softMax > axis.max) {
+              axis.max = hardMax = options.softMax; // #6894
+            }
+            if (isNumber(options.ceiling)) {
+              axis.max = Math.min(axis.max, options.ceiling);
+            }
+          }
+          // When the threshold is soft, adjust the extreme value only if the data
+          // extreme and the padded extreme land on either side of the threshold.
+          // For example, a series of [0, 1, 2, 3] would make the yAxis add a tick
+          // for -1 because of the default minPadding and startOnTick options.
+          // This is prevented by the softThreshold option.
+          if (softThreshold && defined(axis.dataMin)) {
+            threshold = threshold || 0;
+            if (
+              !defined(hardMin) &&
+              axis.min < threshold &&
+              axis.dataMin >= threshold
+            ) {
+              axis.min = axis.options.minRange
+                ? Math.min(threshold, axis.max - axis.minRange)
+                : threshold;
+            } else if (
+              !defined(hardMax) &&
+              axis.max > threshold &&
+              axis.dataMax <= threshold
+            ) {
+              axis.max = axis.options.minRange
+                ? Math.max(threshold, axis.min + axis.minRange)
+                : threshold;
+            }
+          }
+          // get tickInterval
+          if (
+            axis.min === axis.max ||
+            typeof axis.min === "undefined" ||
+            typeof axis.max === "undefined"
+          ) {
+            axis.tickInterval = 1;
+          } else if (
+            isLinked &&
+            !tickIntervalOption &&
+            tickPixelIntervalOption ===
+              axis.linkedParent.options.tickPixelInterval
+          ) {
+            axis.tickInterval = tickIntervalOption =
+              axis.linkedParent.tickInterval;
+          } else {
+            axis.tickInterval = pick(
+              tickIntervalOption,
+              this.tickAmount
+                ? (axis.max - axis.min) / Math.max(this.tickAmount - 1, 1)
+                : void 0,
+              // For categoried axis, 1 is default, for linear axis use
+              // tickPix
+              categories
+                ? 1
+                : // don't let it be more than the data range
+                  ((axis.max - axis.min) * tickPixelIntervalOption) /
+                    Math.max(axis.len, tickPixelIntervalOption)
+            );
+          }
+          // Now we're finished detecting min and max, crop and group series data.
+          // This is in turn needed in order to find tick positions in ordinal
+          // axes.
+          if (isXAxis && !secondPass) {
+            axis.series.forEach(function (series) {
+              series.processData(
+                axis.min !== axis.oldMin || axis.max !== axis.oldMax
+              );
+            });
+          }
+          // set the translation factor used in translate function
+          axis.setAxisTranslation(true);
+          // hook for ordinal axes and radial axes
+          fireEvent(this, "initialAxisTranslation");
+          // In column-like charts, don't cramp in more ticks than there are
+          // points (#1943, #4184)
+          if (axis.pointRange && !tickIntervalOption) {
+            axis.tickInterval = Math.max(axis.pointRange, axis.tickInterval);
+          }
+          // Before normalizing the tick interval, handle minimum tick interval.
+          // This applies only if tickInterval is not defined.
+          minTickInterval = pick(
+            options.minTickInterval,
+            // In datetime axes, don't go below the data interval, except when
+            // there are scatter-like series involved (#13369).
+            axis.dateTime &&
+              !axis.series.some(function (s) {
+                return s.noSharedTooltip;
+              })
+              ? axis.closestPointRange
+              : 0
+          );
+          if (!tickIntervalOption && axis.tickInterval < minTickInterval) {
+            axis.tickInterval = minTickInterval;
+          }
+          // for linear axes, get magnitude and normalize the interval
+          if (!axis.dateTime && !axis.logarithmic && !tickIntervalOption) {
+            axis.tickInterval = normalizeTickInterval(
+              axis.tickInterval,
+              void 0,
+              getMagnitude(axis.tickInterval),
+              pick(
+                options.allowDecimals,
+                // If the tick interval is greather than 0.5, avoid
+                // decimals, as linear axes are often used to render
+                // discrete values. #3363. If a tick amount is set, allow
+                // decimals by default, as it increases the chances for a
+                // good fit.
+                axis.tickInterval < 0.5 || this.tickAmount !== void 0
+              ),
+              !!this.tickAmount
+            );
+          }
+          // Prevent ticks from getting so close that we can't draw the labels
+          if (!this.tickAmount) {
+            axis.tickInterval = axis.unsquish();
+          }
+          this.setTickPositions();
+        };
+        /**
+         * Now we have computed the normalized tickInterval, get the tick positions.
+         *
+         * @private
+         * @function Highcharts.Axis#setTickPositions
+         *
+         * @fires Highcharts.Axis#event:afterSetTickPositions
+         */
+        Axis.prototype.setTickPositions = function () {
+          var axis = this,
+            options = this.options,
+            tickPositions,
+            tickPositionsOption = options.tickPositions,
+            minorTickIntervalOption = this.getMinorTickInterval(),
+            tickPositioner = options.tickPositioner,
+            hasVerticalPanning = this.hasVerticalPanning(),
+            isColorAxis = this.coll === "colorAxis",
+            startOnTick =
+              (isColorAxis || !hasVerticalPanning) && options.startOnTick,
+            endOnTick =
+              (isColorAxis || !hasVerticalPanning) && options.endOnTick;
+          // Set the tickmarkOffset
+          this.tickmarkOffset =
+            this.categories &&
+            options.tickmarkPlacement === "between" &&
+            this.tickInterval === 1
+              ? 0.5
+              : 0; // #3202
+          // get minorTickInterval
+          this.minorTickInterval =
+            minorTickIntervalOption === "auto" && this.tickInterval
+              ? this.tickInterval / 5
+              : minorTickIntervalOption;
+          // When there is only one point, or all points have the same value on
+          // this axis, then min and max are equal and tickPositions.length is 0
+          // or 1. In this case, add some padding in order to center the point,
+          // but leave it with one tick. #1337.
+          this.single =
+            this.min === this.max &&
+            defined(this.min) &&
+            !this.tickAmount &&
+            // Data is on integer (#6563)
+            (parseInt(this.min, 10) === this.min ||
+              // Between integers and decimals are not allowed (#6274)
+              options.allowDecimals !== false);
+          /**
+           * Contains the current positions that are laid out on the axis. The
+           * positions are numbers in terms of axis values. In a category axis
+           * they are integers, in a datetime axis they are also integers, but
+           * designating milliseconds.
+           *
+           * This property is read only - for modifying the tick positions, use
+           * the `tickPositioner` callback or [axis.tickPositions(
+           * https://api.highcharts.com/highcharts/xAxis.tickPositions) option
+           * instead.
+           *
+           * @name Highcharts.Axis#tickPositions
+           * @type {Highcharts.AxisTickPositionsArray|undefined}
+           */
+          this.tickPositions =
+            // Find the tick positions. Work on a copy (#1565)
+            tickPositions = tickPositionsOption && tickPositionsOption.slice();
+          if (!tickPositions) {
+            // Too many ticks (#6405). Create a friendly warning and provide two
+            // ticks so at least we can show the data series.
+            if (
+              (!axis.ordinal || !axis.ordinal.positions) &&
+              (this.max - this.min) / this.tickInterval >
+                Math.max(2 * this.len, 200)
+            ) {
+              tickPositions = [this.min, this.max];
+              error(19, false, this.chart);
+            } else if (axis.dateTime) {
+              tickPositions = axis.getTimeTicks(
+                axis.dateTime.normalizeTimeTickInterval(
+                  this.tickInterval,
+                  options.units
+                ),
+                this.min,
+                this.max,
+                options.startOfWeek,
+                axis.ordinal && axis.ordinal.positions,
+                this.closestPointRange,
+                true
+              );
+            } else if (axis.logarithmic) {
+              tickPositions = axis.logarithmic.getLogTickPositions(
+                this.tickInterval,
+                this.min,
+                this.max
+              );
+            } else {
+              tickPositions = this.getLinearTickPositions(
+                this.tickInterval,
+                this.min,
+                this.max
+              );
+            }
+            // Too dense ticks, keep only the first and last (#4477)
+            if (tickPositions.length > this.len) {
+              tickPositions = [tickPositions[0], tickPositions.pop()];
+              // Reduce doubled value (#7339)
+              if (tickPositions[0] === tickPositions[1]) {
+                tickPositions.length = 1;
+              }
+            }
+            this.tickPositions = tickPositions;
+            // Run the tick positioner callback, that allows modifying auto tick
+            // positions.
+            if (tickPositioner) {
+              tickPositioner = tickPositioner.apply(axis, [this.min, this.max]);
+              if (tickPositioner) {
+                this.tickPositions = tickPositions = tickPositioner;
+              }
+            }
+          }
+          // Reset min/max or remove extremes based on start/end on tick
+          this.paddedTicks = tickPositions.slice(0); // Used for logarithmic minor
+          this.trimTicks(tickPositions, startOnTick, endOnTick);
+          if (!this.isLinked) {
+            // Substract half a unit (#2619, #2846, #2515, #3390),
+            // but not in case of multiple ticks (#6897)
+            if (
+              this.single &&
+              tickPositions.length < 2 &&
+              !this.categories &&
+              !this.series.some(function (s) {
+                return (
+                  s.is("heatmap") && s.options.pointPlacement === "between"
+                );
+              })
+            ) {
+              this.min -= 0.5;
+              this.max += 0.5;
+            }
+            if (!tickPositionsOption && !tickPositioner) {
+              this.adjustTickAmount();
+            }
+          }
+          fireEvent(this, "afterSetTickPositions");
+        };
+        /**
+         * Handle startOnTick and endOnTick by either adapting to padding min/max or
+         * rounded min/max. Also handle single data points.
+         *
+         * @private
+         * @function Highcharts.Axis#trimTicks
+         *
+         * @param {Array<number>} tickPositions
+         * TO-DO: parameter description
+         *
+         * @param {boolean} [startOnTick]
+         * TO-DO: parameter description
+         *
+         * @param {boolean} [endOnTick]
+         * TO-DO: parameter description
+         */
+        Axis.prototype.trimTicks = function (
+          tickPositions,
+          startOnTick,
+          endOnTick
+        ) {
+          var roundedMin = tickPositions[0],
+            roundedMax = tickPositions[tickPositions.length - 1],
+            minPointOffset = (!this.isOrdinal && this.minPointOffset) || 0; // (#12716)
+          fireEvent(this, "trimTicks");
+          if (!this.isLinked) {
+            if (startOnTick && roundedMin !== -Infinity) {
+              // #6502
+              this.min = roundedMin;
+            } else {
+              while (this.min - minPointOffset > tickPositions[0]) {
+                tickPositions.shift();
+              }
+            }
+            if (endOnTick) {
+              this.max = roundedMax;
+            } else {
+              while (
+                this.max + minPointOffset <
+                tickPositions[tickPositions.length - 1]
+              ) {
+                tickPositions.pop();
+              }
+            }
+            // If no tick are left, set one tick in the middle (#3195)
+            if (
+              tickPositions.length === 0 &&
+              defined(roundedMin) &&
+              !this.options.tickPositions
+            ) {
+              tickPositions.push((roundedMax + roundedMin) / 2);
+            }
+          }
+        };
+        /**
+         * Check if there are multiple axes in the same pane.
+         *
+         * @private
+         * @function Highcharts.Axis#alignToOthers
+         *
+         * @return {boolean|undefined}
+         * True if there are other axes.
+         */
+        Axis.prototype.alignToOthers = function () {
+          var axis = this,
+            others =
+              // Whether there is another axis to pair with this one
+              {},
+            hasOther,
+            options = axis.options;
+          if (
+            // Only if alignTicks is true
+            this.chart.options.chart.alignTicks !== false &&
+            options.alignTicks !== false &&
+            // Disabled when startOnTick or endOnTick are false (#7604)
+            options.startOnTick !== false &&
+            options.endOnTick !== false &&
+            // Don't try to align ticks on a log axis, they are not evenly
+            // spaced (#6021)
+            !axis.logarithmic
+          ) {
+            this.chart[this.coll].forEach(function (axis) {
+              var otherOptions = axis.options,
+                horiz = axis.horiz,
+                key = [
+                  horiz ? otherOptions.left : otherOptions.top,
+                  otherOptions.width,
+                  otherOptions.height,
+                  otherOptions.pane,
+                ].join(",");
+              if (axis.series.length) {
+                // #4442
+                if (others[key]) {
+                  hasOther = true; // #4201
+                } else {
+                  others[key] = 1;
+                }
+              }
+            });
+          }
+          return hasOther;
+        };
+        /**
+         * Find the max ticks of either the x and y axis collection, and record it
+         * in `this.tickAmount`.
+         *
+         * @private
+         * @function Highcharts.Axis#getTickAmount
+         */
+        Axis.prototype.getTickAmount = function () {
+          var axis = this,
+            options = this.options,
+            tickAmount = options.tickAmount,
+            tickPixelInterval = options.tickPixelInterval;
+          if (
+            !defined(options.tickInterval) &&
+            !tickAmount &&
+            this.len < tickPixelInterval &&
+            !this.isRadial &&
+            !axis.logarithmic &&
+            options.startOnTick &&
+            options.endOnTick
+          ) {
+            tickAmount = 2;
+          }
+          if (!tickAmount && this.alignToOthers()) {
+            // Add 1 because 4 tick intervals require 5 ticks (including first
+            // and last)
+            tickAmount = Math.ceil(this.len / tickPixelInterval) + 1;
+          }
+          // For tick amounts of 2 and 3, compute five ticks and remove the
+          // intermediate ones. This prevents the axis from adding ticks that are
+          // too far away from the data extremes.
+          if (tickAmount < 4) {
+            this.finalTickAmt = tickAmount;
+            tickAmount = 5;
+          }
+          this.tickAmount = tickAmount;
+        };
+        /**
+         * When using multiple axes, adjust the number of ticks to match the highest
+         * number of ticks in that group.
+         *
+         * @private
+         * @function Highcharts.Axis#adjustTickAmount
+         */
+        Axis.prototype.adjustTickAmount = function () {
+          var axis = this,
+            axisOptions = axis.options,
+            tickInterval = axis.tickInterval,
+            tickPositions = axis.tickPositions,
+            tickAmount = axis.tickAmount,
+            finalTickAmt = axis.finalTickAmt,
+            currentTickAmount = tickPositions && tickPositions.length,
+            threshold = pick(axis.threshold, axis.softThreshold ? 0 : null),
+            min,
+            len,
+            i;
+          if (axis.hasData()) {
+            if (currentTickAmount < tickAmount) {
+              min = axis.min;
+              while (tickPositions.length < tickAmount) {
+                // Extend evenly for both sides unless we're on the
+                // threshold (#3965)
+                if (tickPositions.length % 2 || min === threshold) {
+                  // to the end
+                  tickPositions.push(
+                    correctFloat(
+                      tickPositions[tickPositions.length - 1] + tickInterval
+                    )
+                  );
+                } else {
+                  // to the start
+                  tickPositions.unshift(
+                    correctFloat(tickPositions[0] - tickInterval)
+                  );
+                }
+              }
+              axis.transA *= (currentTickAmount - 1) / (tickAmount - 1);
+              // Do not crop when ticks are not extremes (#9841)
+              axis.min = axisOptions.startOnTick
+                ? tickPositions[0]
+                : Math.min(axis.min, tickPositions[0]);
+              axis.max = axisOptions.endOnTick
+                ? tickPositions[tickPositions.length - 1]
+                : Math.max(axis.max, tickPositions[tickPositions.length - 1]);
+              // We have too many ticks, run second pass to try to reduce ticks
+            } else if (currentTickAmount > tickAmount) {
+              axis.tickInterval *= 2;
+              axis.setTickPositions();
+            }
+            // The finalTickAmt property is set in getTickAmount
+            if (defined(finalTickAmt)) {
+              i = len = tickPositions.length;
+              while (i--) {
+                if (
+                  // Remove every other tick
+                  (finalTickAmt === 3 && i % 2 === 1) ||
+                  // Remove all but first and last
+                  (finalTickAmt <= 2 && i > 0 && i < len - 1)
+                ) {
+                  tickPositions.splice(i, 1);
                 }
-                else {
-                    options = {
-                        innerR: innerR,
-                        start: start,
-                        end: end
-                    };
-                }
-                // Arcs are defined as symbols for the ability to set
-                // attributes in attr and animate
-                arc = this.symbol('arc', x, y, r, r, options);
-                arc.r = r; // #959
-                return arc;
-            };
-            /**
-             * Draw and return a rectangle.
-             *
-             * @function Highcharts.SVGRenderer#rect
-             *
-             * @param {number} [x]
-             * Left position.
-             *
-             * @param {number} [y]
-             * Top position.
-             *
-             * @param {number} [width]
-             * Width of the rectangle.
-             *
-             * @param {number} [height]
-             * Height of the rectangle.
-             *
-             * @param {number} [r]
-             * Border corner radius.
-             *
-             * @param {number} [strokeWidth]
-             * A stroke width can be supplied to allow crisp drawing.
-             *
-             * @return {Highcharts.SVGElement}
-             * The generated wrapper element.
-             */ /**
-            * Draw and return a rectangle.
-            *
-            * @sample highcharts/members/renderer-rect-on-chart/
-            *         Draw a rectangle in a chart
-            * @sample highcharts/members/renderer-rect/
-            *         Draw a rectangle independent from a chart
-            *
-            * @function Highcharts.SVGRenderer#rect
-            *
-            * @param {Highcharts.SVGAttributes} [attributes]
-            * General SVG attributes for the rectangle.
-            *
-            * @return {Highcharts.SVGElement}
-            * The generated wrapper element.
-            */
-            SVGRenderer.prototype.rect = function (x, y, width, height, r, strokeWidth) {
-                r = isObject(x) ? x.r : r;
-                var wrapper = this.createElement('rect'),
-                    attribs = isObject(x) ?
-                        x :
-                        typeof x === 'undefined' ?
-                            {} :
-                            {
-                                x: x,
-                                y: y,
-                                width: Math.max(width, 0),
-                                height: Math.max(height, 0)
-                            };
-                if (!this.styledMode) {
-                    if (typeof strokeWidth !== 'undefined') {
-                        attribs.strokeWidth = strokeWidth;
-                        attribs = wrapper.crisp(attribs);
-                    }
-                    attribs.fill = 'none';
-                }
-                if (r) {
-                    attribs.r = r;
-                }
-                wrapper.rSetter = function (value, key, element) {
-                    wrapper.r = value;
-                    attr(element, {
-                        rx: value,
-                        ry: value
-                    });
-                };
-                wrapper.rGetter = function () {
-                    return wrapper.r;
-                };
-                return wrapper.attr(attribs);
-            };
-            /**
-             * Resize the {@link SVGRenderer#box} and re-align all aligned child
-             * elements.
-             *
-             * @sample highcharts/members/renderer-g/
-             *         Show and hide grouped objects
-             *
-             * @function Highcharts.SVGRenderer#setSize
-             *
-             * @param {number} width
-             * The new pixel width.
-             *
-             * @param {number} height
-             * The new pixel height.
-             *
-             * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animate=true]
-             * Whether and how to animate.
-             */
-            SVGRenderer.prototype.setSize = function (width, height, animate) {
-                var renderer = this,
-                    alignedObjects = renderer.alignedObjects,
-                    i = alignedObjects.length;
-                renderer.width = width;
-                renderer.height = height;
-                renderer.boxWrapper.animate({
-                    width: width,
-                    height: height
-                }, {
-                    step: function () {
-                        this.attr({
-                            viewBox: '0 0 ' + this.attr('width') + ' ' +
-                                this.attr('height')
-                        });
-                    },
-                    duration: pick(animate, true) ? void 0 : 0
+              }
+              axis.finalTickAmt = void 0;
+            }
+          }
+        };
+        /**
+         * Set the scale based on data min and max, user set min and max or options.
+         *
+         * @private
+         * @function Highcharts.Axis#setScale
+         *
+         * @fires Highcharts.Axis#event:afterSetScale
+         */
+        Axis.prototype.setScale = function () {
+          var axis = this,
+            isDirtyAxisLength,
+            isDirtyData = false,
+            isXAxisDirty = false;
+          axis.series.forEach(function (series) {
+            var _a;
+            isDirtyData = isDirtyData || series.isDirtyData || series.isDirty;
+            // When x axis is dirty, we need new data extremes for y as
+            // well:
+            isXAxisDirty =
+              isXAxisDirty ||
+              ((_a = series.xAxis) === null || _a === void 0
+                ? void 0
+                : _a.isDirty) ||
+              false;
+          });
+          axis.oldMin = axis.min;
+          axis.oldMax = axis.max;
+          axis.oldAxisLength = axis.len;
+          // set the new axisLength
+          axis.setAxisSize();
+          isDirtyAxisLength = axis.len !== axis.oldAxisLength;
+          // do we really need to go through all this?
+          if (
+            isDirtyAxisLength ||
+            isDirtyData ||
+            isXAxisDirty ||
+            axis.isLinked ||
+            axis.forceRedraw ||
+            axis.userMin !== axis.oldUserMin ||
+            axis.userMax !== axis.oldUserMax ||
+            axis.alignToOthers()
+          ) {
+            if (axis.stacking) {
+              axis.stacking.resetStacks();
+            }
+            axis.forceRedraw = false;
+            // get data extremes if needed
+            axis.getSeriesExtremes();
+            // get fixed positions based on tickInterval
+            axis.setTickInterval();
+            // record old values to decide whether a rescale is necessary later
+            // on (#540)
+            axis.oldUserMin = axis.userMin;
+            axis.oldUserMax = axis.userMax;
+            // Mark as dirty if it is not already set to dirty and extremes have
+            // changed. #595.
+            if (!axis.isDirty) {
+              axis.isDirty =
+                isDirtyAxisLength ||
+                axis.min !== axis.oldMin ||
+                axis.max !== axis.oldMax;
+            }
+          } else if (axis.stacking) {
+            axis.stacking.cleanStacks();
+          }
+          // Recalculate panning state object, when the data
+          // has changed. It is required when vertical panning is enabled.
+          if (isDirtyData && axis.panningState) {
+            axis.panningState.isDirty = true;
+          }
+          fireEvent(this, "afterSetScale");
+        };
+        /**
+         * Set the minimum and maximum of the axes after render time. If the
+         * `startOnTick` and `endOnTick` options are true, the minimum and maximum
+         * values are rounded off to the nearest tick. To prevent this, these
+         * options can be set to false before calling setExtremes. Also, setExtremes
+         * will not allow a range lower than the `minRange` option, which by default
+         * is the range of five points.
+         *
+         * @sample highcharts/members/axis-setextremes/
+         *         Set extremes from a button
+         * @sample highcharts/members/axis-setextremes-datetime/
+         *         Set extremes on a datetime axis
+         * @sample highcharts/members/axis-setextremes-off-ticks/
+         *         Set extremes off ticks
+         * @sample stock/members/axis-setextremes/
+         *         Set extremes in Highstock
+         * @sample maps/members/axis-setextremes/
+         *         Set extremes in Highmaps
+         *
+         * @function Highcharts.Axis#setExtremes
+         *
+         * @param {number} [newMin]
+         *        The new minimum value.
+         *
+         * @param {number} [newMax]
+         *        The new maximum value.
+         *
+         * @param {boolean} [redraw=true]
+         *        Whether to redraw the chart or wait for an explicit call to
+         *        {@link Highcharts.Chart#redraw}
+         *
+         * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation=true]
+         *        Enable or modify animations.
+         *
+         * @param {*} [eventArguments]
+         *        Arguments to be accessed in event handler.
+         *
+         * @fires Highcharts.Axis#event:setExtremes
+         */
+        Axis.prototype.setExtremes = function (
+          newMin,
+          newMax,
+          redraw,
+          animation,
+          eventArguments
+        ) {
+          var axis = this,
+            chart = axis.chart;
+          redraw = pick(redraw, true); // defaults to true
+          axis.series.forEach(function (serie) {
+            delete serie.kdTree;
+          });
+          // Extend the arguments with min and max
+          eventArguments = extend(eventArguments, {
+            min: newMin,
+            max: newMax,
+          });
+          // Fire the event
+          fireEvent(axis, "setExtremes", eventArguments, function () {
+            axis.userMin = newMin;
+            axis.userMax = newMax;
+            axis.eventArgs = eventArguments;
+            if (redraw) {
+              chart.redraw(animation);
+            }
+          });
+        };
+        /**
+         * Overridable method for zooming chart. Pulled out in a separate method to
+         * allow overriding in stock charts.
+         * @private
+         * @function Highcharts.Axis#zoom
+         *
+         * @param {number} newMin
+         * TO-DO: parameter description
+         *
+         * @param {number} newMax
+         * TO-DO: parameter description
+         *
+         * @return {boolean}
+         */
+        Axis.prototype.zoom = function (newMin, newMax) {
+          var axis = this,
+            dataMin = this.dataMin,
+            dataMax = this.dataMax,
+            options = this.options,
+            min = Math.min(dataMin, pick(options.min, dataMin)),
+            max = Math.max(dataMax, pick(options.max, dataMax)),
+            evt = {
+              newMin: newMin,
+              newMax: newMax,
+            };
+          fireEvent(this, "zoom", evt, function (e) {
+            // Use e.newMin and e.newMax - event handlers may have altered them
+            var newMin = e.newMin,
+              newMax = e.newMax;
+            if (newMin !== axis.min || newMax !== axis.max) {
+              // #5790
+              // Prevent pinch zooming out of range. Check for defined is for
+              // #1946. #1734.
+              if (!axis.allowZoomOutside) {
+                // #6014, sometimes newMax will be smaller than min (or
+                // newMin will be larger than max).
+                if (defined(dataMin)) {
+                  if (newMin < min) {
+                    newMin = min;
+                  }
+                  if (newMin > max) {
+                    newMin = max;
+                  }
+                }
+                if (defined(dataMax)) {
+                  if (newMax < min) {
+                    newMax = min;
+                  }
+                  if (newMax > max) {
+                    newMax = max;
+                  }
+                }
+              }
+              // In full view, displaying the reset zoom button is not
+              // required
+              axis.displayBtn =
+                typeof newMin !== "undefined" || typeof newMax !== "undefined";
+              // Do it
+              axis.setExtremes(newMin, newMax, false, void 0, {
+                trigger: "zoom",
+              });
+            }
+            e.zoomed = true;
+          });
+          return evt.zoomed;
+        };
+        /**
+         * Update the axis metrics.
+         *
+         * @private
+         * @function Highcharts.Axis#setAxisSize
+         */
+        Axis.prototype.setAxisSize = function () {
+          var chart = this.chart,
+            options = this.options,
+            // [top, right, bottom, left]
+            offsets = options.offsets || [0, 0, 0, 0],
+            horiz = this.horiz,
+            // Check for percentage based input values. Rounding fixes problems
+            // with column overflow and plot line filtering (#4898, #4899)
+            width = (this.width = Math.round(
+              relativeLength(
+                pick(options.width, chart.plotWidth - offsets[3] + offsets[1]),
+                chart.plotWidth
+              )
+            )),
+            height = (this.height = Math.round(
+              relativeLength(
+                pick(
+                  options.height,
+                  chart.plotHeight - offsets[0] + offsets[2]
+                ),
+                chart.plotHeight
+              )
+            )),
+            top = (this.top = Math.round(
+              relativeLength(
+                pick(options.top, chart.plotTop + offsets[0]),
+                chart.plotHeight,
+                chart.plotTop
+              )
+            )),
+            left = (this.left = Math.round(
+              relativeLength(
+                pick(options.left, chart.plotLeft + offsets[3]),
+                chart.plotWidth,
+                chart.plotLeft
+              )
+            ));
+          // Expose basic values to use in Series object and navigator
+          this.bottom = chart.chartHeight - height - top;
+          this.right = chart.chartWidth - width - left;
+          // Direction agnostic properties
+          this.len = Math.max(horiz ? width : height, 0); // Math.max fixes #905
+          this.pos = horiz ? left : top; // distance from SVG origin
+        };
+        /**
+         * Get the current extremes for the axis.
+         *
+         * @sample highcharts/members/axis-getextremes/
+         *         Report extremes by click on a button
+         * @sample maps/members/axis-getextremes/
+         *         Get extremes in Highmaps
+         *
+         * @function Highcharts.Axis#getExtremes
+         *
+         * @return {Highcharts.ExtremesObject}
+         * An object containing extremes information.
+         */
+        Axis.prototype.getExtremes = function () {
+          var axis = this;
+          var log = axis.logarithmic;
+          return {
+            min: log ? correctFloat(log.lin2log(axis.min)) : axis.min,
+            max: log ? correctFloat(log.lin2log(axis.max)) : axis.max,
+            dataMin: axis.dataMin,
+            dataMax: axis.dataMax,
+            userMin: axis.userMin,
+            userMax: axis.userMax,
+          };
+        };
+        /**
+         * Get the zero plane either based on zero or on the min or max value.
+         * Used in bar and area plots.
+         *
+         * @function Highcharts.Axis#getThreshold
+         *
+         * @param {number} threshold
+         * The threshold in axis values.
+         *
+         * @return {number|undefined}
+         * The translated threshold position in terms of pixels, and corrected to
+         * stay within the axis bounds.
+         */
+        Axis.prototype.getThreshold = function (threshold) {
+          var axis = this,
+            log = axis.logarithmic,
+            realMin = log ? log.lin2log(axis.min) : axis.min,
+            realMax = log ? log.lin2log(axis.max) : axis.max;
+          if (threshold === null || threshold === -Infinity) {
+            threshold = realMin;
+          } else if (threshold === Infinity) {
+            threshold = realMax;
+          } else if (realMin > threshold) {
+            threshold = realMin;
+          } else if (realMax < threshold) {
+            threshold = realMax;
+          }
+          return axis.translate(threshold, 0, 1, 0, 1);
+        };
+        /**
+         * Compute auto alignment for the axis label based on which side the axis is
+         * on and the given rotation for the label.
+         *
+         * @private
+         * @function Highcharts.Axis#autoLabelAlign
+         *
+         * @param {number} rotation
+         * The rotation in degrees as set by either the `rotation` or `autoRotation`
+         * options.
+         *
+         * @return {Highcharts.AlignValue}
+         * Can be `"center"`, `"left"` or `"right"`.
+         */
+        Axis.prototype.autoLabelAlign = function (rotation) {
+          var angle = (pick(rotation, 0) - this.side * 90 + 720) % 360,
+            evt = { align: "center" };
+          fireEvent(this, "autoLabelAlign", evt, function (e) {
+            if (angle > 15 && angle < 165) {
+              e.align = "right";
+            } else if (angle > 195 && angle < 345) {
+              e.align = "left";
+            }
+          });
+          return evt.align;
+        };
+        /**
+         * Get the tick length and width for the axis based on axis options.
+         * @private
+         * @function Highcharts.Axis#tickSize
+         *
+         * @param {string} [prefix]
+         * 'tick' or 'minorTick'
+         *
+         * @return {Array<number,number>|undefined}
+         * An array of tickLength and tickWidth
+         */
+        Axis.prototype.tickSize = function (prefix) {
+          var options = this.options,
+            tickLength =
+              options[prefix === "tick" ? "tickLength" : "minorTickLength"],
+            tickWidth = pick(
+              options[prefix === "tick" ? "tickWidth" : "minorTickWidth"],
+              // Default to 1 on linear and datetime X axes
+              prefix === "tick" && this.isXAxis && !this.categories ? 1 : 0
+            ),
+            e,
+            tickSize;
+          if (tickWidth && tickLength) {
+            // Negate the length
+            if (options[prefix + "Position"] === "inside") {
+              tickLength = -tickLength;
+            }
+            tickSize = [tickLength, tickWidth];
+          }
+          e = { tickSize: tickSize };
+          fireEvent(this, "afterTickSize", e);
+          return e.tickSize;
+        };
+        /**
+         * Return the size of the labels.
+         *
+         * @private
+         * @function Highcharts.Axis#labelMetrics
+         *
+         * @return {Highcharts.FontMetricsObject}
+         */
+        Axis.prototype.labelMetrics = function () {
+          var index = (this.tickPositions && this.tickPositions[0]) || 0;
+          return this.chart.renderer.fontMetrics(
+            this.options.labels.style && this.options.labels.style.fontSize,
+            this.ticks[index] && this.ticks[index].label
+          );
+        };
+        /**
+         * Prevent the ticks from getting so close we can't draw the labels. On a
+         * horizontal axis, this is handled by rotating the labels, removing ticks
+         * and adding ellipsis. On a vertical axis remove ticks and add ellipsis.
+         *
+         * @private
+         * @function Highcharts.Axis#unsquish
+         *
+         * @return {number}
+         */
+        Axis.prototype.unsquish = function () {
+          var labelOptions = this.options.labels,
+            horiz = this.horiz,
+            tickInterval = this.tickInterval,
+            newTickInterval = tickInterval,
+            slotSize =
+              this.len /
+              (((this.categories ? 1 : 0) + this.max - this.min) /
+                tickInterval),
+            rotation,
+            rotationOption = labelOptions.rotation,
+            labelMetrics = this.labelMetrics(),
+            step,
+            bestScore = Number.MAX_VALUE,
+            autoRotation,
+            range = this.max - this.min,
+            // Return the multiple of tickInterval that is needed to avoid
+            // collision
+            getStep = function (spaceNeeded) {
+              var step = spaceNeeded / (slotSize || 1);
+              step = step > 1 ? Math.ceil(step) : 1;
+              // Guard for very small or negative angles (#9835)
+              if (
+                step * tickInterval > range &&
+                spaceNeeded !== Infinity &&
+                slotSize !== Infinity &&
+                range
+              ) {
+                step = Math.ceil(range / tickInterval);
+              }
+              return correctFloat(step * tickInterval);
+            };
+          if (horiz) {
+            autoRotation =
+              !labelOptions.staggerLines &&
+              !labelOptions.step && // #3971
+              (defined(rotationOption)
+                ? [rotationOption]
+                : slotSize < pick(labelOptions.autoRotationLimit, 80) &&
+                  labelOptions.autoRotation);
+            if (autoRotation) {
+              // Loop over the given autoRotation options, and determine
+              // which gives the best score. The best score is that with
+              // the lowest number of steps and a rotation closest
+              // to horizontal.
+              autoRotation.forEach(function (rot) {
+                var score;
+                if (
+                  rot === rotationOption ||
+                  (rot && rot >= -90 && rot <= 90)
+                ) {
+                  // #3891
+                  step = getStep(
+                    Math.abs(labelMetrics.h / Math.sin(deg2rad * rot))
+                  );
+                  score = step + Math.abs(rot / 360);
+                  if (score < bestScore) {
+                    bestScore = score;
+                    rotation = rot;
+                    newTickInterval = step;
+                  }
+                }
+              });
+            }
+          } else if (!labelOptions.step) {
+            // #4411
+            newTickInterval = getStep(labelMetrics.h);
+          }
+          this.autoRotation = autoRotation;
+          this.labelRotation = pick(rotation, rotationOption);
+          return newTickInterval;
+        };
+        /**
+         * Get the general slot width for labels/categories on this axis. This may
+         * change between the pre-render (from Axis.getOffset) and the final tick
+         * rendering and placement.
+         *
+         * @private
+         * @function Highcharts.Axis#getSlotWidth
+         *
+         * @param {Highcharts.Tick} [tick] Optionally, calculate the slot width
+         * basing on tick label. It is used in highcharts-3d module, where the slots
+         * has different widths depending on perspective angles.
+         *
+         * @return {number}
+         * The pixel width allocated to each axis label.
+         */
+        Axis.prototype.getSlotWidth = function (tick) {
+          var _a;
+          // #5086, #1580, #1931
+          var chart = this.chart,
+            horiz = this.horiz,
+            labelOptions = this.options.labels,
+            slotCount = Math.max(
+              this.tickPositions.length - (this.categories ? 0 : 1),
+              1
+            ),
+            marginLeft = chart.margin[3];
+          // Used by grid axis
+          if (tick && isNumber(tick.slotWidth)) {
+            // #13221, can be 0
+            return tick.slotWidth;
+          }
+          if (horiz && labelOptions && (labelOptions.step || 0) < 2) {
+            if (labelOptions.rotation) {
+              // #4415
+              return 0;
+            }
+            return ((this.staggerLines || 1) * this.len) / slotCount;
+          }
+          if (!horiz) {
+            // #7028
+            var cssWidth =
+              (_a =
+                labelOptions === null || labelOptions === void 0
+                  ? void 0
+                  : labelOptions.style) === null || _a === void 0
+                ? void 0
+                : _a.width;
+            if (cssWidth !== void 0) {
+              return parseInt(cssWidth, 10);
+            }
+            if (marginLeft) {
+              return marginLeft - chart.spacing[3];
+            }
+          }
+          // Last resort, a fraction of the available size
+          return chart.chartWidth * 0.33;
+        };
+        /**
+         * Render the axis labels and determine whether ellipsis or rotation need to
+         * be applied.
+         *
+         * @private
+         * @function Highcharts.Axis#renderUnsquish
+         */
+        Axis.prototype.renderUnsquish = function () {
+          var chart = this.chart,
+            renderer = chart.renderer,
+            tickPositions = this.tickPositions,
+            ticks = this.ticks,
+            labelOptions = this.options.labels,
+            labelStyleOptions = (labelOptions && labelOptions.style) || {},
+            horiz = this.horiz,
+            slotWidth = this.getSlotWidth(),
+            innerWidth = Math.max(
+              1,
+              Math.round(slotWidth - 2 * (labelOptions.padding || 5))
+            ),
+            attr = {},
+            labelMetrics = this.labelMetrics(),
+            textOverflowOption =
+              labelOptions.style && labelOptions.style.textOverflow,
+            commonWidth,
+            commonTextOverflow,
+            maxLabelLength = 0,
+            label,
+            i,
+            pos;
+          // Set rotation option unless it is "auto", like in gauges
+          if (!isString(labelOptions.rotation)) {
+            // #4443:
+            attr.rotation = labelOptions.rotation || 0;
+          }
+          // Get the longest label length
+          tickPositions.forEach(function (tick) {
+            tick = ticks[tick];
+            // Replace label - sorting animation
+            if (tick.movedLabel) {
+              tick.replaceMovedLabel();
+            }
+            if (
+              tick &&
+              tick.label &&
+              tick.label.textPxLength > maxLabelLength
+            ) {
+              maxLabelLength = tick.label.textPxLength;
+            }
+          });
+          this.maxLabelLength = maxLabelLength;
+          // Handle auto rotation on horizontal axis
+          if (this.autoRotation) {
+            // Apply rotation only if the label is too wide for the slot, and
+            // the label is wider than its height.
+            if (
+              maxLabelLength > innerWidth &&
+              maxLabelLength > labelMetrics.h
+            ) {
+              attr.rotation = this.labelRotation;
+            } else {
+              this.labelRotation = 0;
+            }
+            // Handle word-wrap or ellipsis on vertical axis
+          } else if (slotWidth) {
+            // For word-wrap or ellipsis
+            commonWidth = innerWidth;
+            if (!textOverflowOption) {
+              commonTextOverflow = "clip";
+              // On vertical axis, only allow word wrap if there is room
+              // for more lines.
+              i = tickPositions.length;
+              while (!horiz && i--) {
+                pos = tickPositions[i];
+                label = ticks[pos].label;
+                if (label) {
+                  // Reset ellipsis in order to get the correct
+                  // bounding box (#4070)
+                  if (
+                    label.styles &&
+                    label.styles.textOverflow === "ellipsis"
+                  ) {
+                    label.css({ textOverflow: "clip" });
+                    // Set the correct width in order to read
+                    // the bounding box height (#4678, #5034)
+                  } else if (label.textPxLength > slotWidth) {
+                    label.css({ width: slotWidth + "px" });
+                  }
+                  if (
+                    label.getBBox().height >
+                    this.len / tickPositions.length -
+                      (labelMetrics.h - labelMetrics.f)
+                  ) {
+                    label.specificTextOverflow = "ellipsis";
+                  }
+                }
+              }
+            }
+          }
+          // Add ellipsis if the label length is significantly longer than ideal
+          if (attr.rotation) {
+            commonWidth =
+              maxLabelLength > chart.chartHeight * 0.5
+                ? chart.chartHeight * 0.33
+                : maxLabelLength;
+            if (!textOverflowOption) {
+              commonTextOverflow = "ellipsis";
+            }
+          }
+          // Set the explicit or automatic label alignment
+          this.labelAlign =
+            labelOptions.align || this.autoLabelAlign(this.labelRotation);
+          if (this.labelAlign) {
+            attr.align = this.labelAlign;
+          }
+          // Apply general and specific CSS
+          tickPositions.forEach(function (pos) {
+            var tick = ticks[pos],
+              label = tick && tick.label,
+              widthOption = labelStyleOptions.width,
+              css = {};
+            if (label) {
+              // This needs to go before the CSS in old IE (#4502)
+              label.attr(attr);
+              if (tick.shortenLabel) {
+                tick.shortenLabel();
+              } else if (
+                commonWidth &&
+                !widthOption &&
+                // Setting width in this case messes with the bounding box
+                // (#7975)
+                labelStyleOptions.whiteSpace !== "nowrap" &&
+                // Speed optimizing, #7656
+                (commonWidth < label.textPxLength ||
+                  // Resetting CSS, #4928
+                  label.element.tagName === "SPAN")
+              ) {
+                css.width = commonWidth + "px";
+                if (!textOverflowOption) {
+                  css.textOverflow =
+                    label.specificTextOverflow || commonTextOverflow;
+                }
+                label.css(css);
+                // Reset previously shortened label (#8210)
+              } else if (
+                label.styles &&
+                label.styles.width &&
+                !css.width &&
+                !widthOption
+              ) {
+                label.css({ width: null });
+              }
+              delete label.specificTextOverflow;
+              tick.rotation = attr.rotation;
+            }
+          }, this);
+          // Note: Why is this not part of getLabelPosition?
+          this.tickRotCorr = renderer.rotCorr(
+            labelMetrics.b,
+            this.labelRotation || 0,
+            this.side !== 0
+          );
+        };
+        /**
+         * Return true if the axis has associated data.
+         *
+         * @function Highcharts.Axis#hasData
+         *
+         * @return {boolean}
+         * True if the axis has associated visible series and those series have
+         * either valid data points or explicit `min` and `max` settings.
+         */
+        Axis.prototype.hasData = function () {
+          return (
+            this.series.some(function (s) {
+              return s.hasData();
+            }) ||
+            (this.options.showEmpty && defined(this.min) && defined(this.max))
+          );
+        };
+        /**
+         * Adds the title defined in axis.options.title.
+         *
+         * @function Highcharts.Axis#addTitle
+         *
+         * @param {boolean} [display]
+         * Whether or not to display the title.
+         */
+        Axis.prototype.addTitle = function (display) {
+          var axis = this,
+            renderer = axis.chart.renderer,
+            horiz = axis.horiz,
+            opposite = axis.opposite,
+            options = axis.options,
+            axisTitleOptions = options.title,
+            textAlign,
+            styledMode = axis.chart.styledMode;
+          if (!axis.axisTitle) {
+            textAlign = axisTitleOptions.textAlign;
+            if (!textAlign) {
+              textAlign = (
+                horiz
+                  ? {
+                      low: "left",
+                      middle: "center",
+                      high: "right",
+                    }
+                  : {
+                      low: opposite ? "right" : "left",
+                      middle: "center",
+                      high: opposite ? "left" : "right",
+                    }
+              )[axisTitleOptions.align];
+            }
+            axis.axisTitle = renderer
+              .text(axisTitleOptions.text, 0, 0, axisTitleOptions.useHTML)
+              .attr({
+                zIndex: 7,
+                rotation: axisTitleOptions.rotation || 0,
+                align: textAlign,
+              })
+              .addClass("highcharts-axis-title");
+            // #7814, don't mutate style option
+            if (!styledMode) {
+              axis.axisTitle.css(merge(axisTitleOptions.style));
+            }
+            axis.axisTitle.add(axis.axisGroup);
+            axis.axisTitle.isNew = true;
+          }
+          // Max width defaults to the length of the axis
+          if (!styledMode && !axisTitleOptions.style.width && !axis.isRadial) {
+            axis.axisTitle.css({
+              width: axis.len + "px",
+            });
+          }
+          // hide or show the title depending on whether showEmpty is set
+          axis.axisTitle[display ? "show" : "hide"](display);
+        };
+        /**
+         * Generates a tick for initial positioning.
+         *
+         * @private
+         * @function Highcharts.Axis#generateTick
+         *
+         * @param {number} pos
+         * The tick position in axis values.
+         *
+         * @param {number} [i]
+         * The index of the tick in {@link Axis.tickPositions}.
+         */
+        Axis.prototype.generateTick = function (pos) {
+          var axis = this;
+          var ticks = axis.ticks;
+          if (!ticks[pos]) {
+            ticks[pos] = new Tick(axis, pos);
+          } else {
+            ticks[pos].addLabel(); // update labels depending on tick interval
+          }
+        };
+        /**
+         * Render the tick labels to a preliminary position to get their sizes
+         *
+         * @private
+         * @function Highcharts.Axis#getOffset
+         *
+         * @fires Highcharts.Axis#event:afterGetOffset
+         */
+        Axis.prototype.getOffset = function () {
+          var axis = this,
+            chart = axis.chart,
+            renderer = chart.renderer,
+            options = axis.options,
+            tickPositions = axis.tickPositions,
+            ticks = axis.ticks,
+            horiz = axis.horiz,
+            side = axis.side,
+            invertedSide =
+              chart.inverted && !axis.isZAxis ? [1, 0, 3, 2][side] : side,
+            hasData,
+            showAxis,
+            titleOffset = 0,
+            titleOffsetOption,
+            titleMargin = 0,
+            axisTitleOptions = options.title,
+            labelOptions = options.labels,
+            labelOffset = 0, // reset
+            labelOffsetPadded,
+            axisOffset = chart.axisOffset,
+            clipOffset = chart.clipOffset,
+            clip,
+            directionFactor = [-1, 1, 1, -1][side],
+            className = options.className,
+            axisParent = axis.axisParent, // Used in color axis
+            lineHeightCorrection;
+          // For reuse in Axis.render
+          hasData = axis.hasData();
+          axis.showAxis = showAxis = hasData || pick(options.showEmpty, true);
+          // Set/reset staggerLines
+          axis.staggerLines = axis.horiz && labelOptions.staggerLines;
+          // Create the axisGroup and gridGroup elements on first iteration
+          if (!axis.axisGroup) {
+            axis.gridGroup = renderer
+              .g("grid")
+              .attr({ zIndex: options.gridZIndex || 1 })
+              .addClass(
+                "highcharts-" +
+                  this.coll.toLowerCase() +
+                  "-grid " +
+                  (className || "")
+              )
+              .add(axisParent);
+            axis.axisGroup = renderer
+              .g("axis")
+              .attr({ zIndex: options.zIndex || 2 })
+              .addClass(
+                "highcharts-" +
+                  this.coll.toLowerCase() +
+                  " " +
+                  (className || "")
+              )
+              .add(axisParent);
+            axis.labelGroup = renderer
+              .g("axis-labels")
+              .attr({ zIndex: labelOptions.zIndex || 7 })
+              .addClass(
+                "highcharts-" +
+                  axis.coll.toLowerCase() +
+                  "-labels " +
+                  (className || "")
+              )
+              .add(axisParent);
+          }
+          if (hasData || axis.isLinked) {
+            // Generate ticks
+            tickPositions.forEach(function (pos, i) {
+              // i is not used here, but may be used in overrides
+              axis.generateTick(pos, i);
+            });
+            axis.renderUnsquish();
+            // Left side must be align: right and right side must
+            // have align: left for labels
+            axis.reserveSpaceDefault =
+              side === 0 ||
+              side === 2 ||
+              { 1: "left", 3: "right" }[side] === axis.labelAlign;
+            if (
+              pick(
+                labelOptions.reserveSpace,
+                axis.labelAlign === "center" ? true : null,
+                axis.reserveSpaceDefault
+              )
+            ) {
+              tickPositions.forEach(function (pos) {
+                // get the highest offset
+                labelOffset = Math.max(ticks[pos].getLabelSize(), labelOffset);
+              });
+            }
+            if (axis.staggerLines) {
+              labelOffset *= axis.staggerLines;
+            }
+            axis.labelOffset = labelOffset * (axis.opposite ? -1 : 1);
+          } else {
+            // doesn't have data
+            objectEach(ticks, function (tick, n) {
+              tick.destroy();
+              delete ticks[n];
+            });
+          }
+          if (
+            axisTitleOptions &&
+            axisTitleOptions.text &&
+            axisTitleOptions.enabled !== false
+          ) {
+            axis.addTitle(showAxis);
+            if (showAxis && axisTitleOptions.reserveSpace !== false) {
+              axis.titleOffset = titleOffset =
+                axis.axisTitle.getBBox()[horiz ? "height" : "width"];
+              titleOffsetOption = axisTitleOptions.offset;
+              titleMargin = defined(titleOffsetOption)
+                ? 0
+                : pick(axisTitleOptions.margin, horiz ? 5 : 10);
+            }
+          }
+          // Render the axis line
+          axis.renderLine();
+          // handle automatic or user set offset
+          axis.offset =
+            directionFactor *
+            pick(
+              options.offset,
+              axisOffset[side] ? axisOffset[side] + (options.margin || 0) : 0
+            );
+          axis.tickRotCorr = axis.tickRotCorr || { x: 0, y: 0 }; // polar
+          if (side === 0) {
+            lineHeightCorrection = -axis.labelMetrics().h;
+          } else if (side === 2) {
+            lineHeightCorrection = axis.tickRotCorr.y;
+          } else {
+            lineHeightCorrection = 0;
+          }
+          // Find the padded label offset
+          labelOffsetPadded = Math.abs(labelOffset) + titleMargin;
+          if (labelOffset) {
+            labelOffsetPadded -= lineHeightCorrection;
+            labelOffsetPadded +=
+              directionFactor *
+              (horiz
+                ? pick(labelOptions.y, axis.tickRotCorr.y + directionFactor * 8)
+                : labelOptions.x);
+          }
+          axis.axisTitleMargin = pick(titleOffsetOption, labelOffsetPadded);
+          if (axis.getMaxLabelDimensions) {
+            axis.maxLabelDimensions = axis.getMaxLabelDimensions(
+              ticks,
+              tickPositions
+            );
+          }
+          // Due to GridAxis.tickSize, tickSize should be calculated after ticks
+          // has rendered.
+          var tickSize = this.tickSize("tick");
+          axisOffset[side] = Math.max(
+            axisOffset[side],
+            axis.axisTitleMargin + titleOffset + directionFactor * axis.offset,
+            labelOffsetPadded, // #3027
+            tickPositions && tickPositions.length && tickSize
+              ? tickSize[0] + directionFactor * axis.offset
+              : 0 // #4866
+          );
+          // Decide the clipping needed to keep the graph inside
+          // the plot area and axis lines
+          clip = options.offset
+            ? 0
+            : // #4308, #4371:
+              Math.floor(axis.axisLine.strokeWidth() / 2) * 2;
+          clipOffset[invertedSide] = Math.max(clipOffset[invertedSide], clip);
+          fireEvent(this, "afterGetOffset");
+        };
+        /**
+         * Internal function to get the path for the axis line. Extended for polar
+         * charts.
+         *
+         * @function Highcharts.Axis#getLinePath
+         *
+         * @param {number} lineWidth
+         * The line width in pixels.
+         *
+         * @return {Highcharts.SVGPathArray}
+         * The SVG path definition in array form.
+         */
+        Axis.prototype.getLinePath = function (lineWidth) {
+          var chart = this.chart,
+            opposite = this.opposite,
+            offset = this.offset,
+            horiz = this.horiz,
+            lineLeft = this.left + (opposite ? this.width : 0) + offset,
+            lineTop =
+              chart.chartHeight -
+              this.bottom -
+              (opposite ? this.height : 0) +
+              offset;
+          if (opposite) {
+            lineWidth *= -1; // crispify the other way - #1480, #1687
+          }
+          return chart.renderer.crispLine(
+            [
+              ["M", horiz ? this.left : lineLeft, horiz ? lineTop : this.top],
+              [
+                "L",
+                horiz ? chart.chartWidth - this.right : lineLeft,
+                horiz ? lineTop : chart.chartHeight - this.bottom,
+              ],
+            ],
+            lineWidth
+          );
+        };
+        /**
+         * Render the axis line. Called internally when rendering and redrawing the
+         * axis.
+         *
+         * @function Highcharts.Axis#renderLine
+         */
+        Axis.prototype.renderLine = function () {
+          if (!this.axisLine) {
+            this.axisLine = this.chart.renderer
+              .path()
+              .addClass("highcharts-axis-line")
+              .add(this.axisGroup);
+            if (!this.chart.styledMode) {
+              this.axisLine.attr({
+                stroke: this.options.lineColor,
+                "stroke-width": this.options.lineWidth,
+                zIndex: 7,
+              });
+            }
+          }
+        };
+        /**
+         * Position the axis title.
+         *
+         * @private
+         * @function Highcharts.Axis#getTitlePosition
+         *
+         * @return {Highcharts.PositionObject}
+         * X and Y positions for the title.
+         */
+        Axis.prototype.getTitlePosition = function () {
+          // compute anchor points for each of the title align options
+          var horiz = this.horiz,
+            axisLeft = this.left,
+            axisTop = this.top,
+            axisLength = this.len,
+            axisTitleOptions = this.options.title,
+            margin = horiz ? axisLeft : axisTop,
+            opposite = this.opposite,
+            offset = this.offset,
+            xOption = axisTitleOptions.x || 0,
+            yOption = axisTitleOptions.y || 0,
+            axisTitle = this.axisTitle,
+            fontMetrics = this.chart.renderer.fontMetrics(
+              axisTitleOptions.style && axisTitleOptions.style.fontSize,
+              axisTitle
+            ),
+            // The part of a multiline text that is below the baseline of the
+            // first line. Subtract 1 to preserve pixel-perfectness from the
+            // old behaviour (v5.0.12), where only one line was allowed.
+            textHeightOvershoot = Math.max(
+              axisTitle.getBBox(null, 0).height - fontMetrics.h - 1,
+              0
+            ),
+            // the position in the length direction of the axis
+            alongAxis = {
+              low: margin + (horiz ? 0 : axisLength),
+              middle: margin + axisLength / 2,
+              high: margin + (horiz ? axisLength : 0),
+            }[axisTitleOptions.align],
+            // the position in the perpendicular direction of the axis
+            offAxis =
+              (horiz ? axisTop + this.height : axisLeft) +
+              (horiz ? 1 : -1) * // horizontal axis reverses the margin
+                (opposite ? -1 : 1) * // so does opposite axes
+                this.axisTitleMargin +
+              [
+                -textHeightOvershoot,
+                textHeightOvershoot,
+                fontMetrics.f,
+                -textHeightOvershoot, // left
+              ][this.side],
+            titlePosition = {
+              x: horiz
+                ? alongAxis + xOption
+                : offAxis + (opposite ? this.width : 0) + offset + xOption,
+              y: horiz
+                ? offAxis + yOption - (opposite ? this.height : 0) + offset
+                : alongAxis + yOption,
+            };
+          fireEvent(this, "afterGetTitlePosition", {
+            titlePosition: titlePosition,
+          });
+          return titlePosition;
+        };
+        /**
+         * Render a minor tick into the given position. If a minor tick already
+         * exists in this position, move it.
+         *
+         * @function Highcharts.Axis#renderMinorTick
+         *
+         * @param {number} pos
+         * The position in axis values.
+         */
+        Axis.prototype.renderMinorTick = function (pos) {
+          var axis = this;
+          var slideInTicks = axis.chart.hasRendered && isNumber(axis.oldMin);
+          var minorTicks = axis.minorTicks;
+          if (!minorTicks[pos]) {
+            minorTicks[pos] = new Tick(axis, pos, "minor");
+          }
+          // Render new ticks in old position
+          if (slideInTicks && minorTicks[pos].isNew) {
+            minorTicks[pos].render(null, true);
+          }
+          minorTicks[pos].render(null, false, 1);
+        };
+        /**
+         * Render a major tick into the given position. If a tick already exists
+         * in this position, move it.
+         *
+         * @function Highcharts.Axis#renderTick
+         *
+         * @param {number} pos
+         * The position in axis values.
+         *
+         * @param {number} i
+         * The tick index.
+         */
+        Axis.prototype.renderTick = function (pos, i) {
+          var _a;
+          var axis = this;
+          var isLinked = axis.isLinked;
+          var ticks = axis.ticks;
+          var slideInTicks = axis.chart.hasRendered && isNumber(axis.oldMin);
+          // Linked axes need an extra check to find out if
+          if (
+            !isLinked ||
+            (pos >= axis.min && pos <= axis.max) ||
+            ((_a = axis.grid) === null || _a === void 0 ? void 0 : _a.isColumn)
+          ) {
+            if (!ticks[pos]) {
+              ticks[pos] = new Tick(axis, pos);
+            }
+            // NOTE this seems like overkill. Could be handled in tick.render by
+            // setting old position in attr, then set new position in animate.
+            // render new ticks in old position
+            if (slideInTicks && ticks[pos].isNew) {
+              // Start with negative opacity so that it is visible from
+              // halfway into the animation
+              ticks[pos].render(i, true, -1);
+            }
+            ticks[pos].render(i);
+          }
+        };
+        /**
+         * Render the axis.
+         *
+         * @private
+         * @function Highcharts.Axis#render
+         *
+         * @fires Highcharts.Axis#event:afterRender
+         */
+        Axis.prototype.render = function () {
+          var axis = this,
+            chart = axis.chart,
+            log = axis.logarithmic,
+            renderer = chart.renderer,
+            options = axis.options,
+            isLinked = axis.isLinked,
+            tickPositions = axis.tickPositions,
+            axisTitle = axis.axisTitle,
+            ticks = axis.ticks,
+            minorTicks = axis.minorTicks,
+            alternateBands = axis.alternateBands,
+            stackLabelOptions = options.stackLabels,
+            alternateGridColor = options.alternateGridColor,
+            tickmarkOffset = axis.tickmarkOffset,
+            axisLine = axis.axisLine,
+            showAxis = axis.showAxis,
+            animation = animObject(renderer.globalAnimation),
+            from,
+            to;
+          // Reset
+          axis.labelEdge.length = 0;
+          axis.overlap = false;
+          // Mark all elements inActive before we go over and mark the active ones
+          [ticks, minorTicks, alternateBands].forEach(function (coll) {
+            objectEach(coll, function (tick) {
+              tick.isActive = false;
+            });
+          });
+          // If the series has data draw the ticks. Else only the line and title
+          if (axis.hasData() || isLinked) {
+            // minor ticks
+            if (axis.minorTickInterval && !axis.categories) {
+              axis.getMinorTickPositions().forEach(function (pos) {
+                axis.renderMinorTick(pos);
+              });
+            }
+            // Major ticks. Pull out the first item and render it last so that
+            // we can get the position of the neighbour label. #808.
+            if (tickPositions.length) {
+              // #1300
+              tickPositions.forEach(function (pos, i) {
+                axis.renderTick(pos, i);
+              });
+              // In a categorized axis, the tick marks are displayed
+              // between labels. So we need to add a tick mark and
+              // grid line at the left edge of the X axis.
+              if (tickmarkOffset && (axis.min === 0 || axis.single)) {
+                if (!ticks[-1]) {
+                  ticks[-1] = new Tick(axis, -1, null, true);
+                }
+                ticks[-1].render(-1);
+              }
+            }
+            // alternate grid color
+            if (alternateGridColor) {
+              tickPositions.forEach(function (pos, i) {
+                to =
+                  typeof tickPositions[i + 1] !== "undefined"
+                    ? tickPositions[i + 1] + tickmarkOffset
+                    : axis.max - tickmarkOffset;
+                if (
+                  i % 2 === 0 &&
+                  pos < axis.max &&
+                  to <=
+                    axis.max + (chart.polar ? -tickmarkOffset : tickmarkOffset)
+                ) {
+                  // #2248, #4660
+                  if (!alternateBands[pos]) {
+                    // Should be imported from PlotLineOrBand.js, but
+                    // the dependency cycle with axis is a problem
+                    alternateBands[pos] = new H.PlotLineOrBand(axis);
+                  }
+                  from = pos + tickmarkOffset; // #949
+                  alternateBands[pos].options = {
+                    from: log ? log.lin2log(from) : from,
+                    to: log ? log.lin2log(to) : to,
+                    color: alternateGridColor,
+                    className: "highcharts-alternate-grid",
+                  };
+                  alternateBands[pos].render();
+                  alternateBands[pos].isActive = true;
+                }
+              });
+            }
+            // custom plot lines and bands
+            if (!axis._addedPlotLB) {
+              // only first time
+              (options.plotLines || [])
+                .concat(options.plotBands || [])
+                .forEach(function (plotLineOptions) {
+                  axis.addPlotBandOrLine(plotLineOptions);
                 });
+              axis._addedPlotLB = true;
+            }
+          } // end if hasData
+          // Remove inactive ticks
+          [ticks, minorTicks, alternateBands].forEach(function (coll) {
+            var i,
+              forDestruction = [],
+              delay = animation.duration,
+              destroyInactiveItems = function () {
+                i = forDestruction.length;
                 while (i--) {
-                    alignedObjects[i].align();
-                }
-            };
-            /**
-             * Create and return an svg group element. Child
-             * {@link Highcharts.SVGElement} objects are added to the group by using the
-             * group as the first parameter in {@link Highcharts.SVGElement#add|add()}.
-             *
-             * @function Highcharts.SVGRenderer#g
-             *
-             * @param {string} [name]
-             *        The group will be given a class name of `highcharts-{name}`. This
-             *        can be used for styling and scripting.
-             *
-             * @return {Highcharts.SVGElement}
-             *         The generated wrapper element.
-             */
-            SVGRenderer.prototype.g = function (name) {
-                var elem = this.createElement('g');
-                return name ?
-                    elem.attr({ 'class': 'highcharts-' + name }) :
-                    elem;
-            };
-            /**
-             * Display an image.
-             *
-             * @sample highcharts/members/renderer-image-on-chart/
-             *         Add an image in a chart
-             * @sample highcharts/members/renderer-image/
-             *         Add an image independent of a chart
-             *
-             * @function Highcharts.SVGRenderer#image
-             *
-             * @param {string} src
-             *        The image source.
-             *
-             * @param {number} [x]
-             *        The X position.
-             *
-             * @param {number} [y]
-             *        The Y position.
-             *
-             * @param {number} [width]
-             *        The image width. If omitted, it defaults to the image file width.
-             *
-             * @param {number} [height]
-             *        The image height. If omitted it defaults to the image file
-             *        height.
-             *
-             * @param {Function} [onload]
-             *        Event handler for image load.
-             *
-             * @return {Highcharts.SVGElement}
-             *         The generated wrapper element.
-             */
-            SVGRenderer.prototype.image = function (src, x, y, width, height, onload) {
-                var attribs = { preserveAspectRatio: 'none' }, elemWrapper, dummy, setSVGImageSource = function (el, src) {
-                        // Set the href in the xlink namespace
-                        if (el.setAttributeNS) {
-                            el.setAttributeNS('http://www.w3.org/1999/xlink', 'href', src);
-                    }
-                    else {
-                        // could be exporting in IE
-                        // using href throws "not supported" in ie7 and under,
-                        // requries regex shim to fix later
-                        el.setAttribute('hc-svg-href', src);
-                    }
-                }, onDummyLoad = function (e) {
-                    setSVGImageSource(elemWrapper.element, src);
-                    onload.call(elemWrapper, e);
-                };
-                // optional properties
-                if (arguments.length > 1) {
-                    extend(attribs, {
-                        x: x,
-                        y: y,
-                        width: width,
-                        height: height
-                    });
-                }
-                elemWrapper = this.createElement('image').attr(attribs);
-                // Add load event if supplied
-                if (onload) {
-                    // We have to use a dummy HTML image since IE support for SVG image
-                    // load events is very buggy. First set a transparent src, wait for
-                    // dummy to load, and then add the real src to the SVG image.
-                    setSVGImageSource(elemWrapper.element, 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==' /* eslint-disable-line */);
-                    dummy = new win.Image();
-                    addEvent(dummy, 'load', onDummyLoad);
-                    dummy.src = src;
-                    if (dummy.complete) {
-                        onDummyLoad({});
-                    }
-                }
-                else {
-                    setSVGImageSource(elemWrapper.element, src);
-                }
-                return elemWrapper;
-            };
-            /**
-             * Draw a symbol out of pre-defined shape paths from
-             * {@link SVGRenderer#symbols}.
-             * It is used in Highcharts for point makers, which cake a `symbol` option,
-             * and label and button backgrounds like in the tooltip and stock flags.
-             *
-             * @function Highcharts.SVGRenderer#symbol
-             *
-             * @param {string} symbol
-             * The symbol name.
-             *
-             * @param {number} [x]
-             * The X coordinate for the top left position.
-             *
-             * @param {number} [y]
-             * The Y coordinate for the top left position.
-             *
-             * @param {number} [width]
-             * The pixel width.
-             *
-             * @param {number} [height]
-             * The pixel height.
-             *
-             * @param {Highcharts.SymbolOptionsObject} [options]
-             * Additional options, depending on the actual symbol drawn.
-             *
-             * @return {Highcharts.SVGElement}
-             */
-            SVGRenderer.prototype.symbol = function (symbol, x, y, width, height, options) {
-                var ren = this,
-                    obj,
-                    imageRegex = /^url\((.*?)\)$/,
-                    isImage = imageRegex.test(symbol),
-                    sym = (!isImage && (this.symbols[symbol] ? symbol : 'circle')), 
-                    // get the symbol definition function
-                    symbolFn = (sym && this.symbols[sym]),
-                    path,
-                    imageSrc,
-                    centerImage;
-                if (symbolFn) {
-                    // Check if there's a path defined for this symbol
-                    if (typeof x === 'number') {
-                        path = symbolFn.call(this.symbols, Math.round(x || 0), Math.round(y || 0), width || 0, height || 0, options);
-                    }
-                    obj = this.path(path);
-                    if (!ren.styledMode) {
-                        obj.attr('fill', 'none');
-                    }
-                    // expando properties for use in animate and attr
-                    extend(obj, {
-                        symbolName: sym,
-                        x: x,
-                        y: y,
-                        width: width,
-                        height: height
-                    });
-                    if (options) {
-                        extend(obj, options);
-                    }
-                    // Image symbols
-                }
-                else if (isImage) {
-                    imageSrc = symbol.match(imageRegex)[1];
-                    // Create the image synchronously, add attribs async
-                    obj = this.image(imageSrc);
-                    // The image width is not always the same as the symbol width. The
-                    // image may be centered within the symbol, as is the case when
-                    // image shapes are used as label backgrounds, for example in flags.
-                    obj.imgwidth = pick(symbolSizes[imageSrc] && symbolSizes[imageSrc].width, options && options.width);
-                    obj.imgheight = pick(symbolSizes[imageSrc] && symbolSizes[imageSrc].height, options && options.height);
-                    /**
-                     * Set the size and position
-                     */
-                    centerImage = function () {
-                        obj.attr({
-                            width: obj.width,
-                            height: obj.height
-                        });
-                    };
-                    /**
-                     * Width and height setters that take both the image's physical size
-                     * and the label size into consideration, and translates the image
-                     * to center within the label.
-                     */
-                    ['width', 'height'].forEach(function (key) {
-                        obj[key + 'Setter'] = function (value, key) {
-                            var attribs = {}, imgSize = this['img' + key], trans = key === 'width' ? 'translateX' : 'translateY';
-                            this[key] = value;
-                            if (defined(imgSize)) {
-                                // Scale and center the image within its container.
-                                // The name `backgroundSize` is taken from the CSS spec,
-                                // but the value `within` is made up. Other possible
-                                // values in the spec, `cover` and `contain`, can be
-                                // implemented if needed.
-                                if (options &&
-                                    options.backgroundSize === 'within' &&
-                                    this.width &&
-                                    this.height) {
-                                    imgSize = Math.round(imgSize * Math.min(this.width / this.imgwidth, this.height / this.imgheight));
-                                }
-                                if (this.element) {
-                                    this.element.setAttribute(key, imgSize);
-                                }
-                                if (!this.alignByTranslate) {
-                                    attribs[trans] = ((this[key] || 0) - imgSize) / 2;
-                                    this.attr(attribs);
-                                }
-                            }
-                        };
-                    });
-                    if (defined(x)) {
-                        obj.attr({
-                            x: x,
-                            y: y
-                        });
-                    }
-                    obj.isImg = true;
-                    if (defined(obj.imgwidth) && defined(obj.imgheight)) {
-                        centerImage();
-                    }
-                    else {
-                        // Initialize image to be 0 size so export will still function
-                        // if there's no cached sizes.
-                        obj.attr({ width: 0, height: 0 });
-                        // Create a dummy JavaScript image to get the width and height.
-                        createElement('img', {
-                            onload: function () {
-                                var chart = charts[ren.chartIndex];
-                                // Special case for SVGs on IE11, the width is not
-                                // accessible until the image is part of the DOM
-                                // (#2854).
-                                if (this.width === 0) {
-                                    css(this, {
-                                        position: 'absolute',
-                                        top: '-999em'
-                                    });
-                                    doc.body.appendChild(this);
-                                }
-                                // Center the image
-                                symbolSizes[imageSrc] = {
-                                    width: this.width,
-                                    height: this.height
-                                };
-                                obj.imgwidth = this.width;
-                                obj.imgheight = this.height;
-                                if (obj.element) {
-                                    centerImage();
-                                }
-                                // Clean up after #2854 workaround.
-                                if (this.parentNode) {
-                                    this.parentNode.removeChild(this);
-                                }
-                                // Fire the load event when all external images are
-                                // loaded
-                                ren.imgCount--;
-                                if (!ren.imgCount && chart && !chart.hasLoaded) {
-                                    chart.onload();
-                                }
-                            },
-                            src: imageSrc
-                        });
-                        this.imgCount++;
-                    }
-                }
-                return obj;
-            };
-            /**
-             * Define a clipping rectangle. The clipping rectangle is later applied
-             * to {@link SVGElement} objects through the {@link SVGElement#clip}
-             * function.
-             *
-             * @example
-             * var circle = renderer.circle(100, 100, 100)
-             *     .attr({ fill: 'red' })
-             *     .add();
-             * var clipRect = renderer.clipRect(100, 100, 100, 100);
-             *
-             * // Leave only the lower right quarter visible
-             * circle.clip(clipRect);
-             *
-             * @function Highcharts.SVGRenderer#clipRect
-             *
-             * @param {number} [x]
-             *
-             * @param {number} [y]
-             *
-             * @param {number} [width]
-             *
-             * @param {number} [height]
-             *
-             * @return {Highcharts.ClipRectElement}
-             *         A clipping rectangle.
-             */
-            SVGRenderer.prototype.clipRect = function (x, y, width, height) {
-                var wrapper, 
-                    // Add a hyphen at the end to avoid confusion in testing indexes
-                    // -1 and -10, -11 etc (#6550)
-                    id = uniqueKey() + '-', clipPath = this.createElement('clipPath').attr({
-                        id: id
-                    }).add(this.defs);
-                wrapper = this.rect(x, y, width, height, 0).add(clipPath);
-                wrapper.id = id;
-                wrapper.clipPath = clipPath;
-                wrapper.count = 0;
-                return wrapper;
-            };
-            /**
-             * Draw text. The text can contain a subset of HTML, like spans and anchors
-             * and some basic text styling of these. For more advanced features like
-             * border and background, use {@link Highcharts.SVGRenderer#label} instead.
-             * To update the text after render, run `text.attr({ text: 'New text' })`.
-             *
-             * @sample highcharts/members/renderer-text-on-chart/
-             *         Annotate the chart freely
-             * @sample highcharts/members/renderer-on-chart/
-             *         Annotate with a border and in response to the data
-             * @sample highcharts/members/renderer-text/
-             *         Formatted text
-             *
-             * @function Highcharts.SVGRenderer#text
-             *
-             * @param {string} [str]
-             * The text of (subset) HTML to draw.
-             *
-             * @param {number} [x]
-             * The x position of the text's lower left corner.
-             *
-             * @param {number} [y]
-             * The y position of the text's lower left corner.
-             *
-             * @param {boolean} [useHTML=false]
-             * Use HTML to render the text.
-             *
-             * @return {Highcharts.SVGElement}
-             * The text object.
-             */
-            SVGRenderer.prototype.text = function (str, x, y, useHTML) {
-                // declare variables
-                var renderer = this,
-                    wrapper,
-                    attribs = {};
-                if (useHTML && (renderer.allowHTML || !renderer.forExport)) {
-                    return renderer.html(str, x, y);
-                }
-                attribs.x = Math.round(x || 0); // X always needed for line-wrap logic
-                if (y) {
-                    attribs.y = Math.round(y);
-                }
-                if (defined(str)) {
-                    attribs.text = str;
-                }
-                wrapper = renderer.createElement('text')
-                    .attr(attribs);
-                if (!useHTML) {
-                    wrapper.xSetter = function (value, key, element) {
-                        var tspans = element.getElementsByTagName('tspan'),
-                            tspan,
-                            parentVal = element.getAttribute(key),
-                            i;
-                        for (i = 0; i < tspans.length; i++) {
-                            tspan = tspans[i];
-                            // If the x values are equal, the tspan represents a
-                            // linebreak
-                            if (tspan.getAttribute(key) === parentVal) {
-                                tspan.setAttribute(key, value);
-                            }
-                        }
-                        element.setAttribute(key, value);
-                    };
-                }
-                return wrapper;
-            };
-            /**
-             * Utility to return the baseline offset and total line height from the font
-             * size.
-             *
-             * @function Highcharts.SVGRenderer#fontMetrics
-             *
-             * @param {number|string} [fontSize]
-             *        The current font size to inspect. If not given, the font size
-             *        will be found from the DOM element.
-             *
-             * @param {Highcharts.SVGElement|Highcharts.SVGDOMElement} [elem]
-             *        The element to inspect for a current font size.
-             *
-             * @return {Highcharts.FontMetricsObject}
-             *         The font metrics.
-             */
-            SVGRenderer.prototype.fontMetrics = function (fontSize, elem) {
-                var lineHeight,
-                    baseline;
-                if ((this.styledMode || !/px/.test(fontSize)) &&
-                    win.getComputedStyle // old IE doesn't support it
-                ) {
-                    fontSize = elem && SVGElement.prototype.getStyle.call(elem, 'font-size');
-                }
-                else {
-                    fontSize = fontSize ||
-                        // When the elem is a DOM element (#5932)
-                        (elem && elem.style && elem.style.fontSize) ||
-                        // Fall back on the renderer style default
-                        (this.style && this.style.fontSize);
-                }
-                // Handle different units
-                if (/px/.test(fontSize)) {
-                    fontSize = pInt(fontSize);
-                }
-                else {
-                    fontSize = 12;
-                }
-                // Empirical values found by comparing font size and bounding box
-                // height. Applies to the default font family.
-                // https://jsfiddle.net/highcharts/7xvn7/
-                lineHeight = fontSize < 24 ? fontSize + 3 : Math.round(fontSize * 1.2);
-                baseline = Math.round(lineHeight * 0.8);
-                return {
-                    h: lineHeight,
-                    b: baseline,
-                    f: fontSize
-                };
-            };
-            /**
-             * Correct X and Y positioning of a label for rotation (#1764).
-             *
-             * @private
-             * @function Highcharts.SVGRenderer#rotCorr
-             *
-             * @param {number} baseline
-             *
-             * @param {number} rotation
-             *
-             * @param {boolean} [alterY]
-             *
-             * @param {Highcharts.PositionObject}
-             */
-            SVGRenderer.prototype.rotCorr = function (baseline, rotation, alterY) {
-                var y = baseline;
-                if (rotation && alterY) {
-                    y = Math.max(y * Math.cos(rotation * deg2rad), 4);
-                }
-                return {
-                    x: (-baseline / 3) * Math.sin(rotation * deg2rad),
-                    y: y
-                };
-            };
-            /**
-             * Compatibility function to convert the legacy one-dimensional path array
-             * into an array of segments.
-             *
-             * It is used in maps to parse the `path` option, and in SVGRenderer.dSetter
-             * to support legacy paths from demos.
-             *
-             * @private
-             * @function Highcharts.SVGRenderer#pathToSegments
-             */
-            SVGRenderer.prototype.pathToSegments = function (path) {
-                var ret = [];
-                var segment = [];
-                var commandLength = {
-                        A: 8,
-                        C: 7,
-                        H: 2,
-                        L: 3,
-                        M: 3,
-                        Q: 5,
-                        S: 5,
-                        T: 3,
-                        V: 2
-                    };
-                // Short, non-typesafe parsing of the one-dimensional array. It splits
-                // the path on any string. This is not type checked against the tuple
-                // types, but is shorter, and doesn't require specific checks for any
-                // command type in SVG.
-                for (var i = 0; i < path.length; i++) {
-                    // Command skipped, repeat previous or insert L/l for M/m
-                    if (isString(segment[0]) &&
-                        isNumber(path[i]) &&
-                        segment.length === commandLength[(segment[0].toUpperCase())]) {
-                        path.splice(i, 0, segment[0].replace('M', 'L').replace('m', 'l'));
-                    }
-                    // Split on string
-                    if (typeof path[i] === 'string') {
-                        if (segment.length) {
-                            ret.push(segment.slice(0));
-                        }
-                        segment.length = 0;
-                    }
-                    segment.push(path[i]);
-                }
-                ret.push(segment.slice(0));
-                return ret;
-                /*
-                // Fully type-safe version where each tuple type is checked. The
-                // downside is filesize and a lack of flexibility for unsupported
-                // commands
-                const ret: SVGPath = [],
-                    commands = {
-                        A: 7,
-                        C: 6,
-                        H: 1,
-                        L: 2,
-                        M: 2,
-                        Q: 4,
-                        S: 4,
-                        T: 2,
-                        V: 1,
-                        Z: 0
-                    };
-
-                let i = 0,
-                    lastI = 0,
-                    lastCommand;
-
-                while (i < path.length) {
-                    const item = path[i];
-
-                    let command;
-
-                    if (typeof item === 'string') {
-                        command = item;
-                        i += 1;
-                    } else {
-                        command = lastCommand || 'M';
-                    }
-
-                    // Upper case
-                    const commandUC = command.toUpperCase();
-
-                    if (commandUC in commands) {
-
-                        // No numeric parameters
-                        if (command === 'Z' || command === 'z') {
-                            ret.push([command]);
-
-                        // One numeric parameter
-                        } else {
-                            const val0 = path[i];
-                            if (typeof val0 === 'number') {
-
-                                // Horizontal line to
-                                if (command === 'H' || command === 'h') {
-                                    ret.push([command, val0]);
-                                    i += 1;
-
-                                // Vertical line to
-                                } else if (command === 'V' || command === 'v') {
-                                    ret.push([command, val0]);
-                                    i += 1;
-
-                                // Two numeric parameters
-                                } else {
-                                    const val1 = path[i + 1];
-                                    if (typeof val1 === 'number') {
-                                        // lineTo
-                                        if (command === 'L' || command === 'l') {
-                                            ret.push([command, val0, val1]);
-                                            i += 2;
-
-                                        // moveTo
-                                        } else if (command === 'M' || command === 'm') {
-                                            ret.push([command, val0, val1]);
-                                            i += 2;
-
-                                        // Smooth quadratic bezier
-                                        } else if (command === 'T' || command === 't') {
-                                            ret.push([command, val0, val1]);
-                                            i += 2;
-
-                                        // Four numeric parameters
-                                        } else {
-                                            const val2 = path[i + 2],
-                                                val3 = path[i + 3];
-                                            if (
-                                                typeof val2 === 'number' &&
-                                                typeof val3 === 'number'
-                                            ) {
-                                                // Quadratic bezier to
-                                                if (
-                                                    command === 'Q' ||
-                                                    command === 'q'
-                                                ) {
-                                                    ret.push([
-                                                        command,
-                                                        val0,
-                                                        val1,
-                                                        val2,
-                                                        val3
-                                                    ]);
-                                                    i += 4;
-
-                                                // Smooth cubic bezier to
-                                                } else if (
-                                                    command === 'S' ||
-                                                    command === 's'
-                                                ) {
-                                                    ret.push([
-                                                        command,
-                                                        val0,
-                                                        val1,
-                                                        val2,
-                                                        val3
-                                                    ]);
-                                                    i += 4;
-
-                                                // Six numeric parameters
-                                                } else {
-                                                    const val4 = path[i + 4],
-                                                        val5 = path[i + 5];
-
-                                                    if (
-                                                        typeof val4 === 'number' &&
-                                                        typeof val5 === 'number'
-                                                    ) {
-                                                        // Curve to
-                                                        if (
-                                                            command === 'C' ||
-                                                            command === 'c'
-                                                        ) {
-                                                            ret.push([
-                                                                command,
-                                                                val0,
-                                                                val1,
-                                                                val2,
-                                                                val3,
-                                                                val4,
-                                                                val5
-                                                            ]);
-                                                            i += 6;
-
-                                                        // Seven numeric parameters
-                                                        } else {
-                                                            const val6 = path[i + 6];
-
-                                                            // Arc to
-                                                            if (
-                                                                typeof val6 ===
-                                                                'number' &&
-                                                                (
-                                                                    command === 'A' ||
-                                                                    command === 'a'
-                                                                )
-                                                            ) {
-                                                                ret.push([
-                                                                    command,
-                                                                    val0,
-                                                                    val1,
-                                                                    val2,
-                                                                    val3,
-                                                                    val4,
-                                                                    val5,
-                                                                    val6
-                                                                ]);
-                                                                i += 7;
-
-                                                            }
-
-                                                        }
-                                                    }
-                                                }
-                                            }
-                                        }
-                                    }
-
-                                }
-                            }
-                        }
-                    }
-
-                    // An unmarked command following a moveTo is a lineTo
-                    lastCommand = command === 'M' ? 'L' : command;
-
-                    if (i === lastI) {
-                        break;
-                    }
-                    lastI = i;
-                }
-                return ret;
-                */
-            };
-            /**
-             * Draw a label, which is an extended text element with support for border
-             * and background. Highcharts creates a `g` element with a text and a `path`
-             * or `rect` inside, to make it behave somewhat like a HTML div. Border and
-             * background are set through `stroke`, `stroke-width` and `fill` attributes
-             * using the {@link Highcharts.SVGElement#attr|attr} method. To update the
-             * text after render, run `label.attr({ text: 'New text' })`.
-             *
-             * @sample highcharts/members/renderer-label-on-chart/
-             *         A label on the chart
-             *
-             * @function Highcharts.SVGRenderer#label
-             *
-             * @param {string} str
-             *        The initial text string or (subset) HTML to render.
-             *
-             * @param {number} x
-             *        The x position of the label's left side.
-             *
-             * @param {number} [y]
-             *        The y position of the label's top side or baseline, depending on
-             *        the `baseline` parameter.
-             *
-             * @param {string} [shape='rect']
-             *        The shape of the label's border/background, if any. Defaults to
-             *        `rect`. Other possible values are `callout` or other shapes
-             *        defined in {@link Highcharts.SVGRenderer#symbols}.
-             *
-             * @param {number} [anchorX]
-             *        In case the `shape` has a pointer, like a flag, this is the
-             *        coordinates it should be pinned to.
-             *
-             * @param {number} [anchorY]
-             *        In case the `shape` has a pointer, like a flag, this is the
-             *        coordinates it should be pinned to.
-             *
-             * @param {boolean} [useHTML=false]
-             *        Wether to use HTML to render the label.
-             *
-             * @param {boolean} [baseline=false]
-             *        Whether to position the label relative to the text baseline,
-             *        like {@link Highcharts.SVGRenderer#text|renderer.text}, or to the
-             *        upper border of the rectangle.
-             *
-             * @param {string} [className]
-             *        Class name for the group.
-             *
-             * @return {Highcharts.SVGElement}
-             *         The generated label.
-             */
-            SVGRenderer.prototype.label = function (str, x, y, shape, anchorX, anchorY, useHTML, baseline, className) {
-                return new SVGLabel(this, str, x, y, shape, anchorX, anchorY, useHTML, baseline, className);
-            };
-            return SVGRenderer;
-        }());
+                  // When resizing rapidly, the same items
+                  // may be destroyed in different timeouts,
+                  // or the may be reactivated
+                  if (
+                    coll[forDestruction[i]] &&
+                    !coll[forDestruction[i]].isActive
+                  ) {
+                    coll[forDestruction[i]].destroy();
+                    delete coll[forDestruction[i]];
+                  }
+                }
+              };
+            objectEach(coll, function (tick, pos) {
+              if (!tick.isActive) {
+                // Render to zero opacity
+                tick.render(pos, false, 0);
+                tick.isActive = false;
+                forDestruction.push(pos);
+              }
+            });
+            // When the objects are finished fading out, destroy them
+            syncTimeout(
+              destroyInactiveItems,
+              coll === alternateBands || !chart.hasRendered || !delay
+                ? 0
+                : delay
+            );
+          });
+          // Set the axis line path
+          if (axisLine) {
+            axisLine[axisLine.isPlaced ? "animate" : "attr"]({
+              d: this.getLinePath(axisLine.strokeWidth()),
+            });
+            axisLine.isPlaced = true;
+            // Show or hide the line depending on options.showEmpty
+            axisLine[showAxis ? "show" : "hide"](showAxis);
+          }
+          if (axisTitle && showAxis) {
+            var titleXy = axis.getTitlePosition();
+            if (isNumber(titleXy.y)) {
+              axisTitle[axisTitle.isNew ? "attr" : "animate"](titleXy);
+              axisTitle.isNew = false;
+            } else {
+              axisTitle.attr("y", -9999);
+              axisTitle.isNew = true;
+            }
+          }
+          // Stacked totals:
+          if (stackLabelOptions && stackLabelOptions.enabled && axis.stacking) {
+            axis.stacking.renderStackTotals();
+          }
+          // End stacked totals
+          axis.isDirty = false;
+          fireEvent(this, "afterRender");
+        };
         /**
-         * A pointer to the renderer's associated Element class. The VMLRenderer
-         * will have a pointer to VMLElement here.
+         * Redraw the axis to reflect changes in the data or axis extremes. Called
+         * internally from Highcharts.Chart#redraw.
          *
-         * @name Highcharts.SVGRenderer#Element
-         * @type {Highcharts.SVGElement}
-         */
-        SVGRenderer.prototype.Element = SVGElement;
-        /**
          * @private
-         */
-        SVGRenderer.prototype.SVG_NS = SVG_NS;
-        /**
-         * Dummy function for plugins, called every time the renderer is updated.
-         * Prior to Highcharts 5, this was used for the canvg renderer.
-         *
-         * @deprecated
-         * @function Highcharts.SVGRenderer#draw
-         */
-        SVGRenderer.prototype.draw = noop;
+         * @function Highcharts.Axis#redraw
+         */
+        Axis.prototype.redraw = function () {
+          if (this.visible) {
+            // render the axis
+            this.render();
+            // move plot lines and bands
+            this.plotLinesAndBands.forEach(function (plotLine) {
+              plotLine.render();
+            });
+          }
+          // mark associated series as dirty and ready for redraw
+          this.series.forEach(function (series) {
+            series.isDirty = true;
+          });
+        };
         /**
-         * A collection of characters mapped to HTML entities. When `useHTML` on an
-         * element is true, these entities will be rendered correctly by HTML. In
-         * the SVG pseudo-HTML, they need to be unescaped back to simple characters,
-         * so for example `&lt;` will render as `<`.
+         * Returns an array of axis properties, that should be untouched during
+         * reinitialization.
          *
-         * @example
-         * // Add support for unescaping quotes
-         * Highcharts.SVGRenderer.prototype.escapes['"'] = '&quot;';
+         * @private
+         * @function Highcharts.Axis#getKeepProps
          *
-         * @name Highcharts.SVGRenderer#escapes
-         * @type {Highcharts.Dictionary<string>}
+         * @return {Array<string>}
          */
-        SVGRenderer.prototype.escapes = {
-            '&': '&amp;',
-            '<': '&lt;',
-            '>': '&gt;',
-            "'": '&#39;',
-            '"': '&quot;'
+        Axis.prototype.getKeepProps = function () {
+          return this.keepProps || Axis.keepProps;
         };
         /**
-         * An extendable collection of functions for defining symbol paths.
+         * Destroys an Axis instance. See {@link Axis#remove} for the API endpoint
+         * to fully remove the axis.
+         *
+         * @private
+         * @function Highcharts.Axis#destroy
          *
-         * @name Highcharts.SVGRenderer#symbols
-         * @type {Highcharts.SymbolDictionary}
+         * @param {boolean} [keepEvents]
+         * Whether to preserve events, used internally in Axis.update.
          */
-        SVGRenderer.prototype.symbols = {
-            circle: function (x, y, w, h) {
-                // Return a full arc
-                return this.arc(x + w / 2, y + h / 2, w / 2, h / 2, {
-                    start: Math.PI * 0.5,
-                    end: Math.PI * 2.5,
-                    open: false
-                });
-            },
-            square: function (x, y, w, h) {
-                return [
-                    ['M', x, y],
-                    ['L', x + w, y],
-                    ['L', x + w, y + h],
-                    ['L', x, y + h],
-                    ['Z']
-                ];
-            },
-            triangle: function (x, y, w, h) {
-                return [
-                    ['M', x + w / 2, y],
-                    ['L', x + w, y + h],
-                    ['L', x, y + h],
-                    ['Z']
-                ];
-            },
-            'triangle-down': function (x, y, w, h) {
-                return [
-                    ['M', x, y],
-                    ['L', x + w, y],
-                    ['L', x + w / 2, y + h],
-                    ['Z']
-                ];
-            },
-            diamond: function (x, y, w, h) {
-                return [
-                    ['M', x + w / 2, y],
-                    ['L', x + w, y + h / 2],
-                    ['L', x + w / 2, y + h],
-                    ['L', x, y + h / 2],
-                    ['Z']
-                ];
-            },
-            arc: function (x, y, w, h, options) {
-                var arc = [];
-                if (options) {
-                    var start = options.start || 0,
-                        end = options.end || 0,
-                        rx = options.r || w,
-                        ry = options.r || h || w,
-                        proximity = 0.001,
-                        fullCircle = Math.abs(end - start - 2 * Math.PI) <
-                            proximity, 
-                        // Substract a small number to prevent cos and sin of start and
-                        // end from becoming equal on 360 arcs (related: #1561)
-                        end = end - proximity,
-                        innerRadius = options.innerR,
-                        open = pick(options.open,
-                        fullCircle),
-                        cosStart = Math.cos(start),
-                        sinStart = Math.sin(start),
-                        cosEnd = Math.cos(end),
-                        sinEnd = Math.sin(end), 
-                        // Proximity takes care of rounding errors around PI (#6971)
-                        longArc = pick(options.longArc,
-                        end - start - Math.PI < proximity ? 0 : 1);
-                    arc.push([
-                        'M',
-                        x + rx * cosStart,
-                        y + ry * sinStart
-                    ], [
-                        'A',
-                        rx,
-                        ry,
-                        0,
-                        longArc,
-                        pick(options.clockwise, 1),
-                        x + rx * cosEnd,
-                        y + ry * sinEnd
-                    ]);
-                    if (defined(innerRadius)) {
-                        arc.push(open ?
-                            [
-                                'M',
-                                x + innerRadius * cosEnd,
-                                y + innerRadius * sinEnd
-                            ] : [
-                            'L',
-                            x + innerRadius * cosEnd,
-                            y + innerRadius * sinEnd
-                        ], [
-                            'A',
-                            innerRadius,
-                            innerRadius,
-                            0,
-                            longArc,
-                            // Clockwise - opposite to the outer arc clockwise
-                            defined(options.clockwise) ? 1 - options.clockwise : 0,
-                            x + innerRadius * cosStart,
-                            y + innerRadius * sinStart
-                        ]);
-                    }
-                    if (!open) {
-                        arc.push(['Z']);
-                    }
-                }
-                return arc;
-            },
-            /**
-             * Callout shape used for default tooltips, also used for rounded
-             * rectangles in VML
-             */
-            callout: function (x, y, w, h, options) {
-                var arrowLength = 6,
-                    halfDistance = 6,
-                    r = Math.min((options && options.r) || 0,
-                    w,
-                    h),
-                    safeDistance = r + halfDistance,
-                    anchorX = options && options.anchorX || 0,
-                    anchorY = options && options.anchorY || 0,
-                    path;
-                path = [
-                    ['M', x + r, y],
-                    ['L', x + w - r, y],
-                    ['C', x + w, y, x + w, y, x + w, y + r],
-                    ['L', x + w, y + h - r],
-                    ['C', x + w, y + h, x + w, y + h, x + w - r, y + h],
-                    ['L', x + r, y + h],
-                    ['C', x, y + h, x, y + h, x, y + h - r],
-                    ['L', x, y + r],
-                    ['C', x, y, x, y, x + r, y] // top-left corner
-                ];
-                // Anchor on right side
-                if (anchorX && anchorX > w) {
-                    // Chevron
-                    if (anchorY > y + safeDistance &&
-                        anchorY < y + h - safeDistance) {
-                        path.splice(3, 1, ['L', x + w, anchorY - halfDistance], ['L', x + w + arrowLength, anchorY], ['L', x + w, anchorY + halfDistance], ['L', x + w, y + h - r]);
-                        // Simple connector
-                    }
-                    else {
-                        path.splice(3, 1, ['L', x + w, h / 2], ['L', anchorX, anchorY], ['L', x + w, h / 2], ['L', x + w, y + h - r]);
-                    }
-                    // Anchor on left side
-                }
-                else if (anchorX && anchorX < 0) {
-                    // Chevron
-                    if (anchorY > y + safeDistance &&
-                        anchorY < y + h - safeDistance) {
-                        path.splice(7, 1, ['L', x, anchorY + halfDistance], ['L', x - arrowLength, anchorY], ['L', x, anchorY - halfDistance], ['L', x, y + r]);
-                        // Simple connector
-                    }
-                    else {
-                        path.splice(7, 1, ['L', x, h / 2], ['L', anchorX, anchorY], ['L', x, h / 2], ['L', x, y + r]);
-                    }
-                }
-                else if ( // replace bottom
-                anchorY &&
-                    anchorY > h &&
-                    anchorX > x + safeDistance &&
-                    anchorX < x + w - safeDistance) {
-                    path.splice(5, 1, ['L', anchorX + halfDistance, y + h], ['L', anchorX, y + h + arrowLength], ['L', anchorX - halfDistance, y + h], ['L', x + r, y + h]);
-                }
-                else if ( // replace top
-                anchorY &&
-                    anchorY < 0 &&
-                    anchorX > x + safeDistance &&
-                    anchorX < x + w - safeDistance) {
-                    path.splice(1, 1, ['L', anchorX - halfDistance, y], ['L', anchorX, y - arrowLength], ['L', anchorX + halfDistance, y], ['L', w - r, y]);
-                }
-                return path;
+        Axis.prototype.destroy = function (keepEvents) {
+          var axis = this,
+            plotLinesAndBands = axis.plotLinesAndBands,
+            plotGroup,
+            i;
+          fireEvent(this, "destroy", { keepEvents: keepEvents });
+          // Remove the events
+          if (!keepEvents) {
+            removeEvent(axis);
+          }
+          // Destroy collections
+          [axis.ticks, axis.minorTicks, axis.alternateBands].forEach(function (
+            coll
+          ) {
+            destroyObjectProperties(coll);
+          });
+          if (plotLinesAndBands) {
+            i = plotLinesAndBands.length;
+            while (i--) {
+              // #1975
+              plotLinesAndBands[i].destroy();
+            }
+          }
+          // Destroy elements
+          [
+            "axisLine",
+            "axisTitle",
+            "axisGroup",
+            "gridGroup",
+            "labelGroup",
+            "cross",
+            "scrollbar",
+          ].forEach(function (prop) {
+            if (axis[prop]) {
+              axis[prop] = axis[prop].destroy();
             }
+          });
+          // Destroy each generated group for plotlines and plotbands
+          for (plotGroup in axis.plotLinesAndBandsGroups) {
+            // eslint-disable-line guard-for-in
+            axis.plotLinesAndBandsGroups[plotGroup] =
+              axis.plotLinesAndBandsGroups[plotGroup].destroy();
+          }
+          // Delete all properties and fall back to the prototype.
+          objectEach(axis, function (val, key) {
+            if (axis.getKeepProps().indexOf(key) === -1) {
+              delete axis[key];
+            }
+          });
         };
-        H.SVGRenderer = SVGRenderer;
-        H.Renderer = H.SVGRenderer;
-
-        return H.Renderer;
-    });
-    _registerModule(_modules, 'Core/Renderer/HTML/HTMLElement.js', [_modules['Core/Globals.js'], _modules['Core/Renderer/SVG/SVGElement.js'], _modules['Core/Utilities.js']], function (H, SVGElement, U) {
-        /* *
-         *
-         *  (c) 2010-2020 Torstein Honsi
-         *
-         *  License: www.highcharts.com/license
-         *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
-         *
-         * */
-        var css = U.css,
-            defined = U.defined,
-            extend = U.extend,
-            pick = U.pick,
-            pInt = U.pInt;
         /**
-         * Element placebo
-         * @private
-         */
-        var HTMLElement = SVGElement;
-        var isFirefox = H.isFirefox;
-        /* eslint-disable valid-jsdoc */
-        // Extend SvgElement for useHTML option.
-        extend(HTMLElement.prototype, /** @lends SVGElement.prototype */ {
-            /**
-             * Apply CSS to HTML elements. This is used in text within SVG rendering and
-             * by the VML renderer
-             *
-             * @private
-             * @function Highcharts.SVGElement#htmlCss
-             *
-             * @param {Highcharts.CSSObject} styles
-             *
-             * @return {Highcharts.SVGElement}
-             */
-            htmlCss: function (styles) {
-                var wrapper = this,
-                    element = wrapper.element, 
-                    // When setting or unsetting the width style, we need to update
-                    // transform (#8809)
-                    isSettingWidth = (element.tagName === 'SPAN' &&
-                        styles &&
-                        'width' in styles),
-                    textWidth = pick(isSettingWidth && styles.width,
-                    void 0),
-                    doTransform;
-                if (isSettingWidth) {
-                    delete styles.width;
-                    wrapper.textWidth = textWidth;
-                    doTransform = true;
-                }
-                if (styles && styles.textOverflow === 'ellipsis') {
-                    styles.whiteSpace = 'nowrap';
-                    styles.overflow = 'hidden';
-                }
-                wrapper.styles = extend(wrapper.styles, styles);
-                css(wrapper.element, styles);
-                // Now that all styles are applied, to the transform
-                if (doTransform) {
-                    wrapper.htmlUpdateTransform();
-                }
-                return wrapper;
-            },
-            /**
-             * VML and useHTML method for calculating the bounding box based on offsets.
-             *
-             * @private
-             * @function Highcharts.SVGElement#htmlGetBBox
-             *
-             * @param {boolean} refresh
-             *        Whether to force a fresh value from the DOM or to use the cached
-             *        value.
-             *
-             * @return {Highcharts.BBoxObject}
-             *         A hash containing values for x, y, width and height.
-             */
-            htmlGetBBox: function () {
-                var wrapper = this,
-                    element = wrapper.element;
-                return {
-                    x: element.offsetLeft,
-                    y: element.offsetTop,
-                    width: element.offsetWidth,
-                    height: element.offsetHeight
-                };
-            },
-            /**
-             * VML override private method to update elements based on internal
-             * properties based on SVG transform.
-             *
-             * @private
-             * @function Highcharts.SVGElement#htmlUpdateTransform
-             * @return {void}
-             */
-            htmlUpdateTransform: function () {
-                // aligning non added elements is expensive
-                if (!this.added) {
-                    this.alignOnAdd = true;
-                    return;
-                }
-                var wrapper = this,
-                    renderer = wrapper.renderer,
-                    elem = wrapper.element,
-                    translateX = wrapper.translateX || 0,
-                    translateY = wrapper.translateY || 0,
-                    x = wrapper.x || 0,
-                    y = wrapper.y || 0,
-                    align = wrapper.textAlign || 'left',
-                    alignCorrection = {
-                        left: 0,
-                    center: 0.5,
-                    right: 1
-                    }[align],
-                    styles = wrapper.styles,
-                    whiteSpace = styles && styles.whiteSpace;
-                /**
-                 * @private
-                 * @return {number}
-                 */
-                function getTextPxLength() {
-                    // Reset multiline/ellipsis in order to read width (#4928,
-                    // #5417)
-                    css(elem, {
-                        width: '',
-                        whiteSpace: whiteSpace || 'nowrap'
-                    });
-                    return elem.offsetWidth;
-                }
-                // apply translate
-                css(elem, {
-                    marginLeft: translateX,
-                    marginTop: translateY
+         * Internal function to draw a crosshair.
+         *
+         * @function Highcharts.Axis#drawCrosshair
+         *
+         * @param {Highcharts.PointerEventObject} [e]
+         * The event arguments from the modified pointer event, extended with
+         * `chartX` and `chartY`
+         *
+         * @param {Highcharts.Point} [point]
+         * The Point object if the crosshair snaps to points.
+         *
+         * @fires Highcharts.Axis#event:afterDrawCrosshair
+         * @fires Highcharts.Axis#event:drawCrosshair
+         */
+        Axis.prototype.drawCrosshair = function (e, point) {
+          var path,
+            options = this.crosshair,
+            snap = pick(options.snap, true),
+            pos,
+            categorized,
+            graphic = this.cross,
+            crossOptions,
+            chart = this.chart;
+          fireEvent(this, "drawCrosshair", { e: e, point: point });
+          // Use last available event when updating non-snapped crosshairs without
+          // mouse interaction (#5287)
+          if (!e) {
+            e = this.cross && this.cross.e;
+          }
+          if (
+            // Disabled in options
+            !this.crosshair ||
+            // Snap
+            (defined(point) || !snap) === false
+          ) {
+            this.hideCrosshair();
+          } else {
+            // Get the path
+            if (!snap) {
+              pos =
+                e &&
+                (this.horiz
+                  ? e.chartX - this.pos
+                  : this.len - e.chartY + this.pos);
+            } else if (defined(point)) {
+              // #3834
+              pos = pick(
+                this.coll !== "colorAxis"
+                  ? point.crosshairPos // 3D axis extension
+                  : null,
+                this.isXAxis ? point.plotX : this.len - point.plotY
+              );
+            }
+            if (defined(pos)) {
+              crossOptions = {
+                // value, only used on radial
+                value:
+                  point &&
+                  (this.isXAxis ? point.x : pick(point.stackY, point.y)),
+                translatedValue: pos,
+              };
+              if (chart.polar) {
+                // Additional information required for crosshairs in
+                // polar chart
+                extend(crossOptions, {
+                  isCrosshair: true,
+                  chartX: e && e.chartX,
+                  chartY: e && e.chartY,
+                  point: point,
                 });
-                if (!renderer.styledMode && wrapper.shadows) { // used in labels/tooltip
-                    wrapper.shadows.forEach(function (shadow) {
-                        css(shadow, {
-                            marginLeft: translateX + 1,
-                            marginTop: translateY + 1
-                        });
-                    });
-                }
-                // apply inversion
-                if (wrapper.inverted) { // wrapper is a group
-                    [].forEach.call(elem.childNodes, function (child) {
-                        renderer.invertChild(child, elem);
-                    });
-                }
-                if (elem.tagName === 'SPAN') {
-                    var rotation = wrapper.rotation, baseline, textWidth = wrapper.textWidth && pInt(wrapper.textWidth), currentTextTransform = [
-                            rotation,
-                            align,
-                            elem.innerHTML,
-                            wrapper.textWidth,
-                            wrapper.textAlign
-                        ].join(',');
-                    // Update textWidth. Use the memoized textPxLength if possible, to
-                    // avoid the getTextPxLength function using elem.offsetWidth.
-                    // Calling offsetWidth affects rendering time as it forces layout
-                    // (#7656).
-                    if (textWidth !== wrapper.oldTextWidth &&
-                        ((textWidth > wrapper.oldTextWidth) ||
-                            (wrapper.textPxLength || getTextPxLength()) > textWidth) && (
-                    // Only set the width if the text is able to word-wrap, or
-                    // text-overflow is ellipsis (#9537)
-                    /[ \-]/.test(elem.textContent || elem.innerText) ||
-                        elem.style.textOverflow === 'ellipsis')) { // #983, #1254
-                        css(elem, {
-                            width: textWidth + 'px',
-                            display: 'block',
-                            whiteSpace: whiteSpace || 'normal' // #3331
-                        });
-                        wrapper.oldTextWidth = textWidth;
-                        wrapper.hasBoxWidthChanged = true; // #8159
-                    }
-                    else {
-                        wrapper.hasBoxWidthChanged = false; // #8159
-                    }
-                    // Do the calculations and DOM access only if properties changed
-                    if (currentTextTransform !== wrapper.cTT) {
-                        baseline = renderer.fontMetrics(elem.style.fontSize, elem).b;
-                        // Renderer specific handling of span rotation, but only if we
-                        // have something to update.
-                        if (defined(rotation) &&
-                            ((rotation !== (wrapper.oldRotation || 0)) ||
-                                (align !== wrapper.oldAlign))) {
-                            wrapper.setSpanRotation(rotation, alignCorrection, baseline);
-                        }
-                        wrapper.getSpanCorrection(
-                        // Avoid elem.offsetWidth if we can, it affects rendering
-                        // time heavily (#7656)
-                        ((!defined(rotation) && wrapper.textPxLength) || // #7920
-                            elem.offsetWidth), baseline, alignCorrection, rotation, align);
-                    }
-                    // apply position with correction
-                    css(elem, {
-                        left: (x + (wrapper.xCorr || 0)) + 'px',
-                        top: (y + (wrapper.yCorr || 0)) + 'px'
-                    });
-                    // record current text transform
-                    wrapper.cTT = currentTextTransform;
-                    wrapper.oldRotation = rotation;
-                    wrapper.oldAlign = align;
-                }
-            },
-            /**
-             * Set the rotation of an individual HTML span.
-             *
-             * @private
-             * @function Highcharts.SVGElement#setSpanRotation
-             * @param {number} rotation
-             * @param {number} alignCorrection
-             * @param {number} baseline
-             * @return {void}
-             */
-            setSpanRotation: function (rotation, alignCorrection, baseline) {
-                var rotationStyle = {},
-                    cssTransformKey = this.renderer.getTransformKey();
-                rotationStyle[cssTransformKey] = rotationStyle.transform =
-                    'rotate(' + rotation + 'deg)';
-                rotationStyle[cssTransformKey + (isFirefox ? 'Origin' : '-origin')] =
-                    rotationStyle.transformOrigin =
-                        (alignCorrection * 100) + '% ' + baseline + 'px';
-                css(this.element, rotationStyle);
-            },
-            /**
-             * Get the correction in X and Y positioning as the element is rotated.
-             *
-             * @private
-             * @function Highcharts.SVGElement#getSpanCorrection
-             * @param {number} width
-             * @param {number} baseline
-             * @param {number} alignCorrection
-             * @return {void}
-             */
-            getSpanCorrection: function (width, baseline, alignCorrection) {
-                this.xCorr = -width * alignCorrection;
-                this.yCorr = -baseline;
+              }
+              path = this.getPlotLinePath(crossOptions) || null; // #3189
             }
-        });
-
-        return HTMLElement;
-    });
-    _registerModule(_modules, 'Core/Renderer/HTML/HTMLRenderer.js', [_modules['Core/Globals.js'], _modules['Core/Renderer/SVG/SVGElement.js'], _modules['Core/Renderer/SVG/SVGRenderer.js'], _modules['Core/Utilities.js']], function (H, SVGElement, SVGRenderer, U) {
-        /* *
-         *
-         *  (c) 2010-2020 Torstein Honsi
-         *
-         *  License: www.highcharts.com/license
-         *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
-         *
-         * */
-        var isFirefox = H.isFirefox,
-            isMS = H.isMS,
-            isWebKit = H.isWebKit,
-            win = H.win;
-        var attr = U.attr,
-            createElement = U.createElement,
-            extend = U.extend,
-            pick = U.pick;
-        /**
-         * Renderer placebo
-         * @private
-         */
-        var HTMLRenderer = SVGRenderer;
-        /* eslint-disable valid-jsdoc */
-        // Extend SvgRenderer for useHTML option.
-        extend(SVGRenderer.prototype, /** @lends SVGRenderer.prototype */ {
-            /**
-             * @private
-             * @function Highcharts.SVGRenderer#getTransformKey
-             *
-             * @return {string}
-             */
-            getTransformKey: function () {
-                return isMS && !/Edge/.test(win.navigator.userAgent) ?
-                    '-ms-transform' :
-                    isWebKit ?
-                        '-webkit-transform' :
-                        isFirefox ?
-                            'MozTransform' :
-                            win.opera ?
-                                '-o-transform' :
-                                '';
-            },
-            /**
-             * Create HTML text node. This is used by the VML renderer as well as the
-             * SVG renderer through the useHTML option.
-             *
-             * @private
-             * @function Highcharts.SVGRenderer#html
-             *
-             * @param {string} str
-             *        The text of (subset) HTML to draw.
-             *
-             * @param {number} x
-             *        The x position of the text's lower left corner.
-             *
-             * @param {number} y
-             *        The y position of the text's lower left corner.
-             *
-             * @return {Highcharts.HTMLDOMElement}
-             */
-            html: function (str, x, y) {
-                var wrapper = this.createElement('span'), element = wrapper.element, renderer = wrapper.renderer, isSVG = renderer.isSVG, addSetters = function (gWrapper, style) {
-                        // These properties are set as attributes on the SVG group, and
-                        // as identical CSS properties on the div. (#3542)
-                        ['opacity', 'visibility'].forEach(function (prop) {
-                            gWrapper[prop + 'Setter'] = function (value, key, elem) {
-                                var styleObject = gWrapper.div ?
-                                    gWrapper.div.style :
-                                    style;
-                            SVGElement.prototype[prop + 'Setter']
-                                .call(this, value, key, elem);
-                            if (styleObject) {
-                                styleObject[key] = value;
-                            }
-                        };
-                    });
-                    gWrapper.addedSetters = true;
-                };
-                // Text setter
-                wrapper.textSetter = function (value) {
-                    if (value !== element.innerHTML) {
-                        delete this.bBox;
-                        delete this.oldTextWidth;
-                    }
-                    this.textStr = value;
-                    element.innerHTML = pick(value, '');
-                    wrapper.doTransform = true;
-                };
-                // Add setters for the element itself (#4938)
-                if (isSVG) { // #4938, only for HTML within SVG
-                    addSetters(wrapper, wrapper.element.style);
-                }
-                // Various setters which rely on update transform
-                wrapper.xSetter =
-                    wrapper.ySetter =
-                        wrapper.alignSetter =
-                            wrapper.rotationSetter =
-                                function (value, key) {
-                                    if (key === 'align') {
-                                        // Do not overwrite the SVGElement.align method. Same as VML.
-                                        wrapper.alignValue = wrapper.textAlign = value;
-                                    }
-                                    else {
-                                        wrapper[key] = value;
-                                    }
-                                    wrapper.doTransform = true;
-                                };
-                // Runs at the end of .attr()
-                wrapper.afterSetters = function () {
-                    // Update transform. Do this outside the loop to prevent redundant
-                    // updating for batch setting of attributes.
-                    if (this.doTransform) {
-                        this.htmlUpdateTransform();
-                        this.doTransform = false;
-                    }
-                };
-                // Set the default attributes
-                wrapper
-                    .attr({
-                    text: str,
-                    x: Math.round(x),
-                    y: Math.round(y)
+            if (!defined(path)) {
+              this.hideCrosshair();
+              return;
+            }
+            categorized = this.categories && !this.isRadial;
+            // Draw the cross
+            if (!graphic) {
+              this.cross = graphic = chart.renderer
+                .path()
+                .addClass(
+                  "highcharts-crosshair highcharts-crosshair-" +
+                    (categorized ? "category " : "thin ") +
+                    options.className
+                )
+                .attr({
+                  zIndex: pick(options.zIndex, 2),
                 })
-                    .css({
-                    position: 'absolute'
-                });
-                if (!renderer.styledMode) {
-                    wrapper.css({
-                        fontFamily: this.style.fontFamily,
-                        fontSize: this.style.fontSize
-                    });
-                }
-                // Keep the whiteSpace style outside the wrapper.styles collection
-                element.style.whiteSpace = 'nowrap';
-                // Use the HTML specific .css method
-                wrapper.css = wrapper.htmlCss;
-                // This is specific for HTML within SVG
-                if (isSVG) {
-                    wrapper.add = function (svgGroupWrapper) {
-                        var htmlGroup,
-                            container = renderer.box.parentNode,
-                            parentGroup,
-                            parents = [];
-                        this.parentGroup = svgGroupWrapper;
-                        // Create a mock group to hold the HTML elements
-                        if (svgGroupWrapper) {
-                            htmlGroup = svgGroupWrapper.div;
-                            if (!htmlGroup) {
-                                // Read the parent chain into an array and read from top
-                                // down
-                                parentGroup = svgGroupWrapper;
-                                while (parentGroup) {
-                                    parents.push(parentGroup);
-                                    // Move up to the next parent group
-                                    parentGroup = parentGroup.parentGroup;
-                                }
-                                // Ensure dynamically updating position when any parent
-                                // is translated
-                                parents.reverse().forEach(function (parentGroup) {
-                                    var htmlGroupStyle,
-                                        cls = attr(parentGroup.element, 'class');
-                                    /**
-                                     * Common translate setter for X and Y on the HTML
-                                     * group. Reverted the fix for #6957 du to
-                                     * positioning problems and offline export (#7254,
-                                     * #7280, #7529)
-                                     * @private
-                                     * @param {*} value
-                                     * @param {string} key
-                                     * @return {void}
-                                     */
-                                    function translateSetter(value, key) {
-                                        parentGroup[key] = value;
-                                        if (key === 'translateX') {
-                                            htmlGroupStyle.left = value + 'px';
-                                        }
-                                        else {
-                                            htmlGroupStyle.top = value + 'px';
-                                        }
-                                        parentGroup.doTransform = true;
-                                    }
-                                    // Create a HTML div and append it to the parent div
-                                    // to emulate the SVG group structure
-                                    htmlGroup =
-                                        parentGroup.div =
-                                            parentGroup.div || createElement('div', cls ? { className: cls } : void 0, {
-                                                position: 'absolute',
-                                                left: (parentGroup.translateX || 0) + 'px',
-                                                top: (parentGroup.translateY || 0) + 'px',
-                                                display: parentGroup.display,
-                                                opacity: parentGroup.opacity,
-                                                pointerEvents: (parentGroup.styles &&
-                                                    parentGroup.styles.pointerEvents) // #5595
-                                                // the top group is appended to container
-                                            }, htmlGroup || container);
-                                    // Shortcut
-                                    htmlGroupStyle = htmlGroup.style;
-                                    // Set listeners to update the HTML div's position
-                                    // whenever the SVG group position is changed.
-                                    extend(parentGroup, {
-                                        // (#7287) Pass htmlGroup to use
-                                        // the related group
-                                        classSetter: (function (htmlGroup) {
-                                            return function (value) {
-                                                this.element.setAttribute('class', value);
-                                                htmlGroup.className = value;
-                                            };
-                                        }(htmlGroup)),
-                                        on: function () {
-                                            if (parents[0].div) { // #6418
-                                                wrapper.on.apply({ element: parents[0].div }, arguments);
-                                            }
-                                            return parentGroup;
-                                        },
-                                        translateXSetter: translateSetter,
-                                        translateYSetter: translateSetter
-                                    });
-                                    if (!parentGroup.addedSetters) {
-                                        addSetters(parentGroup);
-                                    }
-                                });
-                            }
-                        }
-                        else {
-                            htmlGroup = container;
-                        }
-                        htmlGroup.appendChild(element);
-                        // Shared with VML:
-                        wrapper.added = true;
-                        if (wrapper.alignOnAdd) {
-                            wrapper.htmlUpdateTransform();
-                        }
-                        return wrapper;
-                    };
-                }
-                return wrapper;
+                .add();
+              // Presentational attributes
+              if (!chart.styledMode) {
+                graphic
+                  .attr({
+                    stroke:
+                      options.color ||
+                      (categorized
+                        ? Color.parse("#ccd6eb").setOpacity(0.25).get()
+                        : "#cccccc"),
+                    "stroke-width": pick(options.width, 1),
+                  })
+                  .css({
+                    "pointer-events": "none",
+                  });
+                if (options.dashStyle) {
+                  graphic.attr({
+                    dashstyle: options.dashStyle,
+                  });
+                }
+              }
             }
-        });
-
-        return HTMLRenderer;
-    });
-    _registerModule(_modules, 'Core/Axis/Tick.js', [_modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (H, U) {
-        /* *
-         *
-         *  (c) 2010-2020 Torstein Honsi
-         *
-         *  License: www.highcharts.com/license
-         *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
-         *
-         * */
-        /**
-         * Optional parameters for the tick.
-         * @private
-         * @interface Highcharts.TickParametersObject
-         */ /**
-        * Set category for the tick.
-        * @name Highcharts.TickParametersObject#category
-        * @type {string|undefined}
-        */ /**
-        * @name Highcharts.TickParametersObject#options
-        * @type {Highcharts.Dictionary<any>|undefined}
-        */ /**
-        * Set tickmarkOffset for the tick.
-        * @name Highcharts.TickParametersObject#tickmarkOffset
-        * @type {number|undefined}
-        */
-        var clamp = U.clamp,
-            correctFloat = U.correctFloat,
-            defined = U.defined,
-            destroyObjectProperties = U.destroyObjectProperties,
-            extend = U.extend,
-            fireEvent = U.fireEvent,
-            isNumber = U.isNumber,
-            merge = U.merge,
-            objectEach = U.objectEach,
-            pick = U.pick;
-        var deg2rad = H.deg2rad;
-        /* eslint-disable no-invalid-this, valid-jsdoc */
-        /**
-         * The Tick class.
-         *
-         * @class
-         * @name Highcharts.Tick
-         *
-         * @param {Highcharts.Axis} axis
-         * The axis of the tick.
-         *
-         * @param {number} pos
-         * The position of the tick on the axis in terms of axis values.
-         *
-         * @param {string} [type]
-         * The type of tick, either 'minor' or an empty string
-         *
-         * @param {boolean} [noLabel=false]
-         * Whether to disable the label or not. Defaults to false.
-         *
-         * @param {object} [parameters]
-         * Optional parameters for the tick.
-         */
-        var Tick = /** @class */ (function () {
-                /* *
-                 *
-                 *  Constructors
-                 *
-                 * */
-                function Tick(axis, pos, type, noLabel, parameters) {
-                    this.isNew = true;
-                this.isNewLabel = true;
-                /**
-                 * The related axis of the tick.
-                 * @name Highcharts.Tick#axis
-                 * @type {Highcharts.Axis}
-                 */
-                this.axis = axis;
-                /**
-                 * The logical position of the tick on the axis in terms of axis values.
-                 * @name Highcharts.Tick#pos
-                 * @type {number}
-                 */
-                this.pos = pos;
-                /**
-                 * The tick type, which can be `"minor"`, or an empty string.
-                 * @name Highcharts.Tick#type
-                 * @type {string}
-                 */
-                this.type = type || '';
-                this.parameters = parameters || {};
-                /**
-                 * The mark offset of the tick on the axis. Usually `undefined`, numeric
-                 * for grid axes.
-                 * @name Highcharts.Tick#tickmarkOffset
-                 * @type {number|undefined}
-                 */
-                this.tickmarkOffset = this.parameters.tickmarkOffset;
-                this.options = this.parameters.options;
-                fireEvent(this, 'init');
-                if (!type && !noLabel) {
-                    this.addLabel();
-                }
+            graphic.show().attr({
+              d: path,
+            });
+            if (categorized && !options.width) {
+              graphic.attr({
+                "stroke-width": this.transA,
+              });
             }
-            /* *
-             *
-             *  Functions
-             *
-             * */
-            /**
-             * Write the tick label.
-             *
-             * @private
-             * @function Highcharts.Tick#addLabel
-             * @return {void}
-             */
-            Tick.prototype.addLabel = function () {
-                var tick = this,
-                    axis = tick.axis,
-                    options = axis.options,
-                    chart = axis.chart,
-                    categories = axis.categories,
-                    log = axis.logarithmic,
-                    names = axis.names,
-                    pos = tick.pos,
-                    labelOptions = pick(tick.options && tick.options.labels,
-                    options.labels),
-                    str,
-                    tickPositions = axis.tickPositions,
-                    isFirst = pos === tickPositions[0],
-                    isLast = pos === tickPositions[tickPositions.length - 1],
-                    value = this.parameters.category || (categories ?
-                        pick(categories[pos],
-                    names[pos],
-                    pos) :
-                        pos),
-                    label = tick.label,
-                    animateLabels = (!labelOptions.step || labelOptions.step === 1) &&
-                        axis.tickInterval === 1,
-                    tickPositionInfo = tickPositions.info,
-                    dateTimeLabelFormat,
-                    dateTimeLabelFormats,
-                    i,
-                    list;
-                // Set the datetime label format. If a higher rank is set for this
-                // position, use that. If not, use the general format.
-                if (axis.dateTime && tickPositionInfo) {
-                    dateTimeLabelFormats = chart.time.resolveDTLFormat(options.dateTimeLabelFormats[(!options.grid &&
-                        tickPositionInfo.higherRanks[pos]) ||
-                        tickPositionInfo.unitName]);
-                    dateTimeLabelFormat = dateTimeLabelFormats.main;
-                }
-                // set properties for access in render method
-                /**
-                 * True if the tick is the first one on the axis.
-                 * @name Highcharts.Tick#isFirst
-                 * @readonly
-                 * @type {boolean|undefined}
-                 */
-                tick.isFirst = isFirst;
-                /**
-                 * True if the tick is the last one on the axis.
-                 * @name Highcharts.Tick#isLast
-                 * @readonly
-                 * @type {boolean|undefined}
-                 */
-                tick.isLast = isLast;
-                // Get the string
-                tick.formatCtx = {
-                    axis: axis,
-                    chart: chart,
-                    isFirst: isFirst,
-                    isLast: isLast,
-                    dateTimeLabelFormat: dateTimeLabelFormat,
-                    tickPositionInfo: tickPositionInfo,
-                    value: log ? correctFloat(log.lin2log(value)) : value,
-                    pos: pos
-                };
-                str = axis.labelFormatter.call(tick.formatCtx, this.formatCtx);
-                // Set up conditional formatting based on the format list if existing.
-                list = dateTimeLabelFormats && dateTimeLabelFormats.list;
-                if (list) {
-                    tick.shortenLabel = function () {
-                        for (i = 0; i < list.length; i++) {
-                            label.attr({
-                                text: axis.labelFormatter.call(extend(tick.formatCtx, { dateTimeLabelFormat: list[i] }))
-                            });
-                            if (label.getBBox().width <
-                                axis.getSlotWidth(tick) - 2 *
-                                    pick(labelOptions.padding, 5)) {
-                                return;
-                            }
-                        }
-                        label.attr({
-                            text: ''
-                        });
-                    };
-                }
-                // Call only after first render
-                if (animateLabels && axis._addedPlotLB) {
-                    tick.moveLabel(str, labelOptions);
-                }
-                // First call
-                if (!defined(label) && !tick.movedLabel) {
-                    /**
-                     * The rendered text label of the tick.
-                     * @name Highcharts.Tick#label
-                     * @type {Highcharts.SVGElement|undefined}
-                     */
-                    tick.label = label = tick.createLabel({ x: 0, y: 0 }, str, labelOptions);
-                    // Base value to detect change for new calls to getBBox
-                    tick.rotation = 0;
-                    // update
-                }
-                else if (label && label.textStr !== str && !animateLabels) {
-                    // When resetting text, also reset the width if dynamically set
-                    // (#8809)
-                    if (label.textWidth &&
-                        !(labelOptions.style && labelOptions.style.width) &&
-                        !label.styles.width) {
-                        label.css({ width: null });
-                    }
-                    label.attr({ text: str });
-                    label.textPxLength = label.getBBox().width;
-                }
-            };
-            /**
-             * Render and return the label of the tick.
-             *
-             * @private
-             * @function Highcharts.Tick#createLabel
-             * @param {Highcharts.PositionObject} xy
-             * @param {string} str
-             * @param {Highcharts.XAxisLabelsOptions} labelOptions
-             * @return {Highcharts.SVGElement|undefined}
-             */
-            Tick.prototype.createLabel = function (xy, str, labelOptions) {
-                var axis = this.axis,
-                    chart = axis.chart,
-                    label = defined(str) && labelOptions.enabled ?
-                        chart.renderer
-                            .text(str,
-                    xy.x,
-                    xy.y,
-                    labelOptions.useHTML)
-                            .add(axis.labelGroup) :
-                        null;
-                // Un-rotated length
-                if (label) {
-                    // Without position absolute, IE export sometimes is wrong
-                    if (!chart.styledMode) {
-                        label.css(merge(labelOptions.style));
-                    }
-                    label.textPxLength = label.getBBox().width;
-                }
-                return label;
-            };
-            /**
-             * Destructor for the tick prototype
-             *
-             * @private
-             * @function Highcharts.Tick#destroy
-             * @return {void}
-             */
-            Tick.prototype.destroy = function () {
-                destroyObjectProperties(this, this.axis);
-            };
-            /**
-             * Gets the x and y positions for ticks in terms of pixels.
-             *
-             * @private
-             * @function Highcharts.Tick#getPosition
-             *
-             * @param {boolean} horiz
-             * Whether the tick is on an horizontal axis or not.
-             *
-             * @param {number} tickPos
-             * Position of the tick.
-             *
-             * @param {number} tickmarkOffset
-             * Tickmark offset for all ticks.
-             *
-             * @param {boolean} [old]
-             * Whether the axis has changed or not.
-             *
-             * @return {Highcharts.PositionObject}
-             * The tick position.
-             *
-             * @fires Highcharts.Tick#event:afterGetPosition
-             */
-            Tick.prototype.getPosition = function (horiz, tickPos, tickmarkOffset, old) {
-                var axis = this.axis,
-                    chart = axis.chart,
-                    cHeight = (old && chart.oldChartHeight) || chart.chartHeight,
-                    pos;
-                pos = {
-                    x: horiz ?
-                        correctFloat(axis.translate(tickPos + tickmarkOffset, null, null, old) +
-                            axis.transB) :
-                        (axis.left +
-                            axis.offset +
-                            (axis.opposite ?
-                                (((old && chart.oldChartWidth) ||
-                                    chart.chartWidth) -
-                                    axis.right -
-                                    axis.left) :
-                                0)),
-                    y: horiz ?
-                        (cHeight -
-                            axis.bottom +
-                            axis.offset -
-                            (axis.opposite ? axis.height : 0)) :
-                        correctFloat(cHeight -
-                            axis.translate(tickPos + tickmarkOffset, null, null, old) -
-                            axis.transB)
-                };
-                // Chrome workaround for #10516
-                pos.y = clamp(pos.y, -1e5, 1e5);
-                fireEvent(this, 'afterGetPosition', { pos: pos });
-                return pos;
-            };
-            /**
-             * Get the x, y position of the tick label
-             *
-             * @private
-             * @return {Highcharts.PositionObject}
-             */
-            Tick.prototype.getLabelPosition = function (x, y, label, horiz, labelOptions, tickmarkOffset, index, step) {
-                var axis = this.axis,
-                    transA = axis.transA,
-                    reversed = ( // #7911
-                    axis.isLinked && axis.linkedParent ?
-                        axis.linkedParent.reversed :
-                        axis.reversed),
-                    staggerLines = axis.staggerLines,
-                    rotCorr = axis.tickRotCorr || { x: 0,
-                    y: 0 },
-                    yOffset = labelOptions.y, 
-                    // Adjust for label alignment if we use reserveSpace: true (#5286)
-                    labelOffsetCorrection = (!horiz && !axis.reserveSpaceDefault ?
-                        -axis.labelOffset * (axis.labelAlign === 'center' ? 0.5 : 1) :
-                        0),
-                    line,
-                    pos = {};
-                if (!defined(yOffset)) {
-                    if (axis.side === 0) {
-                        yOffset = label.rotation ? -8 : -label.getBBox().height;
-                    }
-                    else if (axis.side === 2) {
-                        yOffset = rotCorr.y + 8;
-                    }
-                    else {
-                        // #3140, #3140
-                        yOffset = Math.cos(label.rotation * deg2rad) *
-                            (rotCorr.y - label.getBBox(false, 0).height / 2);
-                    }
-                }
-                x = x +
-                    labelOptions.x +
-                    labelOffsetCorrection +
-                    rotCorr.x -
-                    (tickmarkOffset && horiz ?
-                        tickmarkOffset * transA * (reversed ? -1 : 1) :
-                        0);
-                y = y + yOffset - (tickmarkOffset && !horiz ?
-                    tickmarkOffset * transA * (reversed ? 1 : -1) : 0);
-                // Correct for staggered labels
-                if (staggerLines) {
-                    line = (index / (step || 1) % staggerLines);
-                    if (axis.opposite) {
-                        line = staggerLines - line - 1;
-                    }
-                    y += line * (axis.labelOffset / staggerLines);
-                }
-                pos.x = x;
-                pos.y = Math.round(y);
-                fireEvent(this, 'afterGetLabelPosition', { pos: pos, tickmarkOffset: tickmarkOffset, index: index });
-                return pos;
-            };
-            /**
-             * Get the offset height or width of the label
-             *
-             * @private
-             * @function Highcharts.Tick#getLabelSize
-             * @return {number}
-             */
-            Tick.prototype.getLabelSize = function () {
-                return this.label ?
-                    this.label.getBBox()[this.axis.horiz ? 'height' : 'width'] :
-                    0;
-            };
-            /**
-             * Extendible method to return the path of the marker
-             *
-             * @private
-             *
-             */
-            Tick.prototype.getMarkPath = function (x, y, tickLength, tickWidth, horiz, renderer) {
-                return renderer.crispLine([[
-                        'M',
-                        x,
-                        y
-                    ], [
-                        'L',
-                        x + (horiz ? 0 : -tickLength),
-                        y + (horiz ? tickLength : 0)
-                    ]], tickWidth);
-            };
-            /**
-             * Handle the label overflow by adjusting the labels to the left and right
-             * edge, or hide them if they collide into the neighbour label.
-             *
-             * @private
-             * @function Highcharts.Tick#handleOverflow
-             * @param {Highcharts.PositionObject} xy
-             * @return {void}
-             */
-            Tick.prototype.handleOverflow = function (xy) {
-                var tick = this,
-                    axis = this.axis,
-                    labelOptions = axis.options.labels,
-                    pxPos = xy.x,
-                    chartWidth = axis.chart.chartWidth,
-                    spacing = axis.chart.spacing,
-                    leftBound = pick(axis.labelLeft,
-                    Math.min(axis.pos,
-                    spacing[3])),
-                    rightBound = pick(axis.labelRight,
-                    Math.max(!axis.isRadial ? axis.pos + axis.len : 0,
-                    chartWidth - spacing[1])),
-                    label = this.label,
-                    rotation = this.rotation,
-                    factor = {
-                        left: 0,
-                        center: 0.5,
-                        right: 1
-                    }[axis.labelAlign || label.attr('align')],
-                    labelWidth = label.getBBox().width,
-                    slotWidth = axis.getSlotWidth(tick),
-                    modifiedSlotWidth = slotWidth,
-                    xCorrection = factor,
-                    goRight = 1,
-                    leftPos,
-                    rightPos,
-                    textWidth,
-                    css = {};
-                // Check if the label overshoots the chart spacing box. If it does, move
-                // it. If it now overshoots the slotWidth, add ellipsis.
-                if (!rotation &&
-                    pick(labelOptions.overflow, 'justify') === 'justify') {
-                    leftPos = pxPos - factor * labelWidth;
-                    rightPos = pxPos + (1 - factor) * labelWidth;
-                    if (leftPos < leftBound) {
-                        modifiedSlotWidth =
-                            xy.x + modifiedSlotWidth * (1 - factor) - leftBound;
-                    }
-                    else if (rightPos > rightBound) {
-                        modifiedSlotWidth =
-                            rightBound - xy.x + modifiedSlotWidth * factor;
-                        goRight = -1;
-                    }
-                    modifiedSlotWidth = Math.min(slotWidth, modifiedSlotWidth); // #4177
-                    if (modifiedSlotWidth < slotWidth && axis.labelAlign === 'center') {
-                        xy.x += (goRight *
-                            (slotWidth -
-                                modifiedSlotWidth -
-                                xCorrection * (slotWidth - Math.min(labelWidth, modifiedSlotWidth))));
-                    }
-                    // If the label width exceeds the available space, set a text width
-                    // to be picked up below. Also, if a width has been set before, we
-                    // need to set a new one because the reported labelWidth will be
-                    // limited by the box (#3938).
-                    if (labelWidth > modifiedSlotWidth ||
-                        (axis.autoRotation && (label.styles || {}).width)) {
-                        textWidth = modifiedSlotWidth;
-                    }
-                    // Add ellipsis to prevent rotated labels to be clipped against the edge
-                    // of the chart
-                }
-                else if (rotation < 0 &&
-                    pxPos - factor * labelWidth < leftBound) {
-                    textWidth = Math.round(pxPos / Math.cos(rotation * deg2rad) - leftBound);
-                }
-                else if (rotation > 0 &&
-                    pxPos + factor * labelWidth > rightBound) {
-                    textWidth = Math.round((chartWidth - pxPos) /
-                        Math.cos(rotation * deg2rad));
-                }
-                if (textWidth) {
-                    if (tick.shortenLabel) {
-                        tick.shortenLabel();
-                    }
-                    else {
-                        css.width = Math.floor(textWidth) + 'px';
-                        if (!(labelOptions.style || {}).textOverflow) {
-                            css.textOverflow = 'ellipsis';
-                        }
-                        label.css(css);
-                    }
-                }
-            };
-            /**
-             * Try to replace the label if the same one already exists.
-             *
-             * @private
-             * @function Highcharts.Tick#moveLabel
-             * @param {string} str
-             * @param {Highcharts.XAxisLabelsOptions} labelOptions
-             *
-             * @return {void}
-             */
-            Tick.prototype.moveLabel = function (str, labelOptions) {
-                var tick = this,
-                    label = tick.label,
-                    moved = false,
-                    axis = tick.axis,
-                    labelPos,
-                    reversed = axis.reversed,
-                    xPos,
-                    yPos;
-                if (label && label.textStr === str) {
-                    tick.movedLabel = label;
-                    moved = true;
-                    delete tick.label;
-                }
-                else { // Find a label with the same string
-                    objectEach(axis.ticks, function (currentTick) {
-                        if (!moved &&
-                            !currentTick.isNew &&
-                            currentTick !== tick &&
-                            currentTick.label &&
-                            currentTick.label.textStr === str) {
-                            tick.movedLabel = currentTick.label;
-                            moved = true;
-                            currentTick.labelPos = tick.movedLabel.xy;
-                            delete currentTick.label;
-                        }
-                    });
-                }
-                // Create new label if the actual one is moved
-                if (!moved && (tick.labelPos || label)) {
-                    labelPos = tick.labelPos || label.xy;
-                    xPos = axis.horiz ?
-                        (reversed ? 0 : axis.width + axis.left) : labelPos.x;
-                    yPos = axis.horiz ?
-                        labelPos.y : (reversed ? (axis.width + axis.left) : 0);
-                    tick.movedLabel = tick.createLabel({ x: xPos, y: yPos }, str, labelOptions);
-                    if (tick.movedLabel) {
-                        tick.movedLabel.attr({ opacity: 0 });
-                    }
-                }
-            };
-            /**
-             * Put everything in place
-             *
-             * @private
-             * @param {number} index
-             * @param {boolean} [old]
-             *        Use old coordinates to prepare an animation into new position
-             * @param {number} [opacity]
-             * @return {voids}
-             */
-            Tick.prototype.render = function (index, old, opacity) {
-                var tick = this,
-                    axis = tick.axis,
-                    horiz = axis.horiz,
-                    pos = tick.pos,
-                    tickmarkOffset = pick(tick.tickmarkOffset,
-                    axis.tickmarkOffset),
-                    xy = tick.getPosition(horiz,
-                    pos,
-                    tickmarkOffset,
-                    old),
-                    x = xy.x,
-                    y = xy.y,
-                    reverseCrisp = ((horiz && x === axis.pos + axis.len) ||
-                        (!horiz && y === axis.pos)) ? -1 : 1; // #1480, #1687
-                    opacity = pick(opacity, 1);
-                this.isActive = true;
-                // Create the grid line
-                this.renderGridLine(old, opacity, reverseCrisp);
-                // create the tick mark
-                this.renderMark(xy, opacity, reverseCrisp);
-                // the label is created on init - now move it into place
-                this.renderLabel(xy, old, opacity, index);
-                tick.isNew = false;
-                fireEvent(this, 'afterRender');
-            };
-            /**
-             * Renders the gridLine.
-             *
-             * @private
-             * @param {boolean} old  Whether or not the tick is old
-             * @param {number} opacity  The opacity of the grid line
-             * @param {number} reverseCrisp  Modifier for avoiding overlapping 1 or -1
-             * @return {void}
-             */
-            Tick.prototype.renderGridLine = function (old, opacity, reverseCrisp) {
-                var tick = this, axis = tick.axis, options = axis.options, gridLine = tick.gridLine, gridLinePath, attribs = {}, pos = tick.pos, type = tick.type, tickmarkOffset = pick(tick.tickmarkOffset, axis.tickmarkOffset), renderer = axis.chart.renderer, gridPrefix = type ? type + 'Grid' : 'grid', gridLineWidth = options[gridPrefix + 'LineWidth'], gridLineColor = options[gridPrefix + 'LineColor'], dashStyle = options[gridPrefix + 'LineDashStyle'];
-                if (!gridLine) {
-                    if (!axis.chart.styledMode) {
-                        attribs.stroke = gridLineColor;
-                        attribs['stroke-width'] = gridLineWidth;
-                        if (dashStyle) {
-                            attribs.dashstyle = dashStyle;
-                        }
-                    }
-                    if (!type) {
-                        attribs.zIndex = 1;
-                    }
-                    if (old) {
-                        opacity = 0;
-                    }
-                    /**
-                     * The rendered grid line of the tick.
-                     * @name Highcharts.Tick#gridLine
-                     * @type {Highcharts.SVGElement|undefined}
-                     */
-                    tick.gridLine = gridLine = renderer.path()
-                        .attr(attribs)
-                        .addClass('highcharts-' + (type ? type + '-' : '') + 'grid-line')
-                        .add(axis.gridGroup);
-                }
-                if (gridLine) {
-                    gridLinePath = axis.getPlotLinePath({
-                        value: pos + tickmarkOffset,
-                        lineWidth: gridLine.strokeWidth() * reverseCrisp,
-                        force: 'pass',
-                        old: old
-                    });
-                    // If the parameter 'old' is set, the current call will be followed
-                    // by another call, therefore do not do any animations this time
-                    if (gridLinePath) {
-                        gridLine[old || tick.isNew ? 'attr' : 'animate']({
-                            d: gridLinePath,
-                            opacity: opacity
-                        });
-                    }
-                }
-            };
-            /**
-             * Renders the tick mark.
-             *
-             * @private
-             * @param {Highcharts.PositionObject} xy  The position vector of the mark
-             * @param {number} opacity  The opacity of the mark
-             * @param {number} reverseCrisp  Modifier for avoiding overlapping 1 or -1
-             * @return {void}
-             */
-            Tick.prototype.renderMark = function (xy, opacity, reverseCrisp) {
-                var tick = this, axis = tick.axis, options = axis.options, renderer = axis.chart.renderer, type = tick.type, tickPrefix = type ? type + 'Tick' : 'tick', tickSize = axis.tickSize(tickPrefix), mark = tick.mark, isNewMark = !mark, x = xy.x, y = xy.y, tickWidth = pick(options[tickPrefix + 'Width'], !type && axis.isXAxis ? 1 : 0), // X axis defaults to 1
-                    tickColor = options[tickPrefix + 'Color'];
-                if (tickSize) {
-                    // negate the length
-                    if (axis.opposite) {
-                        tickSize[0] = -tickSize[0];
-                    }
-                    // First time, create it
-                    if (isNewMark) {
-                        /**
-                         * The rendered mark of the tick.
-                         * @name Highcharts.Tick#mark
-                         * @type {Highcharts.SVGElement|undefined}
-                         */
-                        tick.mark = mark = renderer.path()
-                            .addClass('highcharts-' + (type ? type + '-' : '') + 'tick')
-                            .add(axis.axisGroup);
-                        if (!axis.chart.styledMode) {
-                            mark.attr({
-                                stroke: tickColor,
-                                'stroke-width': tickWidth
-                            });
-                        }
-                    }
-                    mark[isNewMark ? 'attr' : 'animate']({
-                        d: tick.getMarkPath(x, y, tickSize[0], mark.strokeWidth() * reverseCrisp, axis.horiz, renderer),
-                        opacity: opacity
-                    });
-                }
-            };
-            /**
-             * Renders the tick label.
-             * Note: The label should already be created in init(), so it should only
-             * have to be moved into place.
-             *
-             * @private
-             * @param {Highcharts.PositionObject} xy  The position vector of the label
-             * @param {boolean} old  Whether or not the tick is old
-             * @param {number} opacity  The opacity of the label
-             * @param {number} index  The index of the tick
-             * @return {void}
-             */
-            Tick.prototype.renderLabel = function (xy, old, opacity, index) {
-                var tick = this,
-                    axis = tick.axis,
-                    horiz = axis.horiz,
-                    options = axis.options,
-                    label = tick.label,
-                    labelOptions = options.labels,
-                    step = labelOptions.step,
-                    tickmarkOffset = pick(tick.tickmarkOffset,
-                    axis.tickmarkOffset),
-                    show = true,
-                    x = xy.x,
-                    y = xy.y;
-                if (label && isNumber(x)) {
-                    label.xy = xy = tick.getLabelPosition(x, y, label, horiz, labelOptions, tickmarkOffset, index, step);
-                    // Apply show first and show last. If the tick is both first and
-                    // last, it is a single centered tick, in which case we show the
-                    // label anyway (#2100).
-                    if ((tick.isFirst &&
-                        !tick.isLast &&
-                        !pick(options.showFirstLabel, 1)) ||
-                        (tick.isLast &&
-                            !tick.isFirst &&
-                            !pick(options.showLastLabel, 1))) {
-                        show = false;
-                        // Handle label overflow and show or hide accordingly
-                    }
-                    else if (horiz &&
-                        !labelOptions.step &&
-                        !labelOptions.rotation &&
-                        !old &&
-                        opacity !== 0) {
-                        tick.handleOverflow(xy);
-                    }
-                    // apply step
-                    if (step && index % step) {
-                        // show those indices dividable by step
-                        show = false;
-                    }
-                    // Set the new position, and show or hide
-                    if (show && isNumber(xy.y)) {
-                        xy.opacity = opacity;
-                        label[tick.isNewLabel ? 'attr' : 'animate'](xy);
-                        tick.isNewLabel = false;
-                    }
-                    else {
-                        label.attr('y', -9999); // #1338
-                        tick.isNewLabel = true;
-                    }
-                }
-            };
-            /**
-             * Replace labels with the moved ones to perform animation. Additionally
-             * destroy unused labels.
-             *
-             * @private
-             * @function Highcharts.Tick#replaceMovedLabel
-             * @return {void}
-             */
-            Tick.prototype.replaceMovedLabel = function () {
-                var tick = this,
-                    label = tick.label,
-                    axis = tick.axis,
-                    reversed = axis.reversed,
-                    x,
-                    y;
-                // Animate and destroy
-                if (label && !tick.isNew) {
-                    x = axis.horiz ? (reversed ? axis.left : axis.width + axis.left) : label.xy.x;
-                    y = axis.horiz ?
-                        label.xy.y :
-                        (reversed ? axis.width + axis.top : axis.top);
-                    label.animate({ x: x, y: y, opacity: 0 }, void 0, label.destroy);
-                    delete tick.label;
-                }
-                axis.isDirty = true;
-                tick.label = tick.movedLabel;
-                delete tick.movedLabel;
-            };
-            return Tick;
-        }());
-        H.Tick = Tick;
-
-        return H.Tick;
-    });
-    _registerModule(_modules, 'Core/Time.js', [_modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (Highcharts, U) {
-        /* *
-         *
-         *  (c) 2010-2020 Torstein Honsi
-         *
-         *  License: www.highcharts.com/license
-         *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
-         *
-         * */
-        /**
-         * Normalized interval.
-         *
-         * @interface Highcharts.TimeNormalizedObject
-         */ /**
-        * The count.
-        *
-        * @name Highcharts.TimeNormalizedObject#count
-        * @type {number}
-        */ /**
-        * The interval in axis values (ms).
-        *
-        * @name Highcharts.TimeNormalizedObject#unitRange
-        * @type {number}
-        */
-        /**
-         * Function of an additional date format specifier.
-         *
-         * @callback Highcharts.TimeFormatCallbackFunction
-         *
-         * @param {number} timestamp
-         *        The time to format.
-         *
-         * @return {string}
-         *         The formatted portion of the date.
-         */
-        /**
-         * Additonal time tick information.
-         *
-         * @interface Highcharts.TimeTicksInfoObject
-         * @extends Highcharts.TimeNormalizedObject
-         */ /**
-        * @name Highcharts.TimeTicksInfoObject#higherRanks
-        * @type {Array<string>}
-        */ /**
-        * @name Highcharts.TimeTicksInfoObject#totalRange
-        * @type {number}
-        */
-        /**
-         * Time ticks.
-         *
-         * @interface Highcharts.AxisTickPositionsArray
-         * @extends global.Array<number>
-         */ /**
-        * @name Highcharts.AxisTickPositionsArray#info
-        * @type {Highcharts.TimeTicksInfoObject|undefined}
-        */
-        /**
-         * A callback to return the time zone offset for a given datetime. It
-         * takes the timestamp in terms of milliseconds since January 1 1970,
-         * and returns the timezone offset in minutes. This provides a hook
-         * for drawing time based charts in specific time zones using their
-         * local DST crossover dates, with the help of external libraries.
-         *
-         * @callback Highcharts.TimezoneOffsetCallbackFunction
-         *
-         * @param {number} timestamp
-         * Timestamp in terms of milliseconds since January 1 1970.
-         *
-         * @return {number}
-         * Timezone offset in minutes.
-         */
-        /**
-         * Allows to manually load the `moment.js` library from Highcharts options
-         * instead of the `window`.
-         * In case of loading the library from a `script` tag,
-         * this option is not needed, it will be loaded from there by default.
-         *
-         * @type {function}
-         * @since 8.2.0
-         * @apioption time.moment
-         */
-        var defined = U.defined,
-            error = U.error,
-            extend = U.extend,
-            isObject = U.isObject,
-            merge = U.merge,
-            objectEach = U.objectEach,
-            pad = U.pad,
-            pick = U.pick,
-            splat = U.splat,
-            timeUnits = U.timeUnits;
-        var H = Highcharts,
-            win = H.win;
-        /* eslint-disable no-invalid-this, valid-jsdoc */
-        /**
-         * The Time class. Time settings are applied in general for each page using
-         * `Highcharts.setOptions`, or individually for each Chart item through the
-         * [time](https://api.highcharts.com/highcharts/time) options set.
-         *
-         * The Time object is available from {@link Highcharts.Chart#time},
-         * which refers to  `Highcharts.time` if no individual time settings are
-         * applied.
-         *
-         * @example
-         * // Apply time settings globally
-         * Highcharts.setOptions({
-         *     time: {
-         *         timezone: 'Europe/London'
-         *     }
-         * });
-         *
-         * // Apply time settings by instance
-         * var chart = Highcharts.chart('container', {
-         *     time: {
-         *         timezone: 'America/New_York'
-         *     },
-         *     series: [{
-         *         data: [1, 4, 3, 5]
-         *     }]
-         * });
-         *
-         * // Use the Time object
-         * console.log(
-         *        'Current time in New York',
-         *        chart.time.dateFormat('%Y-%m-%d %H:%M:%S', Date.now())
-         * );
-         *
-         * @since 6.0.5
-         *
-         * @class
-         * @name Highcharts.Time
-         *
-         * @param {Highcharts.TimeOptions} options
-         * Time options as defined in [chart.options.time](/highcharts/time).
-         */
-        var Time = /** @class */ (function () {
-                /* *
-                 *
-                 *  Constructors
-                 *
-                 * */
-                function Time(options) {
-                    /* *
-                     *
-                     *  Properties
-                     *
-                     * */
-                    this.options = {};
-                this.useUTC = false;
-                this.variableTimezone = false;
-                this.Date = win.Date;
-                /**
-                 * Get the time zone offset based on the current timezone information as
-                 * set in the global options.
-                 *
-                 * @function Highcharts.Time#getTimezoneOffset
-                 *
-                 * @param {number} timestamp
-                 *        The JavaScript timestamp to inspect.
-                 *
-                 * @return {number}
-                 *         The timezone offset in minutes compared to UTC.
-                 */
-                this.getTimezoneOffset = this.timezoneOffsetFunction();
-                this.update(options);
-            }
-            /* *
-             *
-             *  Functions
-             *
-             * */
-            /**
-             * Time units used in `Time.get` and `Time.set`
-             *
-             * @typedef {"Date"|"Day"|"FullYear"|"Hours"|"Milliseconds"|"Minutes"|"Month"|"Seconds"} Highcharts.TimeUnitValue
-             */
-            /**
-             * Get the value of a date object in given units, and subject to the Time
-             * object's current timezone settings. This function corresponds directly to
-             * JavaScripts `Date.getXXX / Date.getUTCXXX`, so instead of calling
-             * `date.getHours()` or `date.getUTCHours()` we will call
-             * `time.get('Hours')`.
-             *
-             * @function Highcharts.Time#get
-             *
-             * @param {Highcharts.TimeUnitValue} unit
-             * @param {Date} date
-             *
-             * @return {number}
-             *        The given time unit
-             */
-            Time.prototype.get = function (unit, date) {
-                if (this.variableTimezone || this.timezoneOffset) {
-                    var realMs = date.getTime();
-                    var ms = realMs - this.getTimezoneOffset(date);
-                    date.setTime(ms); // Temporary adjust to timezone
-                    var ret = date['getUTC' + unit]();
-                    date.setTime(realMs); // Reset
-                    return ret;
-                }
-                // UTC time with no timezone handling
-                if (this.useUTC) {
-                    return date['getUTC' + unit]();
-                }
-                // Else, local time
-                return date['get' + unit]();
-            };
-            /**
-             * Set the value of a date object in given units, and subject to the Time
-             * object's current timezone settings. This function corresponds directly to
-             * JavaScripts `Date.setXXX / Date.setUTCXXX`, so instead of calling
-             * `date.setHours(0)` or `date.setUTCHours(0)` we will call
-             * `time.set('Hours', 0)`.
-             *
-             * @function Highcharts.Time#set
-             *
-             * @param {Highcharts.TimeUnitValue} unit
-             * @param {Date} date
-             * @param {number} value
-             *
-             * @return {number}
-             *        The epoch milliseconds of the updated date
-             */
-            Time.prototype.set = function (unit, date, value) {
-                // UTC time with timezone handling
-                if (this.variableTimezone || this.timezoneOffset) {
-                    // For lower order time units, just set it directly using UTC
-                    // time
-                    if (unit === 'Milliseconds' ||
-                        unit === 'Seconds' ||
-                        unit === 'Minutes') {
-                        return date['setUTC' + unit](value);
-                    }
-                    // Higher order time units need to take the time zone into
-                    // account
-                    // Adjust by timezone
-                    var offset = this.getTimezoneOffset(date);
-                    var ms = date.getTime() - offset;
-                    date.setTime(ms);
-                    date['setUTC' + unit](value);
-                    var newOffset = this.getTimezoneOffset(date);
-                    ms = date.getTime() + newOffset;
-                    return date.setTime(ms);
-                }
-                // UTC time with no timezone handling
-                if (this.useUTC) {
-                    return date['setUTC' + unit](value);
-                }
-                // Else, local time
-                return date['set' + unit](value);
-            };
-            /**
-             * Update the Time object with current options. It is called internally on
-             * initializing Highcharts, after running `Highcharts.setOptions` and on
-             * `Chart.update`.
-             *
-             * @private
-             * @function Highcharts.Time#update
-             *
-             * @param {Highcharts.TimeOptions} options
-             *
-             * @return {void}
-             */
-            Time.prototype.update = function (options) {
-                var useUTC = pick(options && options.useUTC,
-                    true),
-                    time = this;
-                this.options = options = merge(true, this.options || {}, options);
-                // Allow using a different Date class
-                this.Date = options.Date || win.Date || Date;
-                this.useUTC = useUTC;
-                this.timezoneOffset = (useUTC && options.timezoneOffset);
-                this.getTimezoneOffset = this.timezoneOffsetFunction();
-                /*
-                 * The time object has options allowing for variable time zones, meaning
-                 * the axis ticks or series data needs to consider this.
-                 */
-                this.variableTimezone = !!(!useUTC ||
-                    options.getTimezoneOffset ||
-                    options.timezone);
-            };
-            /**
-             * Make a time and returns milliseconds. Interprets the inputs as UTC time,
-             * local time or a specific timezone time depending on the current time
-             * settings.
-             *
-             * @function Highcharts.Time#makeTime
-             *
-             * @param {number} year
-             *        The year
-             *
-             * @param {number} month
-             *        The month. Zero-based, so January is 0.
-             *
-             * @param {number} [date=1]
-             *        The day of the month
-             *
-             * @param {number} [hours=0]
-             *        The hour of the day, 0-23.
-             *
-             * @param {number} [minutes=0]
-             *        The minutes
-             *
-             * @param {number} [seconds=0]
-             *        The seconds
-             *
-             * @return {number}
-             *         The time in milliseconds since January 1st 1970.
-             */
-            Time.prototype.makeTime = function (year, month, date, hours, minutes, seconds) {
-                var d,
-                    offset,
-                    newOffset;
-                if (this.useUTC) {
-                    d = this.Date.UTC.apply(0, arguments);
-                    offset = this.getTimezoneOffset(d);
-                    d += offset;
-                    newOffset = this.getTimezoneOffset(d);
-                    if (offset !== newOffset) {
-                        d += newOffset - offset;
-                        // A special case for transitioning from summer time to winter time.
-                        // When the clock is set back, the same time is repeated twice, i.e.
-                        // 02:30 am is repeated since the clock is set back from 3 am to
-                        // 2 am. We need to make the same time as local Date does.
-                    }
-                    else if (offset - 36e5 === this.getTimezoneOffset(d - 36e5) &&
-                        !H.isSafari) {
-                        d -= 36e5;
-                    }
-                }
-                else {
-                    d = new this.Date(year, month, pick(date, 1), pick(hours, 0), pick(minutes, 0), pick(seconds, 0)).getTime();
-                }
-                return d;
-            };
-            /**
-             * Sets the getTimezoneOffset function. If the `timezone` option is set, a
-             * default getTimezoneOffset function with that timezone is returned. If
-             * a `getTimezoneOffset` option is defined, it is returned. If neither are
-             * specified, the function using the `timezoneOffset` option or 0 offset is
-             * returned.
-             *
-             * @private
-             * @function Highcharts.Time#timezoneOffsetFunction
-             *
-             * @return {Function}
-             *         A getTimezoneOffset function
-             */
-            Time.prototype.timezoneOffsetFunction = function () {
-                var time = this,
-                    options = this.options,
-                    moment = options.moment || win.moment;
-                if (!this.useUTC) {
-                    return function (timestamp) {
-                        return new Date(timestamp.toString()).getTimezoneOffset() * 60000;
-                    };
-                }
-                if (options.timezone) {
-                    if (!moment) {
-                        // getTimezoneOffset-function stays undefined because it depends
-                        // on Moment.js
-                        error(25);
-                    }
-                    else {
-                        return function (timestamp) {
-                            return -moment.tz(timestamp, options.timezone).utcOffset() * 60000;
-                        };
-                    }
-                }
-                // If not timezone is set, look for the getTimezoneOffset callback
-                if (this.useUTC && options.getTimezoneOffset) {
-                    return function (timestamp) {
-                        return options.getTimezoneOffset(timestamp.valueOf()) * 60000;
-                    };
-                }
-                // Last, use the `timezoneOffset` option if set
-                return function () {
-                    return (time.timezoneOffset || 0) * 60000;
-                };
-            };
-            /**
-             * Formats a JavaScript date timestamp (milliseconds since Jan 1st 1970)
-             * into a human readable date string. The available format keys are listed
-             * below. Additional formats can be given in the
-             * {@link Highcharts.dateFormats} hook.
-             *
-             * Supported format keys:
-             * - `%a`: Short weekday, like 'Mon'
-             * - `%A`: Long weekday, like 'Monday'
-             * - `%d`: Two digit day of the month, 01 to 31
-             * - `%e`: Day of the month, 1 through 31
-             * - `%w`: Day of the week, 0 through 6
-             * - `%b`: Short month, like 'Jan'
-             * - `%B`: Long month, like 'January'
-             * - `%m`: Two digit month number, 01 through 12
-             * - `%y`: Two digits year, like 09 for 2009
-             * - `%Y`: Four digits year, like 2009
-             * - `%H`: Two digits hours in 24h format, 00 through 23
-             * - `%k`: Hours in 24h format, 0 through 23
-             * - `%I`: Two digits hours in 12h format, 00 through 11
-             * - `%l`: Hours in 12h format, 1 through 12
-             * - `%M`: Two digits minutes, 00 through 59
-             * - `%p`: Upper case AM or PM
-             * - `%P`: Lower case AM or PM
-             * - `%S`: Two digits seconds, 00 through 59
-             * - `%L`: Milliseconds (naming from Ruby)
-             *
-             * @example
-             * const time = new Highcharts.Time();
-             * const s = time.dateFormat('%Y-%m-%d %H:%M:%S', Date.UTC(2020, 0, 1));
-             * console.log(s); // => 2020-01-01 00:00:00
-             *
-             * @function Highcharts.Time#dateFormat
-             *
-             * @param {string} format
-             *        The desired format where various time representations are
-             *        prefixed with %.
-             *
-             * @param {number} timestamp
-             *        The JavaScript timestamp.
-             *
-             * @param {boolean} [capitalize=false]
-             *        Upper case first letter in the return.
-             *
-             * @return {string}
-             *         The formatted date.
-             */
-            Time.prototype.dateFormat = function (format, timestamp, capitalize) {
-                var _a;
-                if (!defined(timestamp) || isNaN(timestamp)) {
-                    return ((_a = H.defaultOptions.lang) === null || _a === void 0 ? void 0 : _a.invalidDate) || '';
-                }
-                format = pick(format, '%Y-%m-%d %H:%M:%S');
-                var time = this, date = new this.Date(timestamp), 
-                    // get the basic time values
-                    hours = this.get('Hours', date), day = this.get('Day', date), dayOfMonth = this.get('Date', date), month = this.get('Month', date), fullYear = this.get('FullYear', date), lang = H.defaultOptions.lang, langWeekdays = lang === null || lang === void 0 ? void 0 : lang.weekdays, shortWeekdays = lang === null || lang === void 0 ? void 0 : lang.shortWeekdays, 
-                    // List all format keys. Custom formats can be added from the
-                    // outside.
-                    replacements = extend({
-                        // Day
-                        // Short weekday, like 'Mon'
-                        a: shortWeekdays ?
-                            shortWeekdays[day] :
-                            langWeekdays[day].substr(0, 3),
-                        // Long weekday, like 'Monday'
-                        A: langWeekdays[day],
-                        // Two digit day of the month, 01 to 31
-                        d: pad(dayOfMonth),
-                        // Day of the month, 1 through 31
-                        e: pad(dayOfMonth, 2, ' '),
-                        // Day of the week, 0 through 6
-                        w: day,
-                        // Week (none implemented)
-                        // 'W': weekNumber(),
-                        // Month
-                        // Short month, like 'Jan'
-                        b: lang.shortMonths[month],
-                        // Long month, like 'January'
-                        B: lang.months[month],
-                        // Two digit month number, 01 through 12
-                        m: pad(month + 1),
-                        // Month number, 1 through 12 (#8150)
-                        o: month + 1,
-                        // Year
-                        // Two digits year, like 09 for 2009
-                        y: fullYear.toString().substr(2, 2),
-                        // Four digits year, like 2009
-                        Y: fullYear,
-                        // Time
-                        // Two digits hours in 24h format, 00 through 23
-                        H: pad(hours),
-                        // Hours in 24h format, 0 through 23
-                        k: hours,
-                        // Two digits hours in 12h format, 00 through 11
-                        I: pad((hours % 12) || 12),
-                        // Hours in 12h format, 1 through 12
-                        l: (hours % 12) || 12,
-                        // Two digits minutes, 00 through 59
-                        M: pad(this.get('Minutes', date)),
-                        // Upper case AM or PM
-                        p: hours < 12 ? 'AM' : 'PM',
-                        // Lower case AM or PM
-                        P: hours < 12 ? 'am' : 'pm',
-                        // Two digits seconds, 00 through  59
-                        S: pad(date.getSeconds()),
-                        // Milliseconds (naming from Ruby)
-                        L: pad(Math.floor(timestamp % 1000), 3)
-                    }, H.dateFormats);
-                // Do the replaces
-                objectEach(replacements, function (val, key) {
-                    // Regex would do it in one line, but this is faster
-                    while (format.indexOf('%' + key) !== -1) {
-                        format = format.replace('%' + key, typeof val === 'function' ? val.call(time, timestamp) : val);
-                    }
-                });
-                // Optionally capitalize the string and return
-                return capitalize ?
-                    (format.substr(0, 1).toUpperCase() +
-                        format.substr(1)) :
-                    format;
-            };
-            /**
-             * Resolve legacy formats of dateTimeLabelFormats (strings and arrays) into
-             * an object.
-             * @private
-             * @param {string|Array<T>|Highcharts.Dictionary<T>} f - General format description
-             * @return {Highcharts.Dictionary<T>} - The object definition
-             */
-            Time.prototype.resolveDTLFormat = function (f) {
-                if (!isObject(f, true)) { // check for string or array
-                    f = splat(f);
-                    return {
-                        main: f[0],
-                        from: f[1],
-                        to: f[2]
-                    };
-                }
-                return f;
-            };
-            /**
-             * Return an array with time positions distributed on round time values
-             * right and right after min and max. Used in datetime axes as well as for
-             * grouping data on a datetime axis.
-             *
-             * @function Highcharts.Time#getTimeTicks
-             *
-             * @param {Highcharts.TimeNormalizedObject} normalizedInterval
-             *        The interval in axis values (ms) and the count
-             *
-             * @param {number} [min]
-             *        The minimum in axis values
-             *
-             * @param {number} [max]
-             *        The maximum in axis values
-             *
-             * @param {number} [startOfWeek=1]
-             *
-             * @return {Highcharts.AxisTickPositionsArray}
-             */
-            Time.prototype.getTimeTicks = function (normalizedInterval, min, max, startOfWeek) {
-                var time = this,
-                    Date = time.Date,
-                    tickPositions = [],
-                    i,
-                    higherRanks = {},
-                    minYear, // used in months and years as a basis for Date.UTC()
-                    // When crossing DST, use the max. Resolves #6278.
-                    minDate = new Date(min),
-                    interval = normalizedInterval.unitRange,
-                    count = normalizedInterval.count || 1,
-                    variableDayLength,
-                    minDay;
-                startOfWeek = pick(startOfWeek, 1);
-                if (defined(min)) { // #1300
-                    time.set('Milliseconds', minDate, interval >= timeUnits.second ?
-                        0 : // #3935
-                        count * Math.floor(time.get('Milliseconds', minDate) / count)); // #3652, #3654
-                    if (interval >= timeUnits.second) { // second
-                        time.set('Seconds', minDate, interval >= timeUnits.minute ?
-                            0 : // #3935
-                            count * Math.floor(time.get('Seconds', minDate) / count));
-                    }
-                    if (interval >= timeUnits.minute) { // minute
-                        time.set('Minutes', minDate, interval >= timeUnits.hour ?
-                            0 :
-                            count * Math.floor(time.get('Minutes', minDate) / count));
-                    }
-                    if (interval >= timeUnits.hour) { // hour
-                        time.set('Hours', minDate, interval >= timeUnits.day ?
-                            0 :
-                            count * Math.floor(time.get('Hours', minDate) / count));
-                    }
-                    if (interval >= timeUnits.day) { // day
-                        time.set('Date', minDate, interval >= timeUnits.month ?
-                            1 :
-                            Math.max(1, count * Math.floor(time.get('Date', minDate) / count)));
-                    }
-                    if (interval >= timeUnits.month) { // month
-                        time.set('Month', minDate, interval >= timeUnits.year ? 0 :
-                            count * Math.floor(time.get('Month', minDate) / count));
-                        minYear = time.get('FullYear', minDate);
-                    }
-                    if (interval >= timeUnits.year) { // year
-                        minYear -= minYear % count;
-                        time.set('FullYear', minDate, minYear);
-                    }
-                    // week is a special case that runs outside the hierarchy
-                    if (interval === timeUnits.week) {
-                        // get start of current week, independent of count
-                        minDay = time.get('Day', minDate);
-                        time.set('Date', minDate, (time.get('Date', minDate) -
-                            minDay + startOfWeek +
-                            // We don't want to skip days that are before
-                            // startOfWeek (#7051)
-                            (minDay < startOfWeek ? -7 : 0)));
-                    }
-                    // Get basics for variable time spans
-                    minYear = time.get('FullYear', minDate);
-                    var minMonth = time.get('Month', minDate), minDateDate = time.get('Date', minDate), minHours = time.get('Hours', minDate);
-                    // Redefine min to the floored/rounded minimum time (#7432)
-                    min = minDate.getTime();
-                    // Handle local timezone offset
-                    if (time.variableTimezone) {
-                        // Detect whether we need to take the DST crossover into
-                        // consideration. If we're crossing over DST, the day length may
-                        // be 23h or 25h and we need to compute the exact clock time for
-                        // each tick instead of just adding hours. This comes at a cost,
-                        // so first we find out if it is needed (#4951).
-                        variableDayLength = (
-                        // Long range, assume we're crossing over.
-                        max - min > 4 * timeUnits.month ||
-                            // Short range, check if min and max are in different time
-                            // zones.
-                            time.getTimezoneOffset(min) !==
-                                time.getTimezoneOffset(max));
-                    }
-                    // Iterate and add tick positions at appropriate values
-                    var t = minDate.getTime();
-                    i = 1;
-                    while (t < max) {
-                        tickPositions.push(t);
-                        // if the interval is years, use Date.UTC to increase years
-                        if (interval === timeUnits.year) {
-                            t = time.makeTime(minYear + i * count, 0);
-                            // if the interval is months, use Date.UTC to increase months
-                        }
-                        else if (interval === timeUnits.month) {
-                            t = time.makeTime(minYear, minMonth + i * count);
-                            // if we're using global time, the interval is not fixed as it
-                            // jumps one hour at the DST crossover
-                        }
-                        else if (variableDayLength &&
-                            (interval === timeUnits.day || interval === timeUnits.week)) {
-                            t = time.makeTime(minYear, minMonth, minDateDate +
-                                i * count * (interval === timeUnits.day ? 1 : 7));
-                        }
-                        else if (variableDayLength &&
-                            interval === timeUnits.hour &&
-                            count > 1) {
-                            // make sure higher ranks are preserved across DST (#6797,
-                            // #7621)
-                            t = time.makeTime(minYear, minMonth, minDateDate, minHours + i * count);
-                            // else, the interval is fixed and we use simple addition
-                        }
-                        else {
-                            t += interval * count;
-                        }
-                        i++;
-                    }
-                    // push the last time
-                    tickPositions.push(t);
-                    // Handle higher ranks. Mark new days if the time is on midnight
-                    // (#950, #1649, #1760, #3349). Use a reasonable dropout threshold
-                    // to prevent looping over dense data grouping (#6156).
-                    if (interval <= timeUnits.hour && tickPositions.length < 10000) {
-                        tickPositions.forEach(function (t) {
-                            if (
-                            // Speed optimization, no need to run dateFormat unless
-                            // we're on a full or half hour
-                            t % 1800000 === 0 &&
-                                // Check for local or global midnight
-                                time.dateFormat('%H%M%S%L', t) === '000000000') {
-                                higherRanks[t] = 'day';
-                            }
-                        });
-                    }
-                }
-                // record information on the chosen unit - for dynamic label formatter
-                tickPositions.info = extend(normalizedInterval, {
-                    higherRanks: higherRanks,
-                    totalRange: interval * count
-                });
-                return tickPositions;
-            };
-            return Time;
-        }());
-        H.Time = Time;
-
-        return H.Time;
-    });
-    _registerModule(_modules, 'Core/Options.js', [_modules['Core/Globals.js'], _modules['Core/Color/Color.js'], _modules['Core/Time.js'], _modules['Core/Utilities.js']], function (H, Color, Time, U) {
-        /* *
-         *
-         *  (c) 2010-2020 Torstein Honsi
-         *
-         *  License: www.highcharts.com/license
-         *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
-         *
-         * */
-        var isTouchDevice = H.isTouchDevice,
-            svg = H.svg;
-        var color = Color.parse;
-        var merge = U.merge;
-        /**
-         * @typedef {"plotBox"|"spacingBox"} Highcharts.ButtonRelativeToValue
-         */
-        /**
-         * Gets fired when a series is added to the chart after load time, using the
-         * `addSeries` method. Returning `false` prevents the series from being added.
-         *
-         * @callback Highcharts.ChartAddSeriesCallbackFunction
-         *
-         * @param {Highcharts.Chart} this
-         *        The chart on which the event occured.
-         *
-         * @param {Highcharts.ChartAddSeriesEventObject} event
-         *        The event that occured.
-         */
-        /**
-         * Contains common event information. Through the `options` property you can
-         * access the series options that were passed to the `addSeries` method.
-         *
-         * @interface Highcharts.ChartAddSeriesEventObject
-         */ /**
-        * The series options that were passed to the `addSeries` method.
-        * @name Highcharts.ChartAddSeriesEventObject#options
-        * @type {Highcharts.SeriesOptionsType}
-        */ /**
-        * Prevents the default behaviour of the event.
-        * @name Highcharts.ChartAddSeriesEventObject#preventDefault
-        * @type {Function}
-        */ /**
-        * The event target.
-        * @name Highcharts.ChartAddSeriesEventObject#target
-        * @type {Highcharts.Chart}
-        */ /**
-        * The event type.
-        * @name Highcharts.ChartAddSeriesEventObject#type
-        * @type {"addSeries"}
-        */
-        /**
-         * Gets fired when clicking on the plot background.
-         *
-         * @callback Highcharts.ChartClickCallbackFunction
-         *
-         * @param {Highcharts.Chart} this
-         *        The chart on which the event occured.
-         *
-         * @param {Highcharts.PointerEventObject} event
-         *        The event that occured.
-         */
-        /**
-         * Contains an axes of the clicked spot.
-         *
-         * @interface Highcharts.ChartClickEventAxisObject
-         */ /**
-        * Axis at the clicked spot.
-        * @name Highcharts.ChartClickEventAxisObject#axis
-        * @type {Highcharts.Axis}
-        */ /**
-        * Axis value at the clicked spot.
-        * @name Highcharts.ChartClickEventAxisObject#value
-        * @type {number}
-        */
-        /**
-         * Contains information about the clicked spot on the chart. Remember the unit
-         * of a datetime axis is milliseconds since 1970-01-01 00:00:00.
-         *
-         * @interface Highcharts.ChartClickEventObject
-         * @extends Highcharts.PointerEventObject
-         */ /**
-        * Information about the x-axis on the clicked spot.
-        * @name Highcharts.ChartClickEventObject#xAxis
-        * @type {Array<Highcharts.ChartClickEventAxisObject>}
-        */ /**
-        * Information about the y-axis on the clicked spot.
-        * @name Highcharts.ChartClickEventObject#yAxis
-        * @type {Array<Highcharts.ChartClickEventAxisObject>}
-        */ /**
-        * Information about the z-axis on the clicked spot.
-        * @name Highcharts.ChartClickEventObject#zAxis
-        * @type {Array<Highcharts.ChartClickEventAxisObject>|undefined}
-        */
-        /**
-         * Gets fired when the chart is finished loading.
-         *
-         * @callback Highcharts.ChartLoadCallbackFunction
-         *
-         * @param {Highcharts.Chart} this
-         *        The chart on which the event occured.
-         *
-         * @param {global.Event} event
-         *        The event that occured.
-         */
-        /**
-         * Fires when the chart is redrawn, either after a call to `chart.redraw()` or
-         * after an axis, series or point is modified with the `redraw` option set to
-         * `true`.
-         *
-         * @callback Highcharts.ChartRedrawCallbackFunction
-         *
-         * @param {Highcharts.Chart} this
-         *        The chart on which the event occured.
-         *
-         * @param {global.Event} event
-         *        The event that occured.
-         */
-        /**
-         * Gets fired after initial load of the chart (directly after the `load` event),
-         * and after each redraw (directly after the `redraw` event).
-         *
-         * @callback Highcharts.ChartRenderCallbackFunction
-         *
-         * @param {Highcharts.Chart} this
-         *        The chart on which the event occured.
-         *
-         * @param {global.Event} event
-         *        The event that occured.
-         */
-        /**
-         * Gets fired when an area of the chart has been selected. The default action
-         * for the selection event is to zoom the chart to the selected area. It can be
-         * prevented by calling `event.preventDefault()` or return false.
-         *
-         * @callback Highcharts.ChartSelectionCallbackFunction
-         *
-         * @param {Highcharts.Chart} this
-         *        The chart on which the event occured.
-         *
-         * @param {global.ChartSelectionContextObject} event
-         *        Event informations
-         *
-         * @return {boolean|undefined}
-         *         Return false to prevent the default action, usually zoom.
-         */
-        /**
-         * The primary axes are `xAxis[0]` and `yAxis[0]`. Remember the unit of a
-         * datetime axis is milliseconds since 1970-01-01 00:00:00.
-         *
-         * @interface Highcharts.ChartSelectionContextObject
-         * @extends global.Event
-         */ /**
-        * Arrays containing the axes of each dimension and each axis' min and max
-        * values.
-        * @name Highcharts.ChartSelectionContextObject#xAxis
-        * @type {Array<Highcharts.ChartSelectionAxisContextObject>}
-        */ /**
-        * Arrays containing the axes of each dimension and each axis' min and max
-        * values.
-        * @name Highcharts.ChartSelectionContextObject#yAxis
-        * @type {Array<Highcharts.ChartSelectionAxisContextObject>}
-        */
-        /**
-         * Axis context of the selection.
-         *
-         * @interface Highcharts.ChartSelectionAxisContextObject
-         */ /**
-        * The selected Axis.
-        * @name Highcharts.ChartSelectionAxisContextObject#axis
-        * @type {Highcharts.Axis}
-        */ /**
-        * The maximum axis value, either automatic or set manually.
-        * @name Highcharts.ChartSelectionAxisContextObject#max
-        * @type {number}
-        */ /**
-        * The minimum axis value, either automatic or set manually.
-        * @name Highcharts.ChartSelectionAxisContextObject#min
-        * @type {number}
-        */
-        ''; // detach doclets above
-        /* ************************************************************************** *
-         * Handle the options                                                         *
-         * ************************************************************************** */
-        /**
-         * Global default settings.
-         *
-         * @name Highcharts.defaultOptions
-         * @type {Highcharts.Options}
-         */ /**
-        * @optionparent
-        */
-        H.defaultOptions = {
-            /**
-             * An array containing the default colors for the chart's series. When
-             * all colors are used, new colors are pulled from the start again.
-             *
-             * Default colors can also be set on a series or series.type basis,
-             * see [column.colors](#plotOptions.column.colors),
-             * [pie.colors](#plotOptions.pie.colors).
-             *
-             * In styled mode, the colors option doesn't exist. Instead, colors
-             * are defined in CSS and applied either through series or point class
-             * names, or through the [chart.colorCount](#chart.colorCount) option.
-             *
-             *
-             * ### Legacy
-             *
-             * In Highcharts 3.x, the default colors were:
-             * ```js
-             * colors: ['#2f7ed8', '#0d233a', '#8bbc21', '#910000', '#1aadce',
-             *         '#492970', '#f28f43', '#77a1e5', '#c42525', '#a6c96a']
-             * ```
-             *
-             * In Highcharts 2.x, the default colors were:
-             * ```js
-             * colors: ['#4572A7', '#AA4643', '#89A54E', '#80699B', '#3D96AE',
-             *         '#DB843D', '#92A8CD', '#A47D7C', '#B5CA92']
-             * ```
-             *
-             * @sample {highcharts} highcharts/chart/colors/
-             *         Assign a global color theme
-             *
-             * @type    {Array<Highcharts.ColorString>}
-             * @default ["#7cb5ec", "#434348", "#90ed7d", "#f7a35c", "#8085e9",
-             *          "#f15c80", "#e4d354", "#2b908f", "#f45b5b", "#91e8e1"]
-             */
-            colors: '#7cb5ec #434348 #90ed7d #f7a35c #8085e9 #f15c80 #e4d354 #2b908f #f45b5b #91e8e1'.split(' '),
-            /**
-             * Styled mode only. Configuration object for adding SVG definitions for
-             * reusable elements. See [gradients, shadows and
-             * patterns](https://www.highcharts.com/docs/chart-design-and-style/gradients-shadows-and-patterns)
-             * for more information and code examples.
-             *
-             * @type      {*}
-             * @since     5.0.0
-             * @apioption defs
-             */
-            /**
-             * @ignore-option
-             */
-            symbols: ['circle', 'diamond', 'square', 'triangle', 'triangle-down'],
-            /**
-             * The language object is global and it can't be set on each chart
-             * initialization. Instead, use `Highcharts.setOptions` to set it before any
-             * chart is initialized.
-             *
-             * ```js
-             * Highcharts.setOptions({
-             *     lang: {
-             *         months: [
-             *             'Janvier', 'Février', 'Mars', 'Avril',
-             *             'Mai', 'Juin', 'Juillet', 'Août',
-             *             'Septembre', 'Octobre', 'Novembre', 'Décembre'
-             *         ],
-             *         weekdays: [
-             *             'Dimanche', 'Lundi', 'Mardi', 'Mercredi',
-             *             'Jeudi', 'Vendredi', 'Samedi'
-             *         ]
-             *     }
-             * });
-             * ```
-             */
-            lang: {
-                /**
-                 * The loading text that appears when the chart is set into the loading
-                 * state following a call to `chart.showLoading`.
-                 */
-                loading: 'Loading...',
-                /**
-                 * An array containing the months names. Corresponds to the `%B` format
-                 * in `Highcharts.dateFormat()`.
-                 *
-                 * @type    {Array<string>}
-                 * @default ["January", "February", "March", "April", "May", "June",
-                 *          "July", "August", "September", "October", "November",
-                 *          "December"]
-                 */
-                months: [
-                    'January', 'February', 'March', 'April', 'May', 'June', 'July',
-                    'August', 'September', 'October', 'November', 'December'
-                ],
-                /**
-                 * An array containing the months names in abbreviated form. Corresponds
-                 * to the `%b` format in `Highcharts.dateFormat()`.
-                 *
-                 * @type    {Array<string>}
-                 * @default ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
-                 *          "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
-                 */
-                shortMonths: [
-                    'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
-                    'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
-                ],
-                /**
-                 * An array containing the weekday names.
-                 *
-                 * @type    {Array<string>}
-                 * @default ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
-                 *          "Friday", "Saturday"]
-                 */
-                weekdays: [
-                    'Sunday', 'Monday', 'Tuesday', 'Wednesday',
-                    'Thursday', 'Friday', 'Saturday'
-                ],
-                /**
-                 * Short week days, starting Sunday. If not specified, Highcharts uses
-                 * the first three letters of the `lang.weekdays` option.
-                 *
-                 * @sample highcharts/lang/shortweekdays/
-                 *         Finnish two-letter abbreviations
-                 *
-                 * @type      {Array<string>}
-                 * @since     4.2.4
-                 * @apioption lang.shortWeekdays
-                 */
-                /**
-                 * What to show in a date field for invalid dates. Defaults to an empty
-                 * string.
-                 *
-                 * @type      {string}
-                 * @since     4.1.8
-                 * @product   highcharts highstock
-                 * @apioption lang.invalidDate
-                 */
-                /**
-                 * The title appearing on hovering the zoom in button. The text itself
-                 * defaults to "+" and can be changed in the button options.
-                 *
-                 * @type      {string}
-                 * @default   Zoom in
-                 * @product   highmaps
-                 * @apioption lang.zoomIn
-                 */
-                /**
-                 * The title appearing on hovering the zoom out button. The text itself
-                 * defaults to "-" and can be changed in the button options.
-                 *
-                 * @type      {string}
-                 * @default   Zoom out
-                 * @product   highmaps
-                 * @apioption lang.zoomOut
-                 */
-                /**
-                 * The default decimal point used in the `Highcharts.numberFormat`
-                 * method unless otherwise specified in the function arguments.
-                 *
-                 * @since 1.2.2
-                 */
-                decimalPoint: '.',
-                /**
-                 * [Metric prefixes](https://en.wikipedia.org/wiki/Metric_prefix) used
-                 * to shorten high numbers in axis labels. Replacing any of the
-                 * positions with `null` causes the full number to be written. Setting
-                 * `numericSymbols` to `null` disables shortening altogether.
-                 *
-                 * @sample {highcharts} highcharts/lang/numericsymbols/
-                 *         Replacing the symbols with text
-                 * @sample {highstock} highcharts/lang/numericsymbols/
-                 *         Replacing the symbols with text
-                 *
-                 * @type    {Array<string>}
-                 * @default ["k", "M", "G", "T", "P", "E"]
-                 * @since   2.3.0
-                 */
-                numericSymbols: ['k', 'M', 'G', 'T', 'P', 'E'],
-                /**
-                 * The magnitude of [numericSymbols](#lang.numericSymbol) replacements.
-                 * Use 10000 for Japanese, Korean and various Chinese locales, which
-                 * use symbols for 10^4, 10^8 and 10^12.
-                 *
-                 * @sample highcharts/lang/numericsymbolmagnitude/
-                 *         10000 magnitude for Japanese
-                 *
-                 * @type      {number}
-                 * @default   1000
-                 * @since     5.0.3
-                 * @apioption lang.numericSymbolMagnitude
-                 */
-                /**
-                 * The text for the label appearing when a chart is zoomed.
-                 *
-                 * @since 1.2.4
-                 */
-                resetZoom: 'Reset zoom',
-                /**
-                 * The tooltip title for the label appearing when a chart is zoomed.
-                 *
-                 * @since 1.2.4
-                 */
-                resetZoomTitle: 'Reset zoom level 1:1',
-                /**
-                 * The default thousands separator used in the `Highcharts.numberFormat`
-                 * method unless otherwise specified in the function arguments. Defaults
-                 * to a single space character, which is recommended in
-                 * [ISO 31-0](https://en.wikipedia.org/wiki/ISO_31-0#Numbers) and works
-                 * across Anglo-American and continental European languages.
-                 *
-                 * @default \u0020
-                 * @since   1.2.2
-                 */
-                thousandsSep: ' '
-            },
-            /**
-             * Global options that don't apply to each chart. These options, like
-             * the `lang` options, must be set using the `Highcharts.setOptions`
-             * method.
-             *
-             * ```js
-             * Highcharts.setOptions({
-             *     global: {
-             *         useUTC: false
-             *     }
-             * });
-             * ```
-             */
-            /**
-             * _Canvg rendering for Android 2.x is removed as of Highcharts 5.0\.
-             * Use the [libURL](#exporting.libURL) option to configure exporting._
-             *
-             * The URL to the additional file to lazy load for Android 2.x devices.
-             * These devices don't support SVG, so we download a helper file that
-             * contains [canvg](https://github.com/canvg/canvg), its dependency
-             * rbcolor, and our own CanVG Renderer class. To avoid hotlinking to
-             * our site, you can install canvas-tools.js on your own server and
-             * change this option accordingly.
-             *
-             * @deprecated
-             *
-             * @type      {string}
-             * @default   https://code.highcharts.com/{version}/modules/canvas-tools.js
-             * @product   highcharts highmaps
-             * @apioption global.canvasToolsURL
-             */
-            /**
-             * This option is deprecated since v6.0.5. Instead, use
-             * [time.useUTC](#time.useUTC) that supports individual time settings
-             * per chart.
-             *
-             * @deprecated
-             *
-             * @type      {boolean}
-             * @apioption global.useUTC
-             */
-            /**
-             * This option is deprecated since v6.0.5. Instead, use
-             * [time.Date](#time.Date) that supports individual time settings
-             * per chart.
-             *
-             * @deprecated
-             *
-             * @type      {Function}
-             * @product   highcharts highstock
-             * @apioption global.Date
-             */
-            /**
-             * This option is deprecated since v6.0.5. Instead, use
-             * [time.getTimezoneOffset](#time.getTimezoneOffset) that supports
-             * individual time settings per chart.
-             *
-             * @deprecated
-             *
-             * @type      {Function}
-             * @product   highcharts highstock
-             * @apioption global.getTimezoneOffset
-             */
-            /**
-             * This option is deprecated since v6.0.5. Instead, use
-             * [time.timezone](#time.timezone) that supports individual time
-             * settings per chart.
-             *
-             * @deprecated
-             *
-             * @type      {string}
-             * @product   highcharts highstock
-             * @apioption global.timezone
-             */
-            /**
-             * This option is deprecated since v6.0.5. Instead, use
-             * [time.timezoneOffset](#time.timezoneOffset) that supports individual
-             * time settings per chart.
-             *
-             * @deprecated
-             *
-             * @type      {number}
-             * @product   highcharts highstock
-             * @apioption global.timezoneOffset
-             */
-            global: {},
-            /**
-             * Time options that can apply globally or to individual charts. These
-             * settings affect how `datetime` axes are laid out, how tooltips are
-             * formatted, how series
-             * [pointIntervalUnit](#plotOptions.series.pointIntervalUnit) works and how
-             * the Highstock range selector handles time.
-             *
-             * The common use case is that all charts in the same Highcharts object
-             * share the same time settings, in which case the global settings are set
-             * using `setOptions`.
-             *
-             * ```js
-             * // Apply time settings globally
-             * Highcharts.setOptions({
-             *     time: {
-             *         timezone: 'Europe/London'
-             *     }
-             * });
-             * // Apply time settings by instance
-             * var chart = Highcharts.chart('container', {
-             *     time: {
-             *         timezone: 'America/New_York'
-             *     },
-             *     series: [{
-             *         data: [1, 4, 3, 5]
-             *     }]
-             * });
-             *
-             * // Use the Time object
-             * console.log(
-             *        'Current time in New York',
-             *        chart.time.dateFormat('%Y-%m-%d %H:%M:%S', Date.now())
-             * );
-             * ```
-             *
-             * Since v6.0.5, the time options were moved from the `global` obect to the
-             * `time` object, and time options can be set on each individual chart.
-             *
-             * @sample {highcharts|highstock}
-             *         highcharts/time/timezone/
-             *         Set the timezone globally
-             * @sample {highcharts}
-             *         highcharts/time/individual/
-             *         Set the timezone per chart instance
-             * @sample {highstock}
-             *         stock/time/individual/
-             *         Set the timezone per chart instance
-             *
-             * @since     6.0.5
-             * @optionparent time
-             */
-            time: {
-                /**
-                 * A custom `Date` class for advanced date handling. For example,
-                 * [JDate](https://github.com/tahajahangir/jdate) can be hooked in to
-                 * handle Jalali dates.
-                 *
-                 * @type      {*}
-                 * @since     4.0.4
-                 * @product   highcharts highstock gantt
-                 */
-                Date: void 0,
-                /**
-                 * A callback to return the time zone offset for a given datetime. It
-                 * takes the timestamp in terms of milliseconds since January 1 1970,
-                 * and returns the timezone offset in minutes. This provides a hook
-                 * for drawing time based charts in specific time zones using their
-                 * local DST crossover dates, with the help of external libraries.
-                 *
-                 * @see [global.timezoneOffset](#global.timezoneOffset)
-                 *
-                 * @sample {highcharts|highstock} highcharts/time/gettimezoneoffset/
-                 *         Use moment.js to draw Oslo time regardless of browser locale
-                 *
-                 * @type      {Highcharts.TimezoneOffsetCallbackFunction}
-                 * @since     4.1.0
-                 * @product   highcharts highstock gantt
-                 */
-                getTimezoneOffset: void 0,
-                /**
-                 * Requires [moment.js](https://momentjs.com/). If the timezone option
-                 * is specified, it creates a default
-                 * [getTimezoneOffset](#time.getTimezoneOffset) function that looks
-                 * up the specified timezone in moment.js. If moment.js is not included,
-                 * this throws a Highcharts error in the console, but does not crash the
-                 * chart.
-                 *
-                 * @see [getTimezoneOffset](#time.getTimezoneOffset)
-                 *
-                 * @sample {highcharts|highstock} highcharts/time/timezone/
-                 *         Europe/Oslo
-                 *
-                 * @type      {string}
-                 * @since     5.0.7
-                 * @product   highcharts highstock gantt
-                 */
-                timezone: void 0,
-                /**
-                 * The timezone offset in minutes. Positive values are west, negative
-                 * values are east of UTC, as in the ECMAScript
-                 * [getTimezoneOffset](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset)
-                 * method. Use this to display UTC based data in a predefined time zone.
-                 *
-                 * @see [time.getTimezoneOffset](#time.getTimezoneOffset)
-                 *
-                 * @sample {highcharts|highstock} highcharts/time/timezoneoffset/
-                 *         Timezone offset
-                 *
-                 * @since     3.0.8
-                 * @product   highcharts highstock gantt
-                 */
-                timezoneOffset: 0,
-                /**
-                 * Whether to use UTC time for axis scaling, tickmark placement and
-                 * time display in `Highcharts.dateFormat`. Advantages of using UTC
-                 * is that the time displays equally regardless of the user agent's
-                 * time zone settings. Local time can be used when the data is loaded
-                 * in real time or when correct Daylight Saving Time transitions are
-                 * required.
-                 *
-                 * @sample {highcharts} highcharts/time/useutc-true/
-                 *         True by default
-                 * @sample {highcharts} highcharts/time/useutc-false/
-                 *         False
-                 */
-                useUTC: true
-            },
-            /**
-             * General options for the chart.
-             */
-            chart: {
-                /**
-                 * Default `mapData` for all series. If set to a string, it functions
-                 * as an index into the `Highcharts.maps` array. Otherwise it is
-                 * interpreted as map data.
-                 *
-                 * @see [mapData](#series.map.mapData)
-                 *
-                 * @sample    maps/demo/geojson
-                 *            Loading geoJSON data
-                 * @sample    maps/chart/topojson
-                 *            Loading topoJSON converted to geoJSON
-                 *
-                 * @type      {string|Array<*>|Highcharts.GeoJSON}
-                 * @since     5.0.0
-                 * @product   highmaps
-                 * @apioption chart.map
-                 */
-                /**
-                 * Set lat/lon transformation definitions for the chart. If not defined,
-                 * these are extracted from the map data.
-                 *
-                 * @type      {*}
-                 * @since     5.0.0
-                 * @product   highmaps
-                 * @apioption chart.mapTransforms
-                 */
-                /**
-                 * When using multiple axis, the ticks of two or more opposite axes
-                 * will automatically be aligned by adding ticks to the axis or axes
-                 * with the least ticks, as if `tickAmount` were specified.
-                 *
-                 * This can be prevented by setting `alignTicks` to false. If the grid
-                 * lines look messy, it's a good idea to hide them for the secondary
-                 * axis by setting `gridLineWidth` to 0.
-                 *
-                 * If `startOnTick` or `endOnTick` in an Axis options are set to false,
-                 * then the `alignTicks ` will be disabled for the Axis.
-                 *
-                 * Disabled for logarithmic axes.
-                 *
-                 * @sample {highcharts} highcharts/chart/alignticks-true/
-                 *         True by default
-                 * @sample {highcharts} highcharts/chart/alignticks-false/
-                 *         False
-                 * @sample {highstock} stock/chart/alignticks-true/
-                 *         True by default
-                 * @sample {highstock} stock/chart/alignticks-false/
-                 *         False
-                 *
-                 * @type      {boolean}
-                 * @default   true
-                 * @product   highcharts highstock gantt
-                 * @apioption chart.alignTicks
-                 */
-                /**
-                 * Set the overall animation for all chart updating. Animation can be
-                 * disabled throughout the chart by setting it to false here. It can
-                 * be overridden for each individual API method as a function parameter.
-                 * The only animation not affected by this option is the initial series
-                 * animation, see [plotOptions.series.animation](
-                 * #plotOptions.series.animation).
-                 *
-                 * The animation can either be set as a boolean or a configuration
-                 * object. If `true`, it will use the 'swing' jQuery easing and a
-                 * duration of 500 ms. If used as a configuration object, the following
-                 * properties are supported:
-                 *
-                 * - `defer`: The animation delay time in milliseconds.
-                 *
-                 * - `duration`: The duration of the animation in milliseconds.
-                 *
-                 * - `easing`: A string reference to an easing function set on the
-                 *   `Math` object. See
-                 *   [the easing demo](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/series-animation-easing/).
-                 *
-                 * When zooming on a series with less than 100 points, the chart redraw
-                 * will be done with animation, but in case of more data points, it is
-                 * necessary to set this option to ensure animation on zoom.
-                 *
-                 * @sample {highcharts} highcharts/chart/animation-none/
-                 *         Updating with no animation
-                 * @sample {highcharts} highcharts/chart/animation-duration/
-                 *         With a longer duration
-                 * @sample {highcharts} highcharts/chart/animation-easing/
-                 *         With a jQuery UI easing
-                 * @sample {highmaps} maps/chart/animation-none/
-                 *         Updating with no animation
-                 * @sample {highmaps} maps/chart/animation-duration/
-                 *         With a longer duration
-                 *
-                 * @type      {boolean|Partial<Highcharts.AnimationOptionsObject>}
-                 * @default   undefined
-                 * @apioption chart.animation
-                 */
-                /**
-                 * A CSS class name to apply to the charts container `div`, allowing
-                 * unique CSS styling for each chart.
-                 *
-                 * @type      {string}
-                 * @apioption chart.className
-                 */
-                /**
-                 * Event listeners for the chart.
-                 *
-                 * @apioption chart.events
-                 */
-                /**
-                 * Fires when a series is added to the chart after load time, using the
-                 * `addSeries` method. One parameter, `event`, is passed to the
-                 * function, containing common event information. Through
-                 * `event.options` you can access the series options that were passed to
-                 * the `addSeries` method. Returning false prevents the series from
-                 * being added.
-                 *
-                 * @sample {highcharts} highcharts/chart/events-addseries/
-                 *         Alert on add series
-                 * @sample {highstock} stock/chart/events-addseries/
-                 *         Alert on add series
-                 *
-                 * @type      {Highcharts.ChartAddSeriesCallbackFunction}
-                 * @since     1.2.0
-                 * @context   Highcharts.Chart
-                 * @apioption chart.events.addSeries
-                 */
-                /**
-                 * Fires when clicking on the plot background. One parameter, `event`,
-                 * is passed to the function, containing common event information.
-                 *
-                 * Information on the clicked spot can be found through `event.xAxis`
-                 * and `event.yAxis`, which are arrays containing the axes of each
-                 * dimension and each axis' value at the clicked spot. The primary axes
-                 * are `event.xAxis[0]` and `event.yAxis[0]`. Remember the unit of a
-                 * datetime axis is milliseconds since 1970-01-01 00:00:00.
-                 *
-                 * ```js
-                 * click: function(e) {
-                 *     console.log(
-                 *         Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', e.xAxis[0].value),
-                 *         e.yAxis[0].value
-                 *     )
-                 * }
-                 * ```
-                 *
-                 * @sample {highcharts} highcharts/chart/events-click/
-                 *         Alert coordinates on click
-                 * @sample {highcharts} highcharts/chart/events-container/
-                 *         Alternatively, attach event to container
-                 * @sample {highstock} stock/chart/events-click/
-                 *         Alert coordinates on click
-                 * @sample {highstock} highcharts/chart/events-container/
-                 *         Alternatively, attach event to container
-                 * @sample {highmaps} maps/chart/events-click/
-                 *         Record coordinates on click
-                 * @sample {highmaps} highcharts/chart/events-container/
-                 *         Alternatively, attach event to container
-                 *
-                 * @type      {Highcharts.ChartClickCallbackFunction}
-                 * @since     1.2.0
-                 * @context   Highcharts.Chart
-                 * @apioption chart.events.click
-                 */
-                /**
-                 * Fires when the chart is finished loading. Since v4.2.2, it also waits
-                 * for images to be loaded, for example from point markers. One
-                 * parameter, `event`, is passed to the function, containing common
-                 * event information.
-                 *
-                 * There is also a second parameter to the chart constructor where a
-                 * callback function can be passed to be executed on chart.load.
-                 *
-                 * @sample {highcharts} highcharts/chart/events-load/
-                 *         Alert on chart load
-                 * @sample {highstock} stock/chart/events-load/
-                 *         Alert on chart load
-                 * @sample {highmaps} maps/chart/events-load/
-                 *         Add series on chart load
-                 *
-                 * @type      {Highcharts.ChartLoadCallbackFunction}
-                 * @context   Highcharts.Chart
-                 * @apioption chart.events.load
-                 */
-                /**
-                 * Fires when the chart is redrawn, either after a call to
-                 * `chart.redraw()` or after an axis, series or point is modified with
-                 * the `redraw` option set to `true`. One parameter, `event`, is passed
-                 * to the function, containing common event information.
-                 *
-                 * @sample {highcharts} highcharts/chart/events-redraw/
-                 *         Alert on chart redraw
-                 * @sample {highstock} stock/chart/events-redraw/
-                 *         Alert on chart redraw when adding a series or moving the
-                 *         zoomed range
-                 * @sample {highmaps} maps/chart/events-redraw/
-                 *         Set subtitle on chart redraw
-                 *
-                 * @type      {Highcharts.ChartRedrawCallbackFunction}
-                 * @since     1.2.0
-                 * @context   Highcharts.Chart
-                 * @apioption chart.events.redraw
-                 */
-                /**
-                 * Fires after initial load of the chart (directly after the `load`
-                 * event), and after each redraw (directly after the `redraw` event).
-                 *
-                 * @type      {Highcharts.ChartRenderCallbackFunction}
-                 * @since     5.0.7
-                 * @context   Highcharts.Chart
-                 * @apioption chart.events.render
-                 */
-                /**
-                 * Fires when an area of the chart has been selected. Selection is
-                 * enabled by setting the chart's zoomType. One parameter, `event`, is
-                 * passed to the function, containing common event information. The
-                 * default action for the selection event is to zoom the chart to the
-                 * selected area. It can be prevented by calling
-                 * `event.preventDefault()` or return false.
-                 *
-                 * Information on the selected area can be found through `event.xAxis`
-                 * and `event.yAxis`, which are arrays containing the axes of each
-                 * dimension and each axis' min and max values. The primary axes are
-                 * `event.xAxis[0]` and `event.yAxis[0]`. Remember the unit of a
-                 * datetime axis is milliseconds since 1970-01-01 00:00:00.
-                 *
-                 * ```js
-                 * selection: function(event) {
-                 *     // log the min and max of the primary, datetime x-axis
-                 *     console.log(
-                 *         Highcharts.dateFormat(
-                 *             '%Y-%m-%d %H:%M:%S',
-                 *             event.xAxis[0].min
-                 *         ),
-                 *         Highcharts.dateFormat(
-                 *             '%Y-%m-%d %H:%M:%S',
-                 *             event.xAxis[0].max
-                 *         )
-                 *     );
-                 *     // log the min and max of the y axis
-                 *     console.log(event.yAxis[0].min, event.yAxis[0].max);
-                 * }
-                 * ```
-                 *
-                 * @sample {highcharts} highcharts/chart/events-selection/
-                 *         Report on selection and reset
-                 * @sample {highcharts} highcharts/chart/events-selection-points/
-                 *         Select a range of points through a drag selection
-                 * @sample {highstock} stock/chart/events-selection/
-                 *         Report on selection and reset
-                 * @sample {highstock} highcharts/chart/events-selection-points/
-                 *         Select a range of points through a drag selection
-                 *         (Highcharts)
-                 *
-                 * @type      {Highcharts.ChartSelectionCallbackFunction}
-                 * @apioption chart.events.selection
-                 */
-                /**
-                 * The margin between the outer edge of the chart and the plot area.
-                 * The numbers in the array designate top, right, bottom and left
-                 * respectively. Use the options `marginTop`, `marginRight`,
-                 * `marginBottom` and `marginLeft` for shorthand setting of one option.
-                 *
-                 * By default there is no margin. The actual space is dynamically
-                 * calculated from the offset of axis labels, axis title, title,
-                 * subtitle and legend in addition to the `spacingTop`, `spacingRight`,
-                 * `spacingBottom` and `spacingLeft` options.
-                 *
-                 * @sample {highcharts} highcharts/chart/margins-zero/
-                 *         Zero margins
-                 * @sample {highstock} stock/chart/margin-zero/
-                 *         Zero margins
-                 *
-                 * @type      {number|Array<number>}
-                 * @apioption chart.margin
-                 */
-                /**
-                 * The margin between the bottom outer edge of the chart and the plot
-                 * area. Use this to set a fixed pixel value for the margin as opposed
-                 * to the default dynamic margin. See also `spacingBottom`.
-                 *
-                 * @sample {highcharts} highcharts/chart/marginbottom/
-                 *         100px bottom margin
-                 * @sample {highstock} stock/chart/marginbottom/
-                 *         100px bottom margin
-                 * @sample {highmaps} maps/chart/margin/
-                 *         100px margins
-                 *
-                 * @type      {number}
-                 * @since     2.0
-                 * @apioption chart.marginBottom
-                 */
-                /**
-                 * The margin between the left outer edge of the chart and the plot
-                 * area. Use this to set a fixed pixel value for the margin as opposed
-                 * to the default dynamic margin. See also `spacingLeft`.
-                 *
-                 * @sample {highcharts} highcharts/chart/marginleft/
-                 *         150px left margin
-                 * @sample {highstock} stock/chart/marginleft/
-                 *         150px left margin
-                 * @sample {highmaps} maps/chart/margin/
-                 *         100px margins
-                 *
-                 * @type      {number}
-                 * @since     2.0
-                 * @apioption chart.marginLeft
-                 */
-                /**
-                 * The margin between the right outer edge of the chart and the plot
-                 * area. Use this to set a fixed pixel value for the margin as opposed
-                 * to the default dynamic margin. See also `spacingRight`.
-                 *
-                 * @sample {highcharts} highcharts/chart/marginright/
-                 *         100px right margin
-                 * @sample {highstock} stock/chart/marginright/
-                 *         100px right margin
-                 * @sample {highmaps} maps/chart/margin/
-                 *         100px margins
-                 *
-                 * @type      {number}
-                 * @since     2.0
-                 * @apioption chart.marginRight
-                 */
-                /**
-                 * The margin between the top outer edge of the chart and the plot area.
-                 * Use this to set a fixed pixel value for the margin as opposed to
-                 * the default dynamic margin. See also `spacingTop`.
-                 *
-                 * @sample {highcharts} highcharts/chart/margintop/ 100px top margin
-                 * @sample {highstock} stock/chart/margintop/
-                 *         100px top margin
-                 * @sample {highmaps} maps/chart/margin/
-                 *         100px margins
-                 *
-                 * @type      {number}
-                 * @since     2.0
-                 * @apioption chart.marginTop
-                 */
-                /**
-                 * Callback function to override the default function that formats all
-                 * the numbers in the chart. Returns a string with the formatted number.
-                 *
-                 * @sample highcharts/members/highcharts-numberformat
-                 *      Arabic digits in Highcharts
-                 * @type {Highcharts.NumberFormatterCallbackFunction}
-                 * @since 8.0.0
-                 * @apioption chart.numberFormatter
-                 */
-                /**
-                 * Allows setting a key to switch between zooming and panning. Can be
-                 * one of `alt`, `ctrl`, `meta` (the command key on Mac and Windows
-                 * key on Windows) or `shift`. The keys are mapped directly to the key
-                 * properties of the click event argument (`event.altKey`,
-                 * `event.ctrlKey`, `event.metaKey` and `event.shiftKey`).
-                 *
-                 * @type       {string}
-                 * @since      4.0.3
-                 * @product    highcharts gantt
-                 * @validvalue ["alt", "ctrl", "meta", "shift"]
-                 * @apioption  chart.panKey
-                 */
-                /**
-                 * Allow panning in a chart. Best used with [panKey](#chart.panKey)
-                 * to combine zooming and panning.
-                 *
-                 * On touch devices, when the [tooltip.followTouchMove](
-                 * #tooltip.followTouchMove) option is `true` (default), panning
-                 * requires two fingers. To allow panning with one finger, set
-                 * `followTouchMove` to `false`.
-                 *
-                 * @sample  {highcharts} highcharts/chart/pankey/ Zooming and panning
-                 * @sample  {highstock} stock/chart/panning/ Zooming and xy panning
-                 *
-                 * @product highcharts highstock gantt
-                 * @apioption chart.panning
-                 */
-                /**
-                 * Enable or disable chart panning.
-                 *
-                 * @type      {boolean}
-                 * @default   {highcharts} false
-                 * @default   {highstock} true
-                 * @apioption chart.panning.enabled
-                 */
-                /**
-                 * Decides in what dimensions the user can pan the chart. Can be
-                 * one of `x`, `y`, or `xy`.
-                 *
-                 * @sample {highcharts} highcharts/chart/panning-type
-                 *         Zooming and xy panning
-                 *
-                 * @type    {string}
-                 * @validvalue ["x", "y", "xy"]
-                 * @default x
-                 * @apioption chart.panning.type
-                 */
-                /**
-                 * Equivalent to [zoomType](#chart.zoomType), but for multitouch
-                 * gestures only. By default, the `pinchType` is the same as the
-                 * `zoomType` setting. However, pinching can be enabled separately in
-                 * some cases, for example in stock charts where a mouse drag pans the
-                 * chart, while pinching is enabled. When [tooltip.followTouchMove](
-                 * #tooltip.followTouchMove) is true, pinchType only applies to
-                 * two-finger touches.
-                 *
-                 * @type       {string}
-                 * @default    {highcharts} undefined
-                 * @default    {highstock} x
-                 * @since      3.0
-                 * @product    highcharts highstock gantt
-                 * @validvalue ["x", "y", "xy"]
-                 * @apioption  chart.pinchType
-                 */
-                /**
-                 * Whether to apply styled mode. When in styled mode, no presentational
-                 * attributes or CSS are applied to the chart SVG. Instead, CSS rules
-                 * are required to style the chart. The default style sheet is
-                 * available from `https://code.highcharts.com/css/highcharts.css`.
-                 *
-                 * @type       {boolean}
-                 * @default    false
-                 * @since      7.0
-                 * @apioption  chart.styledMode
-                 */
-                styledMode: false,
-                /**
-                 * The corner radius of the outer chart border.
-                 *
-                 * @sample {highcharts} highcharts/chart/borderradius/
-                 *         20px radius
-                 * @sample {highstock} stock/chart/border/
-                 *         10px radius
-                 * @sample {highmaps} maps/chart/border/
-                 *         Border options
-                 *
-                 */
-                borderRadius: 0,
-                /**
-                 * In styled mode, this sets how many colors the class names
-                 * should rotate between. With ten colors, series (or points) are
-                 * given class names like `highcharts-color-0`, `highcharts-color-0`
-                 * [...] `highcharts-color-9`. The equivalent in non-styled mode
-                 * is to set colors using the [colors](#colors) setting.
-                 *
-                 * @since      5.0.0
-                 */
-                colorCount: 10,
-                /**
-                 * Alias of `type`.
-                 *
-                 * @sample {highcharts} highcharts/chart/defaultseriestype/
-                 *         Bar
-                 *
-                 * @deprecated
-                 *
-                 * @product highcharts
-                 */
-                defaultSeriesType: 'line',
-                /**
-                 * If true, the axes will scale to the remaining visible series once
-                 * one series is hidden. If false, hiding and showing a series will
-                 * not affect the axes or the other series. For stacks, once one series
-                 * within the stack is hidden, the rest of the stack will close in
-                 * around it even if the axis is not affected.
-                 *
-                 * @sample {highcharts} highcharts/chart/ignorehiddenseries-true/
-                 *         True by default
-                 * @sample {highcharts} highcharts/chart/ignorehiddenseries-false/
-                 *         False
-                 * @sample {highcharts} highcharts/chart/ignorehiddenseries-true-stacked/
-                 *         True with stack
-                 * @sample {highstock} stock/chart/ignorehiddenseries-true/
-                 *         True by default
-                 * @sample {highstock} stock/chart/ignorehiddenseries-false/
-                 *         False
-                 *
-                 * @since   1.2.0
-                 * @product highcharts highstock gantt
-                 */
-                ignoreHiddenSeries: true,
-                /**
-                 * Whether to invert the axes so that the x axis is vertical and y axis
-                 * is horizontal. When `true`, the x axis is [reversed](#xAxis.reversed)
-                 * by default.
-                 *
-                 * @productdesc {highcharts}
-                 * If a bar series is present in the chart, it will be inverted
-                 * automatically. Inverting the chart doesn't have an effect if there
-                 * are no cartesian series in the chart, or if the chart is
-                 * [polar](#chart.polar).
-                 *
-                 * @sample {highcharts} highcharts/chart/inverted/
-                 *         Inverted line
-                 * @sample {highstock} stock/navigator/inverted/
-                 *         Inverted stock chart
-                 *
-                 * @type      {boolean}
-                 * @default   false
-                 * @product   highcharts highstock gantt
-                 * @apioption chart.inverted
-                 */
-                /**
-                 * The distance between the outer edge of the chart and the content,
-                 * like title or legend, or axis title and labels if present. The
-                 * numbers in the array designate top, right, bottom and left
-                 * respectively. Use the options spacingTop, spacingRight, spacingBottom
-                 * and spacingLeft options for shorthand setting of one option.
-                 *
-                 * @type    {Array<number>}
-                 * @see     [chart.margin](#chart.margin)
-                 * @default [10, 10, 15, 10]
-                 * @since   3.0.6
-                 */
-                spacing: [10, 10, 15, 10],
-                /**
-                 * The button that appears after a selection zoom, allowing the user
-                 * to reset zoom.
-                 */
-                resetZoomButton: {
-                    /**
-                     * What frame the button placement should be related to. Can be
-                     * either `plotBox` or `spacingBox`.
-                     *
-                     * @sample {highcharts} highcharts/chart/resetzoombutton-relativeto/
-                     *         Relative to the chart
-                     * @sample {highstock} highcharts/chart/resetzoombutton-relativeto/
-                     *         Relative to the chart
-                     *
-                     * @type       {Highcharts.ButtonRelativeToValue}
-                     * @default    plot
-                     * @since      2.2
-                     * @apioption  chart.resetZoomButton.relativeTo
-                     */
-                    /**
-                     * A collection of attributes for the button. The object takes SVG
-                     * attributes like `fill`, `stroke`, `stroke-width` or `r`, the
-                     * border radius. The theme also supports `style`, a collection of
-                     * CSS properties for the text. Equivalent attributes for the hover
-                     * state are given in `theme.states.hover`.
-                     *
-                     * @sample {highcharts} highcharts/chart/resetzoombutton-theme/
-                     *         Theming the button
-                     * @sample {highstock} highcharts/chart/resetzoombutton-theme/
-                     *         Theming the button
-                     *
-                     * @type {Highcharts.SVGAttributes}
-                     * @since 2.2
-                     */
-                    theme: {
-                        /** @internal */
-                        zIndex: 6
-                    },
-                    /**
-                     * The position of the button.
-                     *
-                     * @sample {highcharts} highcharts/chart/resetzoombutton-position/
-                     *         Above the plot area
-                     * @sample {highstock} highcharts/chart/resetzoombutton-position/
-                     *         Above the plot area
-                     * @sample {highmaps} highcharts/chart/resetzoombutton-position/
-                     *         Above the plot area
-                     *
-                     * @type  {Highcharts.AlignObject}
-                     * @since 2.2
-                     */
-                    position: {
-                        /**
-                         * The horizontal alignment of the button.
-                         */
-                        align: 'right',
-                        /**
-                         * The horizontal offset of the button.
-                         */
-                        x: -10,
-                        /**
-                         * The vertical alignment of the button.
-                         *
-                         * @type       {Highcharts.VerticalAlignValue}
-                         * @default    top
-                         * @apioption  chart.resetZoomButton.position.verticalAlign
-                         */
-                        /**
-                         * The vertical offset of the button.
-                         */
-                        y: 10
-                    }
-                },
-                /**
-                 * The pixel width of the plot area border.
-                 *
-                 * @sample {highcharts} highcharts/chart/plotborderwidth/
-                 *         1px border
-                 * @sample {highstock} stock/chart/plotborder/
-                 *         2px border
-                 * @sample {highmaps} maps/chart/plotborder/
-                 *         Plot border options
-                 *
-                 * @type      {number}
-                 * @default   0
-                 * @apioption chart.plotBorderWidth
-                 */
-                /**
-                 * Whether to apply a drop shadow to the plot area. Requires that
-                 * plotBackgroundColor be set. The shadow can be an object configuration
-                 * containing `color`, `offsetX`, `offsetY`, `opacity` and `width`.
-                 *
-                 * @sample {highcharts} highcharts/chart/plotshadow/
-                 *         Plot shadow
-                 * @sample {highstock} stock/chart/plotshadow/
-                 *         Plot shadow
-                 * @sample {highmaps} maps/chart/plotborder/
-                 *         Plot border options
-                 *
-                 * @type      {boolean|Highcharts.CSSObject}
-                 * @default   false
-                 * @apioption chart.plotShadow
-                 */
-                /**
-                 * When true, cartesian charts like line, spline, area and column are
-                 * transformed into the polar coordinate system. This produces _polar
-                 * charts_, also known as _radar charts_.
-                 *
-                 * @sample {highcharts} highcharts/demo/polar/
-                 *         Polar chart
-                 * @sample {highcharts} highcharts/demo/polar-wind-rose/
-                 *         Wind rose, stacked polar column chart
-                 * @sample {highcharts} highcharts/demo/polar-spider/
-                 *         Spider web chart
-                 * @sample {highcharts} highcharts/parallel-coordinates/polar/
-                 *         Star plot, multivariate data in a polar chart
-                 *
-                 * @type      {boolean}
-                 * @default   false
-                 * @since     2.3.0
-                 * @product   highcharts
-                 * @requires  highcharts-more
-                 * @apioption chart.polar
-                 */
-                /**
-                 * Whether to reflow the chart to fit the width of the container div
-                 * on resizing the window.
-                 *
-                 * @sample {highcharts} highcharts/chart/reflow-true/
-                 *         True by default
-                 * @sample {highcharts} highcharts/chart/reflow-false/
-                 *         False
-                 * @sample {highstock} stock/chart/reflow-true/
-                 *         True by default
-                 * @sample {highstock} stock/chart/reflow-false/
-                 *         False
-                 * @sample {highmaps} maps/chart/reflow-true/
-                 *         True by default
-                 * @sample {highmaps} maps/chart/reflow-false/
-                 *         False
-                 *
-                 * @type      {boolean}
-                 * @default   true
-                 * @since     2.1
-                 * @apioption chart.reflow
-                 */
-                /**
-                 * The HTML element where the chart will be rendered. If it is a string,
-                 * the element by that id is used. The HTML element can also be passed
-                 * by direct reference, or as the first argument of the chart
-                 * constructor, in which case the option is not needed.
-                 *
-                 * @sample {highcharts} highcharts/chart/reflow-true/
-                 *         String
-                 * @sample {highcharts} highcharts/chart/renderto-object/
-                 *         Object reference
-                 * @sample {highcharts} highcharts/chart/renderto-jquery/
-                 *         Object reference through jQuery
-                 * @sample {highstock} stock/chart/renderto-string/
-                 *         String
-                 * @sample {highstock} stock/chart/renderto-object/
-                 *         Object reference
-                 * @sample {highstock} stock/chart/renderto-jquery/
-                 *         Object reference through jQuery
-                 *
-                 * @type      {string|Highcharts.HTMLDOMElement}
-                 * @apioption chart.renderTo
-                 */
-                /**
-                 * The background color of the marker square when selecting (zooming
-                 * in on) an area of the chart.
-                 *
-                 * @see In styled mode, the selection marker fill is set with the
-                 *      `.highcharts-selection-marker` class.
-                 *
-                 * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-                 * @default   rgba(51,92,173,0.25)
-                 * @since     2.1.7
-                 * @apioption chart.selectionMarkerFill
-                 */
-                /**
-                 * Whether to apply a drop shadow to the outer chart area. Requires
-                 * that backgroundColor be set. The shadow can be an object
-                 * configuration containing `color`, `offsetX`, `offsetY`, `opacity` and
-                 * `width`.
-                 *
-                 * @sample {highcharts} highcharts/chart/shadow/
-                 *         Shadow
-                 * @sample {highstock} stock/chart/shadow/
-                 *         Shadow
-                 * @sample {highmaps} maps/chart/border/
-                 *         Chart border and shadow
-                 *
-                 * @type      {boolean|Highcharts.CSSObject}
-                 * @default   false
-                 * @apioption chart.shadow
-                 */
-                /**
-                 * Whether to show the axes initially. This only applies to empty charts
-                 * where series are added dynamically, as axes are automatically added
-                 * to cartesian series.
-                 *
-                 * @sample {highcharts} highcharts/chart/showaxes-false/
-                 *         False by default
-                 * @sample {highcharts} highcharts/chart/showaxes-true/
-                 *         True
-                 *
-                 * @type      {boolean}
-                 * @since     1.2.5
-                 * @product   highcharts gantt
-                 * @apioption chart.showAxes
-                 */
-                /**
-                 * The space between the bottom edge of the chart and the content (plot
-                 * area, axis title and labels, title, subtitle or legend in top
-                 * position).
-                 *
-                 * @sample {highcharts} highcharts/chart/spacingbottom/
-                 *         Spacing bottom set to 100
-                 * @sample {highstock} stock/chart/spacingbottom/
-                 *         Spacing bottom set to 100
-                 * @sample {highmaps} maps/chart/spacing/
-                 *         Spacing 100 all around
-                 *
-                 * @type      {number}
-                 * @default   15
-                 * @since     2.1
-                 * @apioption chart.spacingBottom
-                 */
-                /**
-                 * The space between the left edge of the chart and the content (plot
-                 * area, axis title and labels, title, subtitle or legend in top
-                 * position).
-                 *
-                 * @sample {highcharts} highcharts/chart/spacingleft/
-                 *         Spacing left set to 100
-                 * @sample {highstock} stock/chart/spacingleft/
-                 *         Spacing left set to 100
-                 * @sample {highmaps} maps/chart/spacing/
-                 *         Spacing 100 all around
-                 *
-                 * @type      {number}
-                 * @default   10
-                 * @since     2.1
-                 * @apioption chart.spacingLeft
-                 */
-                /**
-                 * The space between the right edge of the chart and the content (plot
-                 * area, axis title and labels, title, subtitle or legend in top
-                 * position).
-                 *
-                 * @sample {highcharts} highcharts/chart/spacingright-100/
-                 *         Spacing set to 100
-                 * @sample {highcharts} highcharts/chart/spacingright-legend/
-                 *         Legend in right position with default spacing
-                 * @sample {highstock} stock/chart/spacingright/
-                 *         Spacing set to 100
-                 * @sample {highmaps} maps/chart/spacing/
-                 *         Spacing 100 all around
-                 *
-                 * @type      {number}
-                 * @default   10
-                 * @since     2.1
-                 * @apioption chart.spacingRight
-                 */
-                /**
-                 * The space between the top edge of the chart and the content (plot
-                 * area, axis title and labels, title, subtitle or legend in top
-                 * position).
-                 *
-                 * @sample {highcharts} highcharts/chart/spacingtop-100/
-                 *         A top spacing of 100
-                 * @sample {highcharts} highcharts/chart/spacingtop-10/
-                 *         Floating chart title makes the plot area align to the default
-                 *         spacingTop of 10.
-                 * @sample {highstock} stock/chart/spacingtop/
-                 *         A top spacing of 100
-                 * @sample {highmaps} maps/chart/spacing/
-                 *         Spacing 100 all around
-                 *
-                 * @type      {number}
-                 * @default   10
-                 * @since     2.1
-                 * @apioption chart.spacingTop
-                 */
-                /**
-                 * Additional CSS styles to apply inline to the container `div`. Note
-                 * that since the default font styles are applied in the renderer, it
-                 * is ignorant of the individual chart options and must be set globally.
-                 *
-                 * @see    In styled mode, general chart styles can be set with the
-                 *         `.highcharts-root` class.
-                 * @sample {highcharts} highcharts/chart/style-serif-font/
-                 *         Using a serif type font
-                 * @sample {highcharts} highcharts/css/em/
-                 *         Styled mode with relative font sizes
-                 * @sample {highstock} stock/chart/style/
-                 *         Using a serif type font
-                 * @sample {highmaps} maps/chart/style-serif-font/
-                 *         Using a serif type font
-                 *
-                 * @type      {Highcharts.CSSObject}
-                 * @default   {"fontFamily": "\"Lucida Grande\", \"Lucida Sans Unicode\", Verdana, Arial, Helvetica, sans-serif","fontSize":"12px"}
-                 * @apioption chart.style
-                 */
-                /**
-                 * The default series type for the chart. Can be any of the chart types
-                 * listed under [plotOptions](#plotOptions) and [series](#series) or can
-                 * be a series provided by an additional module.
-                 *
-                 * In TypeScript this option has no effect in sense of typing and
-                 * instead the `type` option must always be set in the series.
-                 *
-                 * @sample {highcharts} highcharts/chart/type-bar/
-                 *         Bar
-                 * @sample {highstock} stock/chart/type/
-                 *         Areaspline
-                 * @sample {highmaps} maps/chart/type-mapline/
-                 *         Mapline
-                 *
-                 * @type       {string}
-                 * @default    {highcharts} line
-                 * @default    {highstock} line
-                 * @default    {highmaps} map
-                 * @since      2.1.0
-                 * @apioption  chart.type
-                 */
-                /**
-                 * Decides in what dimensions the user can zoom by dragging the mouse.
-                 * Can be one of `x`, `y` or `xy`.
-                 *
-                 * @see [panKey](#chart.panKey)
-                 *
-                 * @sample {highcharts} highcharts/chart/zoomtype-none/
-                 *         None by default
-                 * @sample {highcharts} highcharts/chart/zoomtype-x/
-                 *         X
-                 * @sample {highcharts} highcharts/chart/zoomtype-y/
-                 *         Y
-                 * @sample {highcharts} highcharts/chart/zoomtype-xy/
-                 *         Xy
-                 * @sample {highstock} stock/demo/basic-line/
-                 *         None by default
-                 * @sample {highstock} stock/chart/zoomtype-x/
-                 *         X
-                 * @sample {highstock} stock/chart/zoomtype-y/
-                 *         Y
-                 * @sample {highstock} stock/chart/zoomtype-xy/
-                 *         Xy
-                 *
-                 * @type       {string}
-                 * @product    highcharts highstock gantt
-                 * @validvalue ["x", "y", "xy"]
-                 * @apioption  chart.zoomType
-                 */
-                /**
-                 * An explicit width for the chart. By default (when `null`) the width
-                 * is calculated from the offset width of the containing element.
-                 *
-                 * @sample {highcharts} highcharts/chart/width/
-                 *         800px wide
-                 * @sample {highstock} stock/chart/width/
-                 *         800px wide
-                 * @sample {highmaps} maps/chart/size/
-                 *         Chart with explicit size
-                 *
-                 * @type {null|number|string}
-                 */
-                width: null,
-                /**
-                 * An explicit height for the chart. If a _number_, the height is
-                 * given in pixels. If given a _percentage string_ (for example
-                 * `'56%'`), the height is given as the percentage of the actual chart
-                 * width. This allows for preserving the aspect ratio across responsive
-                 * sizes.
-                 *
-                 * By default (when `null`) the height is calculated from the offset
-                 * height of the containing element, or 400 pixels if the containing
-                 * element's height is 0.
-                 *
-                 * @sample {highcharts} highcharts/chart/height/
-                 *         500px height
-                 * @sample {highstock} stock/chart/height/
-                 *         300px height
-                 * @sample {highmaps} maps/chart/size/
-                 *         Chart with explicit size
-                 * @sample highcharts/chart/height-percent/
-                 *         Highcharts with percentage height
-                 *
-                 * @type {null|number|string}
-                 */
-                height: null,
-                /**
-                 * The color of the outer chart border.
-                 *
-                 * @see In styled mode, the stroke is set with the
-                 *      `.highcharts-background` class.
-                 *
-                 * @sample {highcharts} highcharts/chart/bordercolor/
-                 *         Brown border
-                 * @sample {highstock} stock/chart/border/
-                 *         Brown border
-                 * @sample {highmaps} maps/chart/border/
-                 *         Border options
-                 *
-                 * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-                 */
-                borderColor: '#335cad',
-                /**
-                 * The pixel width of the outer chart border.
-                 *
-                 * @see In styled mode, the stroke is set with the
-                 *      `.highcharts-background` class.
-                 *
-                 * @sample {highcharts} highcharts/chart/borderwidth/
-                 *         5px border
-                 * @sample {highstock} stock/chart/border/
-                 *         2px border
-                 * @sample {highmaps} maps/chart/border/
-                 *         Border options
-                 *
-                 * @type      {number}
-                 * @default   0
-                 * @apioption chart.borderWidth
-                 */
-                /**
-                 * The background color or gradient for the outer chart area.
-                 *
-                 * @see In styled mode, the background is set with the
-                 *      `.highcharts-background` class.
-                 *
-                 * @sample {highcharts} highcharts/chart/backgroundcolor-color/
-                 *         Color
-                 * @sample {highcharts} highcharts/chart/backgroundcolor-gradient/
-                 *         Gradient
-                 * @sample {highstock} stock/chart/backgroundcolor-color/
-                 *         Color
-                 * @sample {highstock} stock/chart/backgroundcolor-gradient/
-                 *         Gradient
-                 * @sample {highmaps} maps/chart/backgroundcolor-color/
-                 *         Color
-                 * @sample {highmaps} maps/chart/backgroundcolor-gradient/
-                 *         Gradient
-                 *
-                 * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-                 */
-                backgroundColor: '#ffffff',
-                /**
-                 * The background color or gradient for the plot area.
-                 *
-                 * @see In styled mode, the plot background is set with the
-                 *      `.highcharts-plot-background` class.
-                 *
-                 * @sample {highcharts} highcharts/chart/plotbackgroundcolor-color/
-                 *         Color
-                 * @sample {highcharts} highcharts/chart/plotbackgroundcolor-gradient/
-                 *         Gradient
-                 * @sample {highstock} stock/chart/plotbackgroundcolor-color/
-                 *         Color
-                 * @sample {highstock} stock/chart/plotbackgroundcolor-gradient/
-                 *         Gradient
-                 * @sample {highmaps} maps/chart/plotbackgroundcolor-color/
-                 *         Color
-                 * @sample {highmaps} maps/chart/plotbackgroundcolor-gradient/
-                 *         Gradient
-                 *
-                 * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-                 * @apioption chart.plotBackgroundColor
-                 */
-                /**
-                 * The URL for an image to use as the plot background. To set an image
-                 * as the background for the entire chart, set a CSS background image
-                 * to the container element. Note that for the image to be applied to
-                 * exported charts, its URL needs to be accessible by the export server.
-                 *
-                 * @see In styled mode, a plot background image can be set with the
-                 *      `.highcharts-plot-background` class and a [custom pattern](
-                 *      https://www.highcharts.com/docs/chart-design-and-style/
-                 *      gradients-shadows-and-patterns).
-                 *
-                 * @sample {highcharts} highcharts/chart/plotbackgroundimage/
-                 *         Skies
-                 * @sample {highstock} stock/chart/plotbackgroundimage/
-                 *         Skies
-                 *
-                 * @type      {string}
-                 * @apioption chart.plotBackgroundImage
-                 */
-                /**
-                 * The color of the inner chart or plot area border.
-                 *
-                 * @see In styled mode, a plot border stroke can be set with the
-                 *      `.highcharts-plot-border` class.
-                 *
-                 * @sample {highcharts} highcharts/chart/plotbordercolor/
-                 *         Blue border
-                 * @sample {highstock} stock/chart/plotborder/
-                 *         Blue border
-                 * @sample {highmaps} maps/chart/plotborder/
-                 *         Plot border options
-                 *
-                 * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-                 */
-                plotBorderColor: '#cccccc'
-            },
-            /**
-             * The chart's main title.
-             *
-             * @sample {highmaps} maps/title/title/
-             *         Title options demonstrated
-             */
-            title: {
-                /**
-                 * When the title is floating, the plot area will not move to make space
-                 * for it.
-                 *
-                 * @sample {highcharts} highcharts/chart/zoomtype-none/
-                 *         False by default
-                 * @sample {highcharts} highcharts/title/floating/
-                 *         True - title on top of the plot area
-                 * @sample {highstock} stock/chart/title-floating/
-                 *         True - title on top of the plot area
-                 *
-                 * @type      {boolean}
-                 * @default   false
-                 * @since     2.1
-                 * @apioption title.floating
-                 */
-                /**
-                 * CSS styles for the title. Use this for font styling, but use `align`,
-                 * `x` and `y` for text alignment.
-                 *
-                 * In styled mode, the title style is given in the `.highcharts-title`
-                 * class.
-                 *
-                 * @sample {highcharts} highcharts/title/style/
-                 *         Custom color and weight
-                 * @sample {highstock} stock/chart/title-style/
-                 *         Custom color and weight
-                 * @sample highcharts/css/titles/
-                 *         Styled mode
-                 *
-                 * @type      {Highcharts.CSSObject}
-                 * @default   {highcharts|highmaps} { "color": "#333333", "fontSize": "18px" }
-                 * @default   {highstock} { "color": "#333333", "fontSize": "16px" }
-                 * @apioption title.style
-                 */
-                /**
-                 * Whether to
-                 * [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html)
-                 * to render the text.
-                 *
-                 * @type      {boolean}
-                 * @default   false
-                 * @apioption title.useHTML
-                 */
-                /**
-                 * The vertical alignment of the title. Can be one of `"top"`,
-                 * `"middle"` and `"bottom"`. When a value is given, the title behaves
-                 * as if [floating](#title.floating) were `true`.
-                 *
-                 * @sample {highcharts} highcharts/title/verticalalign/
-                 *         Chart title in bottom right corner
-                 * @sample {highstock} stock/chart/title-verticalalign/
-                 *         Chart title in bottom right corner
-                 *
-                 * @type      {Highcharts.VerticalAlignValue}
-                 * @since     2.1
-                 * @apioption title.verticalAlign
-                 */
-                /**
-                 * The x position of the title relative to the alignment within
-                 * `chart.spacingLeft` and `chart.spacingRight`.
-                 *
-                 * @sample {highcharts} highcharts/title/align/
-                 *         Aligned to the plot area (x = 70px = margin left - spacing
-                 *         left)
-                 * @sample {highstock} stock/chart/title-align/
-                 *         Aligned to the plot area (x = 50px = margin left - spacing
-                 *         left)
-                 *
-                 * @type      {number}
-                 * @default   0
-                 * @since     2.0
-                 * @apioption title.x
-                 */
-                /**
-                 * The y position of the title relative to the alignment within
-                 * [chart.spacingTop](#chart.spacingTop) and [chart.spacingBottom](
-                 * #chart.spacingBottom). By default it depends on the font size.
-                 *
-                 * @sample {highcharts} highcharts/title/y/
-                 *         Title inside the plot area
-                 * @sample {highstock} stock/chart/title-verticalalign/
-                 *         Chart title in bottom right corner
-                 *
-                 * @type      {number}
-                 * @since     2.0
-                 * @apioption title.y
-                 */
-                /**
-                 * The title of the chart. To disable the title, set the `text` to
-                 * `undefined`.
-                 *
-                 * @sample {highcharts} highcharts/title/text/
-                 *         Custom title
-                 * @sample {highstock} stock/chart/title-text/
-                 *         Custom title
-                 *
-                 * @default {highcharts|highmaps} Chart title
-                 * @default {highstock} undefined
-                 */
-                text: 'Chart title',
-                /**
-                 * The horizontal alignment of the title. Can be one of "left", "center"
-                 * and "right".
-                 *
-                 * @sample {highcharts} highcharts/title/align/
-                 *         Aligned to the plot area (x = 70px = margin left - spacing
-                 *         left)
-                 * @sample {highstock} stock/chart/title-align/
-                 *         Aligned to the plot area (x = 50px = margin left - spacing
-                 *         left)
-                 *
-                 * @type  {Highcharts.AlignValue}
-                 * @since 2.0
-                 */
-                align: 'center',
-                /**
-                 * The margin between the title and the plot area, or if a subtitle
-                 * is present, the margin between the subtitle and the plot area.
-                 *
-                 * @sample {highcharts} highcharts/title/margin-50/
-                 *         A chart title margin of 50
-                 * @sample {highcharts} highcharts/title/margin-subtitle/
-                 *         The same margin applied with a subtitle
-                 * @sample {highstock} stock/chart/title-margin/
-                 *         A chart title margin of 50
-                 *
-                 * @since 2.1
-                 */
-                margin: 15,
-                /**
-                 * Adjustment made to the title width, normally to reserve space for
-                 * the exporting burger menu.
-                 *
-                 * @sample highcharts/title/widthadjust/
-                 *         Wider menu, greater padding
-                 *
-                 * @since 4.2.5
-                 */
-                widthAdjust: -44
-            },
-            /**
-             * The chart's subtitle. This can be used both to display a subtitle below
-             * the main title, and to display random text anywhere in the chart. The
-             * subtitle can be updated after chart initialization through the
-             * `Chart.setTitle` method.
-             *
-             * @sample {highmaps} maps/title/subtitle/
-             *         Subtitle options demonstrated
-             */
-            subtitle: {
-                /**
-                 * When the subtitle is floating, the plot area will not move to make
-                 * space for it.
-                 *
-                 * @sample {highcharts} highcharts/subtitle/floating/
-                 *         Floating title and subtitle
-                 * @sample {highstock} stock/chart/subtitle-footnote
-                 *         Footnote floating at bottom right of plot area
-                 *
-                 * @type      {boolean}
-                 * @default   false
-                 * @since     2.1
-                 * @apioption subtitle.floating
-                 */
-                /**
-                 * CSS styles for the title.
-                 *
-                 * In styled mode, the subtitle style is given in the
-                 * `.highcharts-subtitle` class.
-                 *
-                 * @sample {highcharts} highcharts/subtitle/style/
-                 *         Custom color and weight
-                 * @sample {highcharts} highcharts/css/titles/
-                 *         Styled mode
-                 * @sample {highstock} stock/chart/subtitle-style
-                 *         Custom color and weight
-                 * @sample {highstock} highcharts/css/titles/
-                 *         Styled mode
-                 * @sample {highmaps} highcharts/css/titles/
-                 *         Styled mode
-                 *
-                 * @type      {Highcharts.CSSObject}
-                 * @default   {"color": "#666666"}
-                 * @apioption subtitle.style
-                 */
-                /**
-                 * Whether to
-                 * [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html)
-                 * to render the text.
-                 *
-                 * @type      {boolean}
-                 * @default   false
-                 * @apioption subtitle.useHTML
-                 */
-                /**
-                 * The vertical alignment of the title. Can be one of `"top"`,
-                 * `"middle"` and `"bottom"`. When middle, the subtitle behaves as
-                 * floating.
-                 *
-                 * @sample {highcharts} highcharts/subtitle/verticalalign/
-                 *         Footnote at the bottom right of plot area
-                 * @sample {highstock} stock/chart/subtitle-footnote
-                 *         Footnote at the bottom right of plot area
-                 *
-                 * @type      {Highcharts.VerticalAlignValue}
-                 * @since     2.1
-                 * @apioption subtitle.verticalAlign
-                 */
-                /**
-                 * The x position of the subtitle relative to the alignment within
-                 * `chart.spacingLeft` and `chart.spacingRight`.
-                 *
-                 * @sample {highcharts} highcharts/subtitle/align/
-                 *         Footnote at right of plot area
-                 * @sample {highstock} stock/chart/subtitle-footnote
-                 *         Footnote at the bottom right of plot area
-                 *
-                 * @type      {number}
-                 * @default   0
-                 * @since     2.0
-                 * @apioption subtitle.x
-                 */
-                /**
-                 * The y position of the subtitle relative to the alignment within
-                 * `chart.spacingTop` and `chart.spacingBottom`. By default the subtitle
-                 * is laid out below the title unless the title is floating.
-                 *
-                 * @sample {highcharts} highcharts/subtitle/verticalalign/
-                 *         Footnote at the bottom right of plot area
-                 * @sample {highstock} stock/chart/subtitle-footnote
-                 *         Footnote at the bottom right of plot area
-                 *
-                 * @type      {number}
-                 * @since     2.0
-                 * @apioption subtitle.y
-                 */
-                /**
-                 * The subtitle of the chart.
-                 *
-                 * @sample {highcharts|highstock} highcharts/subtitle/text/
-                 *         Custom subtitle
-                 * @sample {highcharts|highstock} highcharts/subtitle/text-formatted/
-                 *         Formatted and linked text.
-                 */
-                text: '',
-                /**
-                 * The horizontal alignment of the subtitle. Can be one of "left",
-                 *  "center" and "right".
-                 *
-                 * @sample {highcharts} highcharts/subtitle/align/
-                 *         Footnote at right of plot area
-                 * @sample {highstock} stock/chart/subtitle-footnote
-                 *         Footnote at bottom right of plot area
-                 *
-                 * @type  {Highcharts.AlignValue}
-                 * @since 2.0
-                 */
-                align: 'center',
-                /**
-                 * Adjustment made to the subtitle width, normally to reserve space
-                 * for the exporting burger menu.
-                 *
-                 * @see [title.widthAdjust](#title.widthAdjust)
-                 *
-                 * @sample highcharts/title/widthadjust/
-                 *         Wider menu, greater padding
-                 *
-                 * @since 4.2.5
-                 */
-                widthAdjust: -44
-            },
-            /**
-             * The chart's caption, which will render below the chart and will be part
-             * of exported charts. The caption can be updated after chart initialization
-             * through the `Chart.update` or `Chart.caption.update` methods.
-             *
-             * @sample highcharts/caption/text/
-             *         A chart with a caption
-             * @since  7.2.0
-             */
-            caption: {
-                /**
-                 * When the caption is floating, the plot area will not move to make
-                 * space for it.
-                 *
-                 * @type      {boolean}
-                 * @default   false
-                 * @apioption caption.floating
-                 */
-                /**
-                 * The margin between the caption and the plot area.
-                 */
-                margin: 15,
-                /**
-                 * CSS styles for the caption.
-                 *
-                 * In styled mode, the caption style is given in the
-                 * `.highcharts-caption` class.
-                 *
-                 * @sample {highcharts} highcharts/css/titles/
-                 *         Styled mode
-                 *
-                 * @type      {Highcharts.CSSObject}
-                 * @default   {"color": "#666666"}
-                 * @apioption caption.style
-                 */
-                /**
-                 * Whether to
-                 * [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html)
-                 * to render the text.
-                 *
-                 * @type      {boolean}
-                 * @default   false
-                 * @apioption caption.useHTML
-                 */
-                /**
-                 * The x position of the caption relative to the alignment within
-                 * `chart.spacingLeft` and `chart.spacingRight`.
-                 *
-                 * @type      {number}
-                 * @default   0
-                 * @apioption caption.x
-                 */
-                /**
-                 * The y position of the caption relative to the alignment within
-                 * `chart.spacingTop` and `chart.spacingBottom`.
-                 *
-                 * @type      {number}
-                 * @apioption caption.y
-                 */
-                /**
-                 * The caption text of the chart.
-                 *
-                 * @sample {highcharts} highcharts/caption/text/
-                 *         Custom caption
-                 */
-                text: '',
-                /**
-                 * The horizontal alignment of the caption. Can be one of "left",
-                 *  "center" and "right".
-                 *
-                 * @type  {Highcharts.AlignValue}
-                 */
-                align: 'left',
-                /**
-                 * The vertical alignment of the caption. Can be one of `"top"`,
-                 * `"middle"` and `"bottom"`. When middle, the caption behaves as
-                 * floating.
-                 *
-                 * @type      {Highcharts.VerticalAlignValue}
-                 */
-                verticalAlign: 'bottom'
-            },
-            /**
-             * The plotOptions is a wrapper object for config objects for each series
-             * type. The config objects for each series can also be overridden for
-             * each series item as given in the series array.
-             *
-             * Configuration options for the series are given in three levels. Options
-             * for all series in a chart are given in the [plotOptions.series](
-             * #plotOptions.series) object. Then options for all series of a specific
-             * type are given in the plotOptions of that type, for example
-             * `plotOptions.line`. Next, options for one single series are given in
-             * [the series array](#series).
-             */
-            plotOptions: {},
-            /**
-             * HTML labels that can be positioned anywhere in the chart area.
-             *
-             * This option is deprecated since v7.1.2. Instead, use
-             * [annotations](#annotations) that support labels.
-             *
-             * @deprecated
-             * @product   highcharts highstock
-             */
-            labels: {
-                /**
-                 * An HTML label that can be positioned anywhere in the chart area.
-                 *
-                 * @deprecated
-                 * @type      {Array<*>}
-                 * @apioption labels.items
-                 */
-                /**
-                 * Inner HTML or text for the label.
-                 *
-                 * @deprecated
-                 * @type      {string}
-                 * @apioption labels.items.html
-                 */
-                /**
-                 * CSS styles for each label. To position the label, use left and top
-                 * like this:
-                 * ```js
-                 * style: {
-                 *     left: '100px',
-                 *     top: '100px'
-                 * }
-                 * ```
-                 *
-                 * @deprecated
-                 * @type      {Highcharts.CSSObject}
-                 * @apioption labels.items.style
-                 */
-                /**
-                 * Shared CSS styles for all labels.
-                 *
-                 * @deprecated
-                 * @type    {Highcharts.CSSObject}
-                 * @default {"color": "#333333", "position": "absolute"}
-                 */
-                style: {
-                    /**
-                     * @ignore-option
-                     */
-                    position: 'absolute',
-                    /**
-                     * @ignore-option
-                     */
-                    color: '#333333'
-                }
-            },
-            /**
-             * The legend is a box containing a symbol and name for each series
-             * item or point item in the chart. Each series (or points in case
-             * of pie charts) is represented by a symbol and its name in the legend.
-             *
-             * It is possible to override the symbol creator function and create
-             * [custom legend symbols](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/studies/legend-custom-symbol/).
-             *
-             * @productdesc {highmaps}
-             * A Highmaps legend by default contains one legend item per series, but if
-             * a `colorAxis` is defined, the axis will be displayed in the legend.
-             * Either as a gradient, or as multiple legend items for `dataClasses`.
-             */
-            legend: {
-                /**
-                 * The background color of the legend.
-                 *
-                 * @see In styled mode, the legend background fill can be applied with
-                 *      the `.highcharts-legend-box` class.
-                 *
-                 * @sample {highcharts} highcharts/legend/backgroundcolor/
-                 *         Yellowish background
-                 * @sample {highstock} stock/legend/align/
-                 *         Various legend options
-                 * @sample {highmaps} maps/legend/border-background/
-                 *         Border and background options
-                 *
-                 * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-                 * @apioption legend.backgroundColor
-                 */
-                /**
-                 * The width of the drawn border around the legend.
-                 *
-                 * @see In styled mode, the legend border stroke width can be applied
-                 *      with the `.highcharts-legend-box` class.
-                 *
-                 * @sample {highcharts} highcharts/legend/borderwidth/
-                 *         2px border width
-                 * @sample {highstock} stock/legend/align/
-                 *         Various legend options
-                 * @sample {highmaps} maps/legend/border-background/
-                 *         Border and background options
-                 *
-                 * @type      {number}
-                 * @default   0
-                 * @apioption legend.borderWidth
-                 */
-                /**
-                 * Enable or disable the legend. There is also a series-specific option,
-                 * [showInLegend](#plotOptions.series.showInLegend), that can hide the
-                 * series from the legend. In some series types this is `false` by
-                 * default, so it must set to `true` in order to show the legend for the
-                 * series.
-                 *
-                 * @sample {highcharts} highcharts/legend/enabled-false/ Legend disabled
-                 * @sample {highstock} stock/legend/align/ Various legend options
-                 * @sample {highmaps} maps/legend/enabled-false/ Legend disabled
-                 *
-                 * @default {highstock} false
-                 * @default {highmaps} true
-                 * @default {gantt} false
-                 */
-                enabled: true,
-                /**
-                 * The horizontal alignment of the legend box within the chart area.
-                 * Valid values are `left`, `center` and `right`.
-                 *
-                 * In the case that the legend is aligned in a corner position, the
-                 * `layout` option will determine whether to place it above/below
-                 * or on the side of the plot area.
-                 *
-                 * @sample {highcharts} highcharts/legend/align/
-                 *         Legend at the right of the chart
-                 * @sample {highstock} stock/legend/align/
-                 *         Various legend options
-                 * @sample {highmaps} maps/legend/alignment/
-                 *         Legend alignment
-                 *
-                 * @type  {Highcharts.AlignValue}
-                 * @since 2.0
-                 */
-                align: 'center',
-                /**
-                 * If the [layout](legend.layout) is `horizontal` and the legend items
-                 * span over two lines or more, whether to align the items into vertical
-                 * columns. Setting this to `false` makes room for more items, but will
-                 * look more messy.
-                 *
-                 * @since 6.1.0
-                 */
-                alignColumns: true,
-                /**
-                 * When the legend is floating, the plot area ignores it and is allowed
-                 * to be placed below it.
-                 *
-                 * @sample {highcharts} highcharts/legend/floating-false/
-                 *         False by default
-                 * @sample {highcharts} highcharts/legend/floating-true/
-                 *         True
-                 * @sample {highmaps} maps/legend/alignment/
-                 *         Floating legend
-                 *
-                 * @type      {boolean}
-                 * @default   false
-                 * @since     2.1
-                 * @apioption legend.floating
-                 */
-                /**
-                 * The layout of the legend items. Can be one of `horizontal` or
-                 * `vertical` or `proximate`. When `proximate`, the legend items will be
-                 * placed as close as possible to the graphs they're representing,
-                 * except in inverted charts or when the legend position doesn't allow
-                 * it.
-                 *
-                 * @sample {highcharts} highcharts/legend/layout-horizontal/
-                 *         Horizontal by default
-                 * @sample {highcharts} highcharts/legend/layout-vertical/
-                 *         Vertical
-                 * @sample highcharts/legend/layout-proximate
-                 *         Labels proximate to the data
-                 * @sample {highstock} stock/legend/layout-horizontal/
-                 *         Horizontal by default
-                 * @sample {highmaps} maps/legend/padding-itemmargin/
-                 *         Vertical with data classes
-                 * @sample {highmaps} maps/legend/layout-vertical/
-                 *         Vertical with color axis gradient
-                 *
-                 * @validvalue ["horizontal", "vertical", "proximate"]
-                 */
-                layout: 'horizontal',
-                /**
-                 * In a legend with horizontal layout, the itemDistance defines the
-                 * pixel distance between each item.
-                 *
-                 * @sample {highcharts} highcharts/legend/layout-horizontal/
-                 *         50px item distance
-                 * @sample {highstock} highcharts/legend/layout-horizontal/
-                 *         50px item distance
-                 *
-                 * @type      {number}
-                 * @default   {highcharts} 20
-                 * @default   {highstock} 20
-                 * @default   {highmaps} 8
-                 * @since     3.0.3
-                 * @apioption legend.itemDistance
-                 */
-                /**
-                 * The pixel bottom margin for each legend item.
-                 *
-                 * @sample {highcharts|highstock} highcharts/legend/padding-itemmargin/
-                 *         Padding and item margins demonstrated
-                 * @sample {highmaps} maps/legend/padding-itemmargin/
-                 *         Padding and item margins demonstrated
-                 *
-                 * @type      {number}
-                 * @default   0
-                 * @since     2.2.0
-                 * @apioption legend.itemMarginBottom
-                 */
-                /**
-                 * The pixel top margin for each legend item.
-                 *
-                 * @sample {highcharts|highstock} highcharts/legend/padding-itemmargin/
-                 *         Padding and item margins demonstrated
-                 * @sample {highmaps} maps/legend/padding-itemmargin/
-                 *         Padding and item margins demonstrated
-                 *
-                 * @type      {number}
-                 * @default   0
-                 * @since     2.2.0
-                 * @apioption legend.itemMarginTop
-                 */
-                /**
-                 * The width for each legend item. By default the items are laid out
-                 * successively. In a [horizontal layout](legend.layout), if the items
-                 * are laid out across two rows or more, they will be vertically aligned
-                 * depending on the [legend.alignColumns](legend.alignColumns) option.
-                 *
-                 * @sample {highcharts} highcharts/legend/itemwidth-default/
-                 *         Undefined by default
-                 * @sample {highcharts} highcharts/legend/itemwidth-80/
-                 *         80 for aligned legend items
-                 *
-                 * @type      {number}
-                 * @since     2.0
-                 * @apioption legend.itemWidth
-                 */
-                /**
-                 * A [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting)
-                 * for each legend label. Available variables relates to properties on
-                 * the series, or the point in case of pies.
-                 *
-                 * @type      {string}
-                 * @default   {name}
-                 * @since     1.3
-                 * @apioption legend.labelFormat
-                 */
-                /* eslint-disable valid-jsdoc */
-                /**
-                 * Callback function to format each of the series' labels. The `this`
-                 * keyword refers to the series object, or the point object in case of
-                 * pie charts. By default the series or point name is printed.
-                 *
-                 * @productdesc {highmaps}
-                 * In Highmaps the context can also be a data class in case of a
-                 * `colorAxis`.
-                 *
-                 * @sample {highcharts} highcharts/legend/labelformatter/
-                 *         Add text
-                 * @sample {highmaps} maps/legend/labelformatter/
-                 *         Data classes with label formatter
-                 *
-                 * @type {Highcharts.FormatterCallbackFunction<Point|Series>}
-                 */
-                labelFormatter: function () {
-                    /** eslint-enable valid-jsdoc */
-                    return this.name;
-                },
-                /**
-                 * Line height for the legend items. Deprecated as of 2.1\. Instead,
-                 * the line height for each item can be set using
-                 * `itemStyle.lineHeight`, and the padding between items using
-                 * `itemMarginTop` and `itemMarginBottom`.
-                 *
-                 * @sample {highcharts} highcharts/legend/lineheight/
-                 *         Setting padding
-                 *
-                 * @deprecated
-                 *
-                 * @type      {number}
-                 * @default   16
-                 * @since     2.0
-                 * @product   highcharts gantt
-                 * @apioption legend.lineHeight
-                 */
-                /**
-                 * If the plot area sized is calculated automatically and the legend is
-                 * not floating, the legend margin is the space between the legend and
-                 * the axis labels or plot area.
-                 *
-                 * @sample {highcharts} highcharts/legend/margin-default/
-                 *         12 pixels by default
-                 * @sample {highcharts} highcharts/legend/margin-30/
-                 *         30 pixels
-                 *
-                 * @type      {number}
-                 * @default   12
-                 * @since     2.1
-                 * @apioption legend.margin
-                 */
-                /**
-                 * Maximum pixel height for the legend. When the maximum height is
-                 * extended, navigation will show.
-                 *
-                 * @type      {number}
-                 * @since     2.3.0
-                 * @apioption legend.maxHeight
-                 */
-                /**
-                 * The color of the drawn border around the legend.
-                 *
-                 * @see In styled mode, the legend border stroke can be applied with the
-                 *      `.highcharts-legend-box` class.
-                 *
-                 * @sample {highcharts} highcharts/legend/bordercolor/
-                 *         Brown border
-                 * @sample {highstock} stock/legend/align/
-                 *         Various legend options
-                 * @sample {highmaps} maps/legend/border-background/
-                 *         Border and background options
-                 *
-                 * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-                 */
-                borderColor: '#999999',
-                /**
-                 * The border corner radius of the legend.
-                 *
-                 * @sample {highcharts} highcharts/legend/borderradius-default/
-                 *         Square by default
-                 * @sample {highcharts} highcharts/legend/borderradius-round/
-                 *         5px rounded
-                 * @sample {highmaps} maps/legend/border-background/
-                 *         Border and background options
-                 */
-                borderRadius: 0,
-                /**
-                 * Options for the paging or navigation appearing when the legend is
-                 * overflown. Navigation works well on screen, but not in static
-                 * exported images. One way of working around that is to
-                 * [increase the chart height in
-                 * export](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/legend/navigation-enabled-false/).
-                 */
-                navigation: {
-                    /**
-                     * How to animate the pages when navigating up or down. A value of
-                     * `true` applies the default navigation given in the
-                     * `chart.animation` option. Additional options can be given as an
-                     * object containing values for easing and duration.
-                     *
-                     * @sample {highcharts} highcharts/legend/navigation/
-                     *         Legend page navigation demonstrated
-                     * @sample {highstock} highcharts/legend/navigation/
-                     *         Legend page navigation demonstrated
-                     *
-                     * @type      {boolean|Partial<Highcharts.AnimationOptionsObject>}
-                     * @default   true
-                     * @since     2.2.4
-                     * @apioption legend.navigation.animation
-                     */
-                    /**
-                     * The pixel size of the up and down arrows in the legend paging
-                     * navigation.
-                     *
-                     * @sample {highcharts} highcharts/legend/navigation/
-                     *         Legend page navigation demonstrated
-                     * @sample {highstock} highcharts/legend/navigation/
-                     *         Legend page navigation demonstrated
-                     *
-                     * @type      {number}
-                     * @default   12
-                     * @since     2.2.4
-                     * @apioption legend.navigation.arrowSize
-                     */
-                    /**
-                     * Whether to enable the legend navigation. In most cases, disabling
-                     * the navigation results in an unwanted overflow.
-                     *
-                     * See also the [adapt chart to legend](
-                     * https://www.highcharts.com/products/plugin-registry/single/8/Adapt-Chart-To-Legend)
-                     * plugin for a solution to extend the chart height to make room for
-                     * the legend, optionally in exported charts only.
-                     *
-                     * @type      {boolean}
-                     * @default   true
-                     * @since     4.2.4
-                     * @apioption legend.navigation.enabled
-                     */
-                    /**
-                     * Text styles for the legend page navigation.
-                     *
-                     * @see In styled mode, the navigation items are styled with the
-                     *      `.highcharts-legend-navigation` class.
-                     *
-                     * @sample {highcharts} highcharts/legend/navigation/
-                     *         Legend page navigation demonstrated
-                     * @sample {highstock} highcharts/legend/navigation/
-                     *         Legend page navigation demonstrated
-                     *
-                     * @type      {Highcharts.CSSObject}
-                     * @since     2.2.4
-                     * @apioption legend.navigation.style
-                     */
-                    /**
-                     * The color for the active up or down arrow in the legend page
-                     * navigation.
-                     *
-                     * @see In styled mode, the active arrow be styled with the
-                     *      `.highcharts-legend-nav-active` class.
-                     *
-                     * @sample  {highcharts} highcharts/legend/navigation/
-                     *          Legend page navigation demonstrated
-                     * @sample  {highstock} highcharts/legend/navigation/
-                     *          Legend page navigation demonstrated
-                     *
-                     * @type  {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-                     * @since 2.2.4
-                     */
-                    activeColor: '#003399',
-                    /**
-                     * The color of the inactive up or down arrow in the legend page
-                     * navigation. .
-                     *
-                     * @see In styled mode, the inactive arrow be styled with the
-                     *      `.highcharts-legend-nav-inactive` class.
-                     *
-                     * @sample {highcharts} highcharts/legend/navigation/
-                     *         Legend page navigation demonstrated
-                     * @sample {highstock} highcharts/legend/navigation/
-                     *         Legend page navigation demonstrated
-                     *
-                     * @type  {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-                     * @since 2.2.4
-                     */
-                    inactiveColor: '#cccccc'
-                },
-                /**
-                 * The inner padding of the legend box.
-                 *
-                 * @sample {highcharts|highstock} highcharts/legend/padding-itemmargin/
-                 *         Padding and item margins demonstrated
-                 * @sample {highmaps} maps/legend/padding-itemmargin/
-                 *         Padding and item margins demonstrated
-                 *
-                 * @type      {number}
-                 * @default   8
-                 * @since     2.2.0
-                 * @apioption legend.padding
-                 */
-                /**
-                 * Whether to reverse the order of the legend items compared to the
-                 * order of the series or points as defined in the configuration object.
-                 *
-                 * @see [yAxis.reversedStacks](#yAxis.reversedStacks),
-                 *      [series.legendIndex](#series.legendIndex)
-                 *
-                 * @sample {highcharts} highcharts/legend/reversed/
-                 *         Stacked bar with reversed legend
-                 *
-                 * @type      {boolean}
-                 * @default   false
-                 * @since     1.2.5
-                 * @apioption legend.reversed
-                 */
-                /**
-                 * Whether to show the symbol on the right side of the text rather than
-                 * the left side. This is common in Arabic and Hebraic.
-                 *
-                 * @sample {highcharts} highcharts/legend/rtl/
-                 *         Symbol to the right
-                 *
-                 * @type      {boolean}
-                 * @default   false
-                 * @since     2.2
-                 * @apioption legend.rtl
-                 */
-                /**
-                 * CSS styles for the legend area. In the 1.x versions the position
-                 * of the legend area was determined by CSS. In 2.x, the position is
-                 * determined by properties like `align`, `verticalAlign`, `x` and `y`,
-                 * but the styles are still parsed for backwards compatibility.
-                 *
-                 * @deprecated
-                 *
-                 * @type      {Highcharts.CSSObject}
-                 * @product   highcharts highstock
-                 * @apioption legend.style
-                 */
-                /**
-                 * CSS styles for each legend item. Only a subset of CSS is supported,
-                 * notably those options related to text. The default `textOverflow`
-                 * property makes long texts truncate. Set it to `undefined` to wrap
-                 * text instead. A `width` property can be added to control the text
-                 * width.
-                 *
-                 * @see In styled mode, the legend items can be styled with the
-                 *      `.highcharts-legend-item` class.
-                 *
-                 * @sample {highcharts} highcharts/legend/itemstyle/
-                 *         Bold black text
-                 * @sample {highmaps} maps/legend/itemstyle/
-                 *         Item text styles
-                 *
-                 * @type    {Highcharts.CSSObject}
-                 * @default {"color": "#333333", "cursor": "pointer", "fontSize": "12px", "fontWeight": "bold", "textOverflow": "ellipsis"}
-                 */
-                itemStyle: {
-                    /**
-                     * @ignore
-                     */
-                    color: '#333333',
-                    /**
-                     * @ignore
-                     */
-                    cursor: 'pointer',
-                    /**
-                     * @ignore
-                     */
-                    fontSize: '12px',
-                    /**
-                     * @ignore
-                     */
-                    fontWeight: 'bold',
-                    /**
-                     * @ignore
-                     */
-                    textOverflow: 'ellipsis'
-                },
-                /**
-                 * CSS styles for each legend item in hover mode. Only a subset of
-                 * CSS is supported, notably those options related to text. Properties
-                 * are inherited from `style` unless overridden here.
-                 *
-                 * @see In styled mode, the hovered legend items can be styled with
-                 *      the `.highcharts-legend-item:hover` pesudo-class.
-                 *
-                 * @sample {highcharts} highcharts/legend/itemhoverstyle/
-                 *         Red on hover
-                 * @sample {highmaps} maps/legend/itemstyle/
-                 *         Item text styles
-                 *
-                 * @type    {Highcharts.CSSObject}
-                 * @default {"color": "#000000"}
-                 */
-                itemHoverStyle: {
-                    /**
-                     * @ignore
-                     */
-                    color: '#000000'
-                },
-                /**
-                 * CSS styles for each legend item when the corresponding series or
-                 * point is hidden. Only a subset of CSS is supported, notably those
-                 * options related to text. Properties are inherited from `style`
-                 * unless overridden here.
-                 *
-                 * @see In styled mode, the hidden legend items can be styled with
-                 *      the `.highcharts-legend-item-hidden` class.
-                 *
-                 * @sample {highcharts} highcharts/legend/itemhiddenstyle/
-                 *         Darker gray color
-                 *
-                 * @type    {Highcharts.CSSObject}
-                 * @default {"color": "#cccccc"}
-                 */
-                itemHiddenStyle: {
-                    /**
-                     * @ignore
-                     */
-                    color: '#cccccc'
-                },
-                /**
-                 * Whether to apply a drop shadow to the legend. A `backgroundColor`
-                 * also needs to be applied for this to take effect. The shadow can be
-                 * an object configuration containing `color`, `offsetX`, `offsetY`,
-                 * `opacity` and `width`.
-                 *
-                 * @sample {highcharts} highcharts/legend/shadow/
-                 *         White background and drop shadow
-                 * @sample {highstock} stock/legend/align/
-                 *         Various legend options
-                 * @sample {highmaps} maps/legend/border-background/
-                 *         Border and background options
-                 *
-                 * @type {boolean|Highcharts.CSSObject}
-                 */
-                shadow: false,
-                /**
-                 * Default styling for the checkbox next to a legend item when
-                 * `showCheckbox` is true.
-                 *
-                 * @type {Highcharts.CSSObject}
-                 * @default {"width": "13px", "height": "13px", "position":"absolute"}
-                 */
-                itemCheckboxStyle: {
-                    /**
-                     * @ignore
-                     */
-                    position: 'absolute',
-                    /**
-                     * @ignore
-                     */
-                    width: '13px',
-                    /**
-                     * @ignore
-                     */
-                    height: '13px'
-                },
-                // itemWidth: undefined,
-                /**
-                 * When this is true, the legend symbol width will be the same as
-                 * the symbol height, which in turn defaults to the font size of the
-                 * legend items.
-                 *
-                 * @since 5.0.0
-                 */
-                squareSymbol: true,
-                /**
-                 * The pixel height of the symbol for series types that use a rectangle
-                 * in the legend. Defaults to the font size of legend items.
-                 *
-                 * @productdesc {highmaps}
-                 * In Highmaps, when the symbol is the gradient of a vertical color
-                 * axis, the height defaults to 200.
-                 *
-                 * @sample {highmaps} maps/legend/layout-vertical-sized/
-                 *         Sized vertical gradient
-                 * @sample {highmaps} maps/legend/padding-itemmargin/
-                 *         No distance between data classes
-                 *
-                 * @type      {number}
-                 * @since     3.0.8
-                 * @apioption legend.symbolHeight
-                 */
-                /**
-                 * The border radius of the symbol for series types that use a rectangle
-                 * in the legend. Defaults to half the `symbolHeight`.
-                 *
-                 * @sample {highcharts} highcharts/legend/symbolradius/
-                 *         Round symbols
-                 * @sample {highstock} highcharts/legend/symbolradius/
-                 *         Round symbols
-                 * @sample {highmaps} highcharts/legend/symbolradius/
-                 *         Round symbols
-                 *
-                 * @type      {number}
-                 * @since     3.0.8
-                 * @apioption legend.symbolRadius
-                 */
-                /**
-                 * The pixel width of the legend item symbol. When the `squareSymbol`
-                 * option is set, this defaults to the `symbolHeight`, otherwise 16.
-                 *
-                 * @productdesc {highmaps}
-                 * In Highmaps, when the symbol is the gradient of a horizontal color
-                 * axis, the width defaults to 200.
-                 *
-                 * @sample {highcharts} highcharts/legend/symbolwidth/
-                 *         Greater symbol width and padding
-                 * @sample {highmaps} maps/legend/padding-itemmargin/
-                 *         Padding and item margins demonstrated
-                 * @sample {highmaps} maps/legend/layout-vertical-sized/
-                 *         Sized vertical gradient
-                 *
-                 * @type      {number}
-                 * @apioption legend.symbolWidth
-                 */
-                /**
-                 * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html)
-                 * to render the legend item texts.
-                 *
-                 * Prior to 4.1.7, when using HTML, [legend.navigation](
-                 * #legend.navigation) was disabled.
-                 *
-                 * @type      {boolean}
-                 * @default   false
-                 * @apioption legend.useHTML
-                 */
-                /**
-                 * The width of the legend box. If a number is set, it translates to
-                 * pixels. Since v7.0.2 it allows setting a percent string of the full
-                 * chart width, for example `40%`.
-                 *
-                 * Defaults to the full chart width for legends below or above the
-                 * chart, half the chart width for legends to the left and right.
-                 *
-                 * @sample {highcharts} highcharts/legend/width/
-                 *         Aligned to the plot area
-                 * @sample {highcharts} highcharts/legend/width-percent/
-                 *         A percent of the chart width
-                 *
-                 * @type      {number|string}
-                 * @since     2.0
-                 * @apioption legend.width
-                 */
-                /**
-                 * The pixel padding between the legend item symbol and the legend
-                 * item text.
-                 *
-                 * @sample {highcharts} highcharts/legend/symbolpadding/
-                 *         Greater symbol width and padding
-                 */
-                symbolPadding: 5,
-                /**
-                 * The vertical alignment of the legend box. Can be one of `top`,
-                 * `middle` or `bottom`. Vertical position can be further determined
-                 * by the `y` option.
-                 *
-                 * In the case that the legend is aligned in a corner position, the
-                 * `layout` option will determine whether to place it above/below
-                 * or on the side of the plot area.
-                 *
-                 * When the [layout](#legend.layout) option is `proximate`, the
-                 * `verticalAlign` option doesn't apply.
-                 *
-                 * @sample {highcharts} highcharts/legend/verticalalign/
-                 *         Legend 100px from the top of the chart
-                 * @sample {highstock} stock/legend/align/
-                 *         Various legend options
-                 * @sample {highmaps} maps/legend/alignment/
-                 *         Legend alignment
-                 *
-                 * @type  {Highcharts.VerticalAlignValue}
-                 * @since 2.0
-                 */
-                verticalAlign: 'bottom',
-                // width: undefined,
-                /**
-                 * The x offset of the legend relative to its horizontal alignment
-                 * `align` within chart.spacingLeft and chart.spacingRight. Negative
-                 * x moves it to the left, positive x moves it to the right.
-                 *
-                 * @sample {highcharts} highcharts/legend/width/
-                 *         Aligned to the plot area
-                 *
-                 * @since 2.0
-                 */
-                x: 0,
-                /**
-                 * The vertical offset of the legend relative to it's vertical alignment
-                 * `verticalAlign` within chart.spacingTop and chart.spacingBottom.
-                 *  Negative y moves it up, positive y moves it down.
-                 *
-                 * @sample {highcharts} highcharts/legend/verticalalign/
-                 *         Legend 100px from the top of the chart
-                 * @sample {highstock} stock/legend/align/
-                 *         Various legend options
-                 * @sample {highmaps} maps/legend/alignment/
-                 *         Legend alignment
-                 *
-                 * @since 2.0
-                 */
-                y: 0,
-                /**
-                 * A title to be added on top of the legend.
-                 *
-                 * @sample {highcharts} highcharts/legend/title/
-                 *         Legend title
-                 * @sample {highmaps} maps/legend/alignment/
-                 *         Legend with title
-                 *
-                 * @since 3.0
-                 */
-                title: {
-                    /**
-                     * A text or HTML string for the title.
-                     *
-                     * @type      {string}
-                     * @since     3.0
-                     * @apioption legend.title.text
-                     */
-                    /**
-                     * Generic CSS styles for the legend title.
-                     *
-                     * @see In styled mode, the legend title is styled with the
-                     *      `.highcharts-legend-title` class.
-                     *
-                     * @type    {Highcharts.CSSObject}
-                     * @default {"fontWeight": "bold"}
-                     * @since   3.0
-                     */
-                    style: {
-                        /**
-                         * @ignore
-                         */
-                        fontWeight: 'bold'
-                    }
-                }
-            },
-            /**
-             * The loading options control the appearance of the loading screen
-             * that covers the plot area on chart operations. This screen only
-             * appears after an explicit call to `chart.showLoading()`. It is a
-             * utility for developers to communicate to the end user that something
-             * is going on, for example while retrieving new data via an XHR connection.
-             * The "Loading..." text itself is not part of this configuration
-             * object, but part of the `lang` object.
-             */
-            loading: {
-                /**
-                 * The duration in milliseconds of the fade out effect.
-                 *
-                 * @sample highcharts/loading/hideduration/
-                 *         Fade in and out over a second
-                 *
-                 * @type      {number}
-                 * @default   100
-                 * @since     1.2.0
-                 * @apioption loading.hideDuration
-                 */
-                /**
-                 * The duration in milliseconds of the fade in effect.
-                 *
-                 * @sample highcharts/loading/hideduration/
-                 *         Fade in and out over a second
-                 *
-                 * @type      {number}
-                 * @default   100
-                 * @since     1.2.0
-                 * @apioption loading.showDuration
-                 */
-                /**
-                 * CSS styles for the loading label `span`.
-                 *
-                 * @see In styled mode, the loading label is styled with the
-                 *      `.highcharts-loading-inner` class.
-                 *
-                 * @sample {highcharts|highmaps} highcharts/loading/labelstyle/
-                 *         Vertically centered
-                 * @sample {highstock} stock/loading/general/
-                 *         Label styles
-                 *
-                 * @type    {Highcharts.CSSObject}
-                 * @default {"fontWeight": "bold", "position": "relative", "top": "45%"}
-                 * @since   1.2.0
-                 */
-                labelStyle: {
-                    /**
-                     * @ignore
-                     */
-                    fontWeight: 'bold',
-                    /**
-                     * @ignore
-                     */
-                    position: 'relative',
-                    /**
-                     * @ignore
-                     */
-                    top: '45%'
-                },
-                /**
-                 * CSS styles for the loading screen that covers the plot area.
-                 *
-                 * In styled mode, the loading label is styled with the
-                 * `.highcharts-loading` class.
-                 *
-                 * @sample  {highcharts|highmaps} highcharts/loading/style/
-                 *          Gray plot area, white text
-                 * @sample  {highstock} stock/loading/general/
-                 *          Gray plot area, white text
-                 *
-                 * @type    {Highcharts.CSSObject}
-                 * @default {"position": "absolute", "backgroundColor": "#ffffff", "opacity": 0.5, "textAlign": "center"}
-                 * @since   1.2.0
-                 */
-                style: {
-                    /**
-                     * @ignore
-                     */
-                    position: 'absolute',
-                    /**
-                     * @ignore
-                     */
-                    backgroundColor: '#ffffff',
-                    /**
-                     * @ignore
-                     */
-                    opacity: 0.5,
-                    /**
-                     * @ignore
-                     */
-                    textAlign: 'center'
-                }
-            },
-            /**
-             * Options for the tooltip that appears when the user hovers over a
-             * series or point.
-             *
-             * @declare Highcharts.TooltipOptions
-             */
-            tooltip: {
-                /**
-                 * The color of the tooltip border. When `undefined`, the border takes
-                 * the color of the corresponding series or point.
-                 *
-                 * @sample {highcharts} highcharts/tooltip/bordercolor-default/
-                 *         Follow series by default
-                 * @sample {highcharts} highcharts/tooltip/bordercolor-black/
-                 *         Black border
-                 * @sample {highstock} stock/tooltip/general/
-                 *         Styled tooltip
-                 * @sample {highmaps} maps/tooltip/background-border/
-                 *         Background and border demo
-                 *
-                 * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-                 * @apioption tooltip.borderColor
-                 */
-                /**
-                 * A CSS class name to apply to the tooltip's container div,
-                 * allowing unique CSS styling for each chart.
-                 *
-                 * @type      {string}
-                 * @apioption tooltip.className
-                 */
-                /**
-                 * Since 4.1, the crosshair definitions are moved to the Axis object
-                 * in order for a better separation from the tooltip. See
-                 * [xAxis.crosshair](#xAxis.crosshair).
-                 *
-                 * @sample {highcharts} highcharts/tooltip/crosshairs-x/
-                 *         Enable a crosshair for the x value
-                 *
-                 * @deprecated
-                 *
-                 * @type      {*}
-                 * @default   true
-                 * @apioption tooltip.crosshairs
-                 */
-                /**
-                 * Distance from point to tooltip in pixels.
-                 *
-                 * @type      {number}
-                 * @default   16
-                 * @apioption tooltip.distance
-                 */
-                /**
-                 * Whether the tooltip should follow the mouse as it moves across
-                 * columns, pie slices and other point types with an extent.
-                 * By default it behaves this way for pie, polygon, map, sankey
-                 * and wordcloud series by override in the `plotOptions`
-                 * for those series types.
-                 *
-                 * For touch moves to behave the same way, [followTouchMove](
-                 * #tooltip.followTouchMove) must be `true` also.
-                 *
-                 * @type      {boolean}
-                 * @default   {highcharts} false
-                 * @default   {highstock} false
-                 * @default   {highmaps} true
-                 * @since     3.0
-                 * @apioption tooltip.followPointer
-                 */
-                /**
-                 * Whether the tooltip should update as the finger moves on a touch
-                 * device. If this is `true` and [chart.panning](#chart.panning) is
-                 * set,`followTouchMove` will take over one-finger touches, so the user
-                 * needs to use two fingers for zooming and panning.
-                 *
-                 * Note the difference to [followPointer](#tooltip.followPointer) that
-                 * only defines the _position_ of the tooltip. If `followPointer` is
-                 * false in for example a column series, the tooltip will show above or
-                 * below the column, but as `followTouchMove` is true, the tooltip will
-                 * jump from column to column as the user swipes across the plot area.
-                 *
-                 * @type      {boolean}
-                 * @default   {highcharts} true
-                 * @default   {highstock} true
-                 * @default   {highmaps} false
-                 * @since     3.0.1
-                 * @apioption tooltip.followTouchMove
-                 */
-                /**
-                 * Callback function to format the text of the tooltip from scratch. In
-                 * case of single or [shared](#tooltip.shared) tooltips, a string should
-                 * be returned. In case of [split](#tooltip.split) tooltips, it should
-                 * return an array where the first item is the header, and subsequent
-                 * items are mapped to the points. Return `false` to disable tooltip for
-                 * a specific point on series.
-                 *
-                 * A subset of HTML is supported. Unless `useHTML` is true, the HTML of
-                 * the tooltip is parsed and converted to SVG, therefore this isn't a
-                 * complete HTML renderer. The following HTML tags are supported: `b`,
-                 * `br`, `em`, `i`, `span`, `strong`. Spans can be styled with a `style`
-                 * attribute, but only text-related CSS, that is shared with SVG, is
-                 * handled.
-                 *
-                 * The available data in the formatter differ a bit depending on whether
-                 * the tooltip is shared or split, or belongs to a single point. In a
-                 * shared/split tooltip, all properties except `x`, which is common for
-                 * all points, are kept in an array, `this.points`.
-                 *
-                 * Available data are:
-                 *
-                 * - **this.percentage (not shared) /**
-                 *   **this.points[i].percentage (shared)**:
-                 *   Stacked series and pies only. The point's percentage of the total.
-                 *
-                 * - **this.point (not shared) / this.points[i].point (shared)**:
-                 *   The point object. The point name, if defined, is available through
-                 *   `this.point.name`.
-                 *
-                 * - **this.points**:
-                 *   In a shared tooltip, this is an array containing all other
-                 *   properties for each point.
-                 *
-                 * - **this.series (not shared) / this.points[i].series (shared)**:
-                 *   The series object. The series name is available through
-                 *   `this.series.name`.
-                 *
-                 * - **this.total (not shared) / this.points[i].total (shared)**:
-                 *   Stacked series only. The total value at this point's x value.
-                 *
-                 * - **this.x**:
-                 *   The x value. This property is the same regardless of the tooltip
-                 *   being shared or not.
-                 *
-                 * - **this.y (not shared) / this.points[i].y (shared)**:
-                 *   The y value.
-                 *
-                 * @sample {highcharts} highcharts/tooltip/formatter-simple/
-                 *         Simple string formatting
-                 * @sample {highcharts} highcharts/tooltip/formatter-shared/
-                 *         Formatting with shared tooltip
-                 * @sample {highcharts|highstock} highcharts/tooltip/formatter-split/
-                 *         Formatting with split tooltip
-                 * @sample highcharts/tooltip/formatter-conditional-default/
-                 *         Extending default formatter
-                 * @sample {highstock} stock/tooltip/formatter/
-                 *         Formatting with shared tooltip
-                 * @sample {highmaps} maps/tooltip/formatter/
-                 *         String formatting
-                 *
-                 * @type      {Highcharts.TooltipFormatterCallbackFunction}
-                 * @apioption tooltip.formatter
-                 */
-                /**
-                 * Callback function to format the text of the tooltip for
-                 * visible null points.
-                 * Works analogously to [formatter](#tooltip.formatter).
-                 *
-                 * @sample highcharts/plotoptions/series-nullformat
-                 *         Format data label and tooltip for null point.
-                 *
-                 * @type      {Highcharts.TooltipFormatterCallbackFunction}
-                 * @apioption tooltip.nullFormatter
-                 */
-                /**
-                 * The number of milliseconds to wait until the tooltip is hidden when
-                 * mouse out from a point or chart.
-                 *
-                 * @type      {number}
-                 * @default   500
-                 * @since     3.0
-                 * @apioption tooltip.hideDelay
-                 */
-                /**
-                 * Whether to allow the tooltip to render outside the chart's SVG
-                 * element box. By default (`false`), the tooltip is rendered within the
-                 * chart's SVG element, which results in the tooltip being aligned
-                 * inside the chart area. For small charts, this may result in clipping
-                 * or overlapping. When `true`, a separate SVG element is created and
-                 * overlaid on the page, allowing the tooltip to be aligned inside the
-                 * page itself.
-                 *
-                 * Defaults to `true` if `chart.scrollablePlotArea` is activated,
-                 * otherwise `false`.
-                 *
-                 * @sample highcharts/tooltip/outside
-                 *         Small charts with tooltips outside
-                 *
-                 * @type      {boolean|undefined}
-                 * @default   undefined
-                 * @since     6.1.1
-                 * @apioption tooltip.outside
-                 */
-                /**
-                 * A callback function for formatting the HTML output for a single point
-                 * in the tooltip. Like the `pointFormat` string, but with more
-                 * flexibility.
-                 *
-                 * @type      {Highcharts.FormatterCallbackFunction<Highcharts.Point>}
-                 * @since     4.1.0
-                 * @context   Highcharts.Point
-                 * @apioption tooltip.pointFormatter
-                 */
-                /**
-                 * A callback function to place the tooltip in a default position. The
-                 * callback receives three parameters: `labelWidth`, `labelHeight` and
-                 * `point`, where point contains values for `plotX` and `plotY` telling
-                 * where the reference point is in the plot area. Add `chart.plotLeft`
-                 * and `chart.plotTop` to get the full coordinates.
-                 *
-                 * Since v7, when [tooltip.split](#tooltip.split) option is enabled,
-                 * positioner is called for each of the boxes separately, including
-                 * xAxis header. xAxis header is not a point, instead `point` argument
-                 * contains info:
-                 * `{ plotX: Number, plotY: Number, isHeader: Boolean }`
-                 *
-                 *
-                 * The return should be an object containing x and y values, for example
-                 * `{ x: 100, y: 100 }`.
-                 *
-                 * @sample {highcharts} highcharts/tooltip/positioner/
-                 *         A fixed tooltip position
-                 * @sample {highstock} stock/tooltip/positioner/
-                 *         A fixed tooltip position on top of the chart
-                 * @sample {highmaps} maps/tooltip/positioner/
-                 *         A fixed tooltip position
-                 * @sample {highstock} stock/tooltip/split-positioner/
-                 *         Split tooltip with fixed positions
-                 * @sample {highstock} stock/tooltip/positioner-scrollable-plotarea/
-                 *         Scrollable plot area combined with tooltip positioner
-                 *
-                 * @type      {Highcharts.TooltipPositionerCallbackFunction}
-                 * @since     2.2.4
-                 * @apioption tooltip.positioner
-                 */
-                /**
-                 * The name of a symbol to use for the border around the tooltip. Can
-                 * be one of: `"callout"`, `"circle"`, or `"square"`. When
-                 * [tooltip.split](#tooltip.split)
-                 * option is enabled, shape is applied to all boxes except header, which
-                 * is controlled by
-                 * [tooltip.headerShape](#tooltip.headerShape).
-                 *
-                 * Custom callbacks for symbol path generation can also be added to
-                 * `Highcharts.SVGRenderer.prototype.symbols` the same way as for
-                 * [series.marker.symbol](plotOptions.line.marker.symbol).
-                 *
-                 * @type      {Highcharts.TooltipShapeValue}
-                 * @default   callout
-                 * @since     4.0
-                 * @apioption tooltip.shape
-                 */
-                /**
-                 * The name of a symbol to use for the border around the tooltip
-                 * header. Applies only when [tooltip.split](#tooltip.split) is
-                 * enabled.
-                 *
-                 * Custom callbacks for symbol path generation can also be added to
-                 * `Highcharts.SVGRenderer.prototype.symbols` the same way as for
-                 * [series.marker.symbol](plotOptions.line.marker.symbol).
-                 *
-                 * @see [tooltip.shape](#tooltip.shape)
-                 *
-                 * @sample {highstock} stock/tooltip/split-positioner/
-                 *         Different shapes for header and split boxes
-                 *
-                 * @type       {Highcharts.TooltipShapeValue}
-                 * @default    callout
-                 * @validvalue ["callout", "square"]
-                 * @since      7.0
-                 * @apioption  tooltip.headerShape
-                 */
-                /**
-                 * When the tooltip is shared, the entire plot area will capture mouse
-                 * movement or touch events. Tooltip texts for series types with ordered
-                 * data (not pie, scatter, flags etc) will be shown in a single bubble.
-                 * This is recommended for single series charts and for tablet/mobile
-                 * optimized charts.
-                 *
-                 * See also [tooltip.split](#tooltip.split), that is better suited for
-                 * charts with many series, especially line-type series. The
-                 * `tooltip.split` option takes precedence over `tooltip.shared`.
-                 *
-                 * @sample {highcharts} highcharts/tooltip/shared-false/
-                 *         False by default
-                 * @sample {highcharts} highcharts/tooltip/shared-true/
-                 *         True
-                 * @sample {highcharts} highcharts/tooltip/shared-x-crosshair/
-                 *         True with x axis crosshair
-                 * @sample {highcharts} highcharts/tooltip/shared-true-mixed-types/
-                 *         True with mixed series types
-                 *
-                 * @type      {boolean}
-                 * @default   false
-                 * @since     2.1
-                 * @product   highcharts highstock
-                 * @apioption tooltip.shared
-                 */
-                /**
-                 * Split the tooltip into one label per series, with the header close
-                 * to the axis. This is recommended over [shared](#tooltip.shared)
-                 * tooltips for charts with multiple line series, generally making them
-                 * easier to read. This option takes precedence over `tooltip.shared`.
-                 *
-                 * @productdesc {highstock} In Highstock, tooltips are split by default
-                 * since v6.0.0. Stock charts typically contain multi-dimension points
-                 * and multiple panes, making split tooltips the preferred layout over
-                 * the previous `shared` tooltip.
-                 *
-                 * @sample highcharts/tooltip/split/
-                 *         Split tooltip
-                 * @sample {highcharts|highstock} highcharts/tooltip/formatter-split/
-                 *         Split tooltip and custom formatter callback
-                 *
-                 * @type      {boolean}
-                 * @default   {highcharts} false
-                 * @default   {highstock} true
-                 * @since     5.0.0
-                 * @product   highcharts highstock
-                 * @apioption tooltip.split
-                 */
-                /**
-                 * Prevents the tooltip from switching or closing, when touched or
-                 * pointed.
-                 *
-                 * @sample highcharts/tooltip/stickoncontact/
-                 *         Tooltip sticks on pointer contact
-                 *
-                 * @type      {boolean}
-                 * @since     8.0.1
-                 * @apioption tooltip.stickOnContact
-                 */
-                /**
-                 * Use HTML to render the contents of the tooltip instead of SVG. Using
-                 * HTML allows advanced formatting like tables and images in the
-                 * tooltip. It is also recommended for rtl languages as it works around
-                 * rtl bugs in early Firefox.
-                 *
-                 * @sample {highcharts|highstock} highcharts/tooltip/footerformat/
-                 *         A table for value alignment
-                 * @sample {highcharts|highstock} highcharts/tooltip/fullhtml/
-                 *         Full HTML tooltip
-                 * @sample {highmaps} maps/tooltip/usehtml/
-                 *         Pure HTML tooltip
-                 *
-                 * @type      {boolean}
-                 * @default   false
-                 * @since     2.2
-                 * @apioption tooltip.useHTML
-                 */
-                /**
-                 * How many decimals to show in each series' y value. This is
-                 * overridable in each series' tooltip options object. The default is to
-                 * preserve all decimals.
-                 *
-                 * @sample {highcharts|highstock} highcharts/tooltip/valuedecimals/
-                 *         Set decimals, prefix and suffix for the value
-                 * @sample {highmaps} maps/tooltip/valuedecimals/
-                 *         Set decimals, prefix and suffix for the value
-                 *
-                 * @type      {number}
-                 * @since     2.2
-                 * @apioption tooltip.valueDecimals
-                 */
-                /**
-                 * A string to prepend to each series' y value. Overridable in each
-                 * series' tooltip options object.
-                 *
-                 * @sample {highcharts|highstock} highcharts/tooltip/valuedecimals/
-                 *         Set decimals, prefix and suffix for the value
-                 * @sample {highmaps} maps/tooltip/valuedecimals/
-                 *         Set decimals, prefix and suffix for the value
-                 *
-                 * @type      {string}
-                 * @since     2.2
-                 * @apioption tooltip.valuePrefix
-                 */
-                /**
-                 * A string to append to each series' y value. Overridable in each
-                 * series' tooltip options object.
-                 *
-                 * @sample {highcharts|highstock} highcharts/tooltip/valuedecimals/
-                 *         Set decimals, prefix and suffix for the value
-                 * @sample {highmaps} maps/tooltip/valuedecimals/
-                 *         Set decimals, prefix and suffix for the value
-                 *
-                 * @type      {string}
-                 * @since     2.2
-                 * @apioption tooltip.valueSuffix
-                 */
-                /**
-                 * The format for the date in the tooltip header if the X axis is a
-                 * datetime axis. The default is a best guess based on the smallest
-                 * distance between points in the chart.
-                 *
-                 * @sample {highcharts} highcharts/tooltip/xdateformat/
-                 *         A different format
-                 *
-                 * @type      {string}
-                 * @product   highcharts highstock gantt
-                 * @apioption tooltip.xDateFormat
-                 */
-                /**
-                 * How many decimals to show for the `point.change` value when the
-                 * `series.compare` option is set. This is overridable in each series'
-                 * tooltip options object. The default is to preserve all decimals.
-                 *
-                 * @type      {number}
-                 * @since     1.0.1
-                 * @product   highstock
-                 * @apioption tooltip.changeDecimals
-                 */
-                /**
-                 * Enable or disable the tooltip.
-                 *
-                 * @sample {highcharts} highcharts/tooltip/enabled/
-                 *         Disabled
-                 * @sample {highcharts} highcharts/plotoptions/series-point-events-mouseover/
-                 *         Disable tooltip and show values on chart instead
-                 */
-                enabled: true,
-                /**
-                 * Enable or disable animation of the tooltip.
-                 *
-                 * @type       {boolean}
-                 * @default    true
-                 * @since      2.3.0
-                 */
-                animation: svg,
-                /**
-                 * The radius of the rounded border corners.
-                 *
-                 * @sample {highcharts} highcharts/tooltip/bordercolor-default/
-                 *         5px by default
-                 * @sample {highcharts} highcharts/tooltip/borderradius-0/
-                 *         Square borders
-                 * @sample {highmaps} maps/tooltip/background-border/
-                 *         Background and border demo
-                 */
-                borderRadius: 3,
-                /**
-                 * For series on a datetime axes, the date format in the tooltip's
-                 * header will by default be guessed based on the closest data points.
-                 * This member gives the default string representations used for
-                 * each unit. For an overview of the replacement codes, see
-                 * [dateFormat](/class-reference/Highcharts#dateFormat).
-                 *
-                 * @see [xAxis.dateTimeLabelFormats](#xAxis.dateTimeLabelFormats)
-                 *
-                 * @type    {Highcharts.Dictionary<string>}
-                 * @product highcharts highstock gantt
-                 */
-                dateTimeLabelFormats: {
-                    /** @internal */
-                    millisecond: '%A, %b %e, %H:%M:%S.%L',
-                    /** @internal */
-                    second: '%A, %b %e, %H:%M:%S',
-                    /** @internal */
-                    minute: '%A, %b %e, %H:%M',
-                    /** @internal */
-                    hour: '%A, %b %e, %H:%M',
-                    /** @internal */
-                    day: '%A, %b %e, %Y',
-                    /** @internal */
-                    week: 'Week from %A, %b %e, %Y',
-                    /** @internal */
-                    month: '%B %Y',
-                    /** @internal */
-                    year: '%Y'
-                },
-                /**
-                 * A string to append to the tooltip format.
-                 *
-                 * @sample {highcharts} highcharts/tooltip/footerformat/
-                 *         A table for value alignment
-                 * @sample {highmaps} maps/tooltip/format/
-                 *         Format demo
-                 *
-                 * @since 2.2
-                 */
-                footerFormat: '',
-                /**
-                 * Padding inside the tooltip, in pixels.
-                 *
-                 * @since      5.0.0
-                 */
-                padding: 8,
-                /**
-                 * Proximity snap for graphs or single points. It defaults to 10 for
-                 * mouse-powered devices and 25 for touch devices.
-                 *
-                 * Note that in most cases the whole plot area captures the mouse
-                 * movement, and in these cases `tooltip.snap` doesn't make sense. This
-                 * applies when [stickyTracking](#plotOptions.series.stickyTracking)
-                 * is `true` (default) and when the tooltip is [shared](#tooltip.shared)
-                 * or [split](#tooltip.split).
-                 *
-                 * @sample {highcharts} highcharts/tooltip/bordercolor-default/
-                 *         10 px by default
-                 * @sample {highcharts} highcharts/tooltip/snap-50/
-                 *         50 px on graph
-                 *
-                 * @type    {number}
-                 * @default 10/25
-                 * @since   1.2.0
-                 * @product highcharts highstock
-                 */
-                snap: isTouchDevice ? 25 : 10,
-                /**
-                 * The HTML of the tooltip header line. Variables are enclosed by
-                 * curly brackets. Available variables are `point.key`, `series.name`,
-                 * `series.color` and other members from the `point` and `series`
-                 * objects. The `point.key` variable contains the category name, x
-                 * value or datetime string depending on the type of axis. For datetime
-                 * axes, the `point.key` date format can be set using
-                 * `tooltip.xDateFormat`.
-                 *
-                 * @sample {highcharts} highcharts/tooltip/footerformat/
-                 *         An HTML table in the tooltip
-                 * @sample {highstock} highcharts/tooltip/footerformat/
-                 *         An HTML table in the tooltip
-                 * @sample {highmaps} maps/tooltip/format/
-                 *         Format demo
-                 *
-                 * @type       {string}
-                 * @apioption  tooltip.headerFormat
-                 */
-                headerFormat: '<span style="font-size: 10px">{point.key}</span><br/>',
-                /**
-                 * The HTML of the null point's line in the tooltip. Works analogously
-                 * to [pointFormat](#tooltip.pointFormat).
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/series-nullformat
-                 *         Format data label and tooltip for null point.
-                 *
-                 * @type      {string}
-                 * @apioption tooltip.nullFormat
-                 */
-                /**
-                 * The HTML of the point's line in the tooltip. Variables are enclosed
-                 * by curly brackets. Available variables are `point.x`, `point.y`,
-                 * `series.name` and `series.color` and other properties on the same
-                 * form. Furthermore, `point.y` can be extended by the
-                 * `tooltip.valuePrefix` and `tooltip.valueSuffix` variables. This can
-                 * also be overridden for each series, which makes it a good hook for
-                 * displaying units.
-                 *
-                 * In styled mode, the dot is colored by a class name rather
-                 * than the point color.
-                 *
-                 * @sample {highcharts} highcharts/tooltip/pointformat/
-                 *         A different point format with value suffix
-                 * @sample {highmaps} maps/tooltip/format/
-                 *         Format demo
-                 *
-                 * @type       {string}
-                 * @since      2.2
-                 * @apioption  tooltip.pointFormat
-                 */
-                pointFormat: '<span style="color:{point.color}">\u25CF</span> {series.name}: <b>{point.y}</b><br/>',
-                /**
-                 * The background color or gradient for the tooltip.
-                 *
-                 * In styled mode, the stroke width is set in the
-                 * `.highcharts-tooltip-box` class.
-                 *
-                 * @sample {highcharts} highcharts/tooltip/backgroundcolor-solid/
-                 *         Yellowish background
-                 * @sample {highcharts} highcharts/tooltip/backgroundcolor-gradient/
-                 *         Gradient
-                 * @sample {highcharts} highcharts/css/tooltip-border-background/
-                 *         Tooltip in styled mode
-                 * @sample {highstock} stock/tooltip/general/
-                 *         Custom tooltip
-                 * @sample {highstock} highcharts/css/tooltip-border-background/
-                 *         Tooltip in styled mode
-                 * @sample {highmaps} maps/tooltip/background-border/
-                 *         Background and border demo
-                 * @sample {highmaps} highcharts/css/tooltip-border-background/
-                 *         Tooltip in styled mode
-                 *
-                 * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-                 */
-                backgroundColor: color('#f7f7f7')
-                    .setOpacity(0.85).get(),
-                /**
-                 * The pixel width of the tooltip border.
-                 *
-                 * In styled mode, the stroke width is set in the
-                 * `.highcharts-tooltip-box` class.
-                 *
-                 * @sample {highcharts} highcharts/tooltip/bordercolor-default/
-                 *         2px by default
-                 * @sample {highcharts} highcharts/tooltip/borderwidth/
-                 *         No border (shadow only)
-                 * @sample {highcharts} highcharts/css/tooltip-border-background/
-                 *         Tooltip in styled mode
-                 * @sample {highstock} stock/tooltip/general/
-                 *         Custom tooltip
-                 * @sample {highstock} highcharts/css/tooltip-border-background/
-                 *         Tooltip in styled mode
-                 * @sample {highmaps} maps/tooltip/background-border/
-                 *         Background and border demo
-                 * @sample {highmaps} highcharts/css/tooltip-border-background/
-                 *         Tooltip in styled mode
-                 */
-                borderWidth: 1,
-                /**
-                 * Whether to apply a drop shadow to the tooltip.
-                 *
-                 * @sample {highcharts} highcharts/tooltip/bordercolor-default/
-                 *         True by default
-                 * @sample {highcharts} highcharts/tooltip/shadow/
-                 *         False
-                 * @sample {highmaps} maps/tooltip/positioner/
-                 *         Fixed tooltip position, border and shadow disabled
-                 *
-                 * @type {boolean|Highcharts.ShadowOptionsObject}
-                 */
-                shadow: true,
-                /**
-                 * CSS styles for the tooltip. The tooltip can also be styled through
-                 * the CSS class `.highcharts-tooltip`.
-                 *
-                 * Note that the default `pointerEvents` style makes the tooltip ignore
-                 * mouse events, so in order to use clickable tooltips, this value must
-                 * be set to `auto`.
-                 *
-                 * @sample {highcharts} highcharts/tooltip/style/
-                 *         Greater padding, bold text
-                 *
-                 * @type {Highcharts.CSSObject}
-                 */
-                style: {
-                    /** @internal */
-                    color: '#333333',
-                    /** @internal */
-                    cursor: 'default',
-                    /** @internal */
-                    fontSize: '12px',
-                    /** @internal */
-                    whiteSpace: 'nowrap'
-                }
-            },
-            /**
-             * Highchart by default puts a credits label in the lower right corner
-             * of the chart. This can be changed using these options.
-             */
-            credits: {
-                /**
-                 * Credits for map source to be concatenated with conventional credit
-                 * text. By default this is a format string that collects copyright
-                 * information from the map if available.
-                 *
-                 * @see [mapTextFull](#credits.mapTextFull)
-                 * @see [text](#credits.text)
-                 *
-                 * @type      {string}
-                 * @default   \u00a9 <a href="{geojson.copyrightUrl}">{geojson.copyrightShort}</a>
-                 * @since     4.2.2
-                 * @product   highmaps
-                 * @apioption credits.mapText
-                 */
-                /**
-                 * Detailed credits for map source to be displayed on hover of credits
-                 * text. By default this is a format string that collects copyright
-                 * information from the map if available.
-                 *
-                 * @see [mapText](#credits.mapText)
-                 * @see [text](#credits.text)
-                 *
-                 * @type      {string}
-                 * @default   {geojson.copyright}
-                 * @since     4.2.2
-                 * @product   highmaps
-                 * @apioption credits.mapTextFull
-                 */
-                /**
-                 * Whether to show the credits text.
-                 *
-                 * @sample {highcharts} highcharts/credits/enabled-false/
-                 *         Credits disabled
-                 * @sample {highstock} stock/credits/enabled/
-                 *         Credits disabled
-                 * @sample {highmaps} maps/credits/enabled-false/
-                 *         Credits disabled
-                 */
-                enabled: true,
-                /**
-                 * The URL for the credits label.
-                 *
-                 * @sample {highcharts} highcharts/credits/href/
-                 *         Custom URL and text
-                 * @sample {highmaps} maps/credits/customized/
-                 *         Custom URL and text
-                 */
-                href: 'https://www.highcharts.com?credits',
-                /**
-                 * Position configuration for the credits label.
-                 *
-                 * @sample {highcharts} highcharts/credits/position-left/
-                 *         Left aligned
-                 * @sample {highcharts} highcharts/credits/position-left/
-                 *         Left aligned
-                 * @sample {highmaps} maps/credits/customized/
-                 *         Left aligned
-                 * @sample {highmaps} maps/credits/customized/
-                 *         Left aligned
-                 *
-                 * @type    {Highcharts.AlignObject}
-                 * @since   2.1
-                 */
-                position: {
-                    /** @internal */
-                    align: 'right',
-                    /** @internal */
-                    x: -10,
-                    /** @internal */
-                    verticalAlign: 'bottom',
-                    /** @internal */
-                    y: -5
-                },
-                /**
-                 * CSS styles for the credits label.
-                 *
-                 * @see In styled mode, credits styles can be set with the
-                 *      `.highcharts-credits` class.
-                 *
-                 * @type {Highcharts.CSSObject}
-                 */
-                style: {
-                    /** @internal */
-                    cursor: 'pointer',
-                    /** @internal */
-                    color: '#999999',
-                    /** @internal */
-                    fontSize: '9px'
-                },
-                /**
-                 * The text for the credits label.
-                 *
-                 * @productdesc {highmaps}
-                 * If a map is loaded as GeoJSON, the text defaults to
-                 * `Highcharts @ {map-credits}`. Otherwise, it defaults to
-                 * `Highcharts.com`.
-                 *
-                 * @sample {highcharts} highcharts/credits/href/
-                 *         Custom URL and text
-                 * @sample {highmaps} maps/credits/customized/
-                 *         Custom URL and text
-                 */
-                text: 'Highcharts.com'
-            }
-        };
-        /* eslint-disable spaced-comment */
-
-        '';
-        /**
-         * Global `Time` object with default options. Since v6.0.5, time settings can be
-         * applied individually for each chart. If no individual settings apply, this
-         * `Time` object is shared by all instances.
-         *
-         * @name Highcharts.time
-         * @type {Highcharts.Time}
-         */
-        H.time = new Time(merge(H.defaultOptions.global, H.defaultOptions.time));
-        /**
-         * Formats a JavaScript date timestamp (milliseconds since Jan 1st 1970) into a
-         * human readable date string. The format is a subset of the formats for PHP's
-         * [strftime](https://www.php.net/manual/en/function.strftime.php) function.
-         * Additional formats can be given in the {@link Highcharts.dateFormats} hook.
-         *
-         * Since v6.0.5, all internal dates are formatted through the
-         * {@link Highcharts.Chart#time} instance to respect chart-level time settings.
-         * The `Highcharts.dateFormat` function only reflects global time settings set
-         * with `setOptions`.
-         *
-         * Supported format keys:
-         * - `%a`: Short weekday, like 'Mon'
-         * - `%A`: Long weekday, like 'Monday'
-         * - `%d`: Two digit day of the month, 01 to 31
-         * - `%e`: Day of the month, 1 through 31
-         * - `%w`: Day of the week, 0 through 6
-         * - `%b`: Short month, like 'Jan'
-         * - `%B`: Long month, like 'January'
-         * - `%m`: Two digit month number, 01 through 12
-         * - `%y`: Two digits year, like 09 for 2009
-         * - `%Y`: Four digits year, like 2009
-         * - `%H`: Two digits hours in 24h format, 00 through 23
-         * - `%k`: Hours in 24h format, 0 through 23
-         * - `%I`: Two digits hours in 12h format, 00 through 11
-         * - `%l`: Hours in 12h format, 1 through 12
-         * - `%M`: Two digits minutes, 00 through 59
-         * - `%p`: Upper case AM or PM
-         * - `%P`: Lower case AM or PM
-         * - `%S`: Two digits seconds, 00 through 59
-         * - `%L`: Milliseconds (naming from Ruby)
-         *
-         * @function Highcharts.dateFormat
-         *
-         * @param {string} format
-         *        The desired format where various time representations are prefixed
-         *        with `%`.
-         *
-         * @param {number} timestamp
-         *        The JavaScript timestamp.
-         *
-         * @param {boolean} [capitalize=false]
-         *        Upper case first letter in the return.
-         *
-         * @return {string}
-         *         The formatted date.
-         */
-        H.dateFormat = function (format, timestamp, capitalize) {
-            return H.time.dateFormat(format, timestamp, capitalize);
-        };
-        var optionsModule = {
-                dateFormat: H.dateFormat,
-                defaultOptions: H.defaultOptions,
-                time: H.time
-            };
-
-        return optionsModule;
-    });
-    _registerModule(_modules, 'Core/Axis/Axis.js', [_modules['Core/Animation/AnimationUtilities.js'], _modules['Core/Color/Color.js'], _modules['Core/Globals.js'], _modules['Core/Axis/Tick.js'], _modules['Core/Utilities.js'], _modules['Core/Options.js']], function (A, Color, H, Tick, U, O) {
-        /* *
-         *
-         *  (c) 2010-2020 Torstein Honsi
-         *
-         *  License: www.highcharts.com/license
-         *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
-         *
-         * */
-        var animObject = A.animObject;
-        var addEvent = U.addEvent,
-            arrayMax = U.arrayMax,
-            arrayMin = U.arrayMin,
-            clamp = U.clamp,
-            correctFloat = U.correctFloat,
-            defined = U.defined,
-            destroyObjectProperties = U.destroyObjectProperties,
-            error = U.error,
-            extend = U.extend,
-            fireEvent = U.fireEvent,
-            format = U.format,
-            getMagnitude = U.getMagnitude,
-            isArray = U.isArray,
-            isFunction = U.isFunction,
-            isNumber = U.isNumber,
-            isString = U.isString,
-            merge = U.merge,
-            normalizeTickInterval = U.normalizeTickInterval,
-            objectEach = U.objectEach,
-            pick = U.pick,
-            relativeLength = U.relativeLength,
-            removeEvent = U.removeEvent,
-            splat = U.splat,
-            syncTimeout = U.syncTimeout;
-        /**
-         * Options for the path on the Axis to be calculated.
-         * @interface Highcharts.AxisPlotLinePathOptionsObject
-         */ /**
-        * Axis value.
-        * @name Highcharts.AxisPlotLinePathOptionsObject#value
-        * @type {number|undefined}
-        */ /**
-        * Line width used for calculation crisp line coordinates. Defaults to 1.
-        * @name Highcharts.AxisPlotLinePathOptionsObject#lineWidth
-        * @type {number|undefined}
-        */ /**
-        * If `false`, the function will return null when it falls outside the axis
-        * bounds. If `true`, the function will return a path aligned to the plot area
-        * sides if it falls outside. If `pass`, it will return a path outside.
-        * @name Highcharts.AxisPlotLinePathOptionsObject#force
-        * @type {string|boolean|undefined}
-        */ /**
-        * Used in Highstock. When `true`, plot paths (crosshair, plotLines, gridLines)
-        * will be rendered on all axes when defined on the first axis.
-        * @name Highcharts.AxisPlotLinePathOptionsObject#acrossPanes
-        * @type {boolean|undefined}
-        */ /**
-        * Use old coordinates (for resizing and rescaling).
-        * If not set, defaults to `false`.
-        * @name Highcharts.AxisPlotLinePathOptionsObject#old
-        * @type {boolean|undefined}
-        */ /**
-        * If given, return the plot line path of a pixel position on the axis.
-        * @name Highcharts.AxisPlotLinePathOptionsObject#translatedValue
-        * @type {number|undefined}
-        */ /**
-        * Used in Polar axes. Reverse the positions for concatenation of polygonal
-        * plot bands
-        * @name Highcharts.AxisPlotLinePathOptionsObject#reverse
-        * @type {boolean|undefined}
-        */
-        /**
-         * Options for crosshairs on axes.
-         *
-         * @product highstock
-         *
-         * @typedef {Highcharts.XAxisCrosshairOptions|Highcharts.YAxisCrosshairOptions} Highcharts.AxisCrosshairOptions
-         */
-        /**
-         * @typedef {"navigator"|"pan"|"rangeSelectorButton"|"rangeSelectorInput"|"scrollbar"|"traverseUpButton"|"zoom"} Highcharts.AxisExtremesTriggerValue
-         */
-        /**
-         * @callback Highcharts.AxisEventCallbackFunction
-         *
-         * @param {Highcharts.Axis} this
-         */
-        /**
-         * @callback Highcharts.AxisLabelsFormatterCallbackFunction
-         *
-         * @param {Highcharts.AxisLabelsFormatterContextObject<number>} this
-         *
-         * @param {Highcharts.AxisLabelsFormatterContextObject<string>} that
-         *
-         * @return {string}
-         */
-        /**
-         * @interface Highcharts.AxisLabelsFormatterContextObject<T>
-         */ /**
-        * @name Highcharts.AxisLabelsFormatterContextObject<T>#axis
-        * @type {Highcharts.Axis}
-        */ /**
-        * @name Highcharts.AxisLabelsFormatterContextObject<T>#chart
-        * @type {Highcharts.Chart}
-        */ /**
-        * @name Highcharts.AxisLabelsFormatterContextObject<T>#isFirst
-        * @type {boolean}
-        */ /**
-        * @name Highcharts.AxisLabelsFormatterContextObject<T>#isLast
-        * @type {boolean}
-        */ /**
-        * @name Highcharts.AxisLabelsFormatterContextObject<T>#pos
-        * @type {number}
-        */ /**
-        * This can be either a numeric value or a category string.
-        * @name Highcharts.AxisLabelsFormatterContextObject<T>#value
-        * @type {T}
-        */
-        /**
-         * Options for axes.
-         *
-         * @typedef {Highcharts.XAxisOptions|Highcharts.YAxisOptions|Highcharts.ZAxisOptions} Highcharts.AxisOptions
-         */
-        /**
-         * @callback Highcharts.AxisPointBreakEventCallbackFunction
-         *
-         * @param {Highcharts.Axis} this
-         *
-         * @param {Highcharts.AxisPointBreakEventObject} evt
-         */
-        /**
-         * @interface Highcharts.AxisPointBreakEventObject
-         */ /**
-        * @name Highcharts.AxisPointBreakEventObject#brk
-        * @type {Highcharts.Dictionary<number>}
-        */ /**
-        * @name Highcharts.AxisPointBreakEventObject#point
-        * @type {Highcharts.Point}
-        */ /**
-        * @name Highcharts.AxisPointBreakEventObject#preventDefault
-        * @type {Function}
-        */ /**
-        * @name Highcharts.AxisPointBreakEventObject#target
-        * @type {Highcharts.SVGElement}
-        */ /**
-        * @name Highcharts.AxisPointBreakEventObject#type
-        * @type {"pointBreak"|"pointInBreak"}
-        */
-        /**
-         * @callback Highcharts.AxisSetExtremesEventCallbackFunction
-         *
-         * @param {Highcharts.Axis} this
-         *
-         * @param {Highcharts.AxisSetExtremesEventObject} evt
-         */
-        /**
-         * @interface Highcharts.AxisSetExtremesEventObject
-         * @extends Highcharts.ExtremesObject
-         */ /**
-        * @name Highcharts.AxisSetExtremesEventObject#preventDefault
-        * @type {Function}
-        */ /**
-        * @name Highcharts.AxisSetExtremesEventObject#target
-        * @type {Highcharts.SVGElement}
-        */ /**
-        * @name Highcharts.AxisSetExtremesEventObject#trigger
-        * @type {Highcharts.AxisExtremesTriggerValue|string}
-        */ /**
-        * @name Highcharts.AxisSetExtremesEventObject#type
-        * @type {"setExtremes"}
-        */
-        /**
-         * @callback Highcharts.AxisTickPositionerCallbackFunction
-         *
-         * @param {Highcharts.Axis} this
-         *
-         * @return {Highcharts.AxisTickPositionsArray}
-         */
-        /**
-         * @interface Highcharts.AxisTickPositionsArray
-         * @augments Array<number>
-         */
-        /**
-         * @typedef {"high"|"low"|"middle"} Highcharts.AxisTitleAlignValue
-         */
-        /**
-         * @typedef {Highcharts.XAxisTitleOptions|Highcharts.YAxisTitleOptions|Highcharts.ZAxisTitleOptions} Highcharts.AxisTitleOptions
-         */
-        /**
-         * @typedef {"linear"|"logarithmic"|"datetime"|"category"|"treegrid"} Highcharts.AxisTypeValue
-         */
-        /**
-         * The returned object literal from the {@link Highcharts.Axis#getExtremes}
-         * function.
-         *
-         * @interface Highcharts.ExtremesObject
-         */ /**
-        * The maximum value of the axis' associated series.
-        * @name Highcharts.ExtremesObject#dataMax
-        * @type {number}
-        */ /**
-        * The minimum value of the axis' associated series.
-        * @name Highcharts.ExtremesObject#dataMin
-        * @type {number}
-        */ /**
-        * The maximum axis value, either automatic or set manually. If the `max` option
-        * is not set, `maxPadding` is 0 and `endOnTick` is false, this value will be
-        * the same as `dataMax`.
-        * @name Highcharts.ExtremesObject#max
-        * @type {number}
-        */ /**
-        * The minimum axis value, either automatic or set manually. If the `min` option
-        * is not set, `minPadding` is 0 and `startOnTick` is false, this value will be
-        * the same as `dataMin`.
-        * @name Highcharts.ExtremesObject#min
-        * @type {number}
-        */ /**
-        * The user defined maximum, either from the `max` option or from a zoom or
-        * `setExtremes` action.
-        * @name Highcharts.ExtremesObject#userMax
-        * @type {number}
-        */ /**
-        * The user defined minimum, either from the `min` option or from a zoom or
-        * `setExtremes` action.
-        * @name Highcharts.ExtremesObject#userMin
-        * @type {number}
-        */
-        /**
-         * Formatter function for the text of a crosshair label.
-         *
-         * @callback Highcharts.XAxisCrosshairLabelFormatterCallbackFunction
-         *
-         * @param {Highcharts.Axis} this
-         *        Axis context
-         *
-         * @param {number} value
-         *        Y value of the data point
-         *
-         * @return {string}
-         */
-        var defaultOptions = O.defaultOptions;
-        var deg2rad = H.deg2rad;
-        /**
-         * Create a new axis object. Called internally when instanciating a new chart or
-         * adding axes by {@link Highcharts.Chart#addAxis}.
-         *
-         * A chart can have from 0 axes (pie chart) to multiples. In a normal, single
-         * series cartesian chart, there is one X axis and one Y axis.
-         *
-         * The X axis or axes are referenced by {@link Highcharts.Chart.xAxis}, which is
-         * an array of Axis objects. If there is only one axis, it can be referenced
-         * through `chart.xAxis[0]`, and multiple axes have increasing indices. The same
-         * pattern goes for Y axes.
-         *
-         * If you need to get the axes from a series object, use the `series.xAxis` and
-         * `series.yAxis` properties. These are not arrays, as one series can only be
-         * associated to one X and one Y axis.
-         *
-         * A third way to reference the axis programmatically is by `id`. Add an `id` in
-         * the axis configuration options, and get the axis by
-         * {@link Highcharts.Chart#get}.
-         *
-         * Configuration options for the axes are given in options.xAxis and
-         * options.yAxis.
-         *
-         * @class
-         * @name Highcharts.Axis
-         *
-         * @param {Highcharts.Chart} chart
-         * The Chart instance to apply the axis on.
-         *
-         * @param {Highcharts.AxisOptions} userOptions
-         * Axis options.
-         */
-        var Axis = /** @class */ (function () {
-                /* *
-                 *
-                 *  Constructors
-                 *
-                 * */
-                function Axis(chart, userOptions) {
-                    this.alternateBands = void 0;
-                this.bottom = void 0;
-                this.categories = void 0;
-                this.chart = void 0;
-                this.closestPointRange = void 0;
-                this.coll = void 0;
-                this.hasNames = void 0;
-                this.hasVisibleSeries = void 0;
-                this.height = void 0;
-                this.isLinked = void 0;
-                this.labelEdge = void 0; // @todo
-                this.labelFormatter = void 0;
-                this.left = void 0;
-                this.len = void 0;
-                this.max = void 0;
-                this.maxLabelLength = void 0;
-                this.min = void 0;
-                this.minorTickInterval = void 0;
-                this.minorTicks = void 0;
-                this.minPixelPadding = void 0;
-                this.names = void 0;
-                this.offset = void 0;
-                this.oldMax = void 0;
-                this.oldMin = void 0;
-                this.options = void 0;
-                this.overlap = void 0;
-                this.paddedTicks = void 0;
-                this.plotLinesAndBands = void 0;
-                this.plotLinesAndBandsGroups = void 0;
-                this.pointRange = void 0;
-                this.pointRangePadding = void 0;
-                this.pos = void 0;
-                this.positiveValuesOnly = void 0;
-                this.right = void 0;
-                this.series = void 0;
-                this.side = void 0;
-                this.tickAmount = void 0;
-                this.tickInterval = void 0;
-                this.tickmarkOffset = void 0;
-                this.tickPositions = void 0;
-                this.tickRotCorr = void 0;
-                this.ticks = void 0;
-                this.top = void 0;
-                this.transA = void 0;
-                this.transB = void 0;
-                this.translationSlope = void 0;
-                this.userOptions = void 0;
-                this.visible = void 0;
-                this.width = void 0;
-                this.zoomEnabled = void 0;
-                this.init(chart, userOptions);
-            }
-            /* *
-             *
-             *  Functions
-             *
-             * */
-            /**
-             * Overrideable function to initialize the axis.
-             *
-             * @see {@link Axis}
-             *
-             * @function Highcharts.Axis#init
-             *
-             * @param {Highcharts.Chart} chart
-             * The Chart instance to apply the axis on.
-             *
-             * @param {Highcharts.AxisOptions} userOptions
-             * Axis options.
-             *
-             * @fires Highcharts.Axis#event:afterInit
-             * @fires Highcharts.Axis#event:init
-             */
-            Axis.prototype.init = function (chart, userOptions) {
-                var isXAxis = userOptions.isX,
-                    axis = this;
-                /**
-                 * The Chart that the axis belongs to.
-                 *
-                 * @name Highcharts.Axis#chart
-                 * @type {Highcharts.Chart}
-                 */
-                axis.chart = chart;
-                /**
-                 * Whether the axis is horizontal.
-                 *
-                 * @name Highcharts.Axis#horiz
-                 * @type {boolean|undefined}
-                 */
-                axis.horiz = chart.inverted && !axis.isZAxis ? !isXAxis : isXAxis;
-                /**
-                 * Whether the axis is the x-axis.
-                 *
-                 * @name Highcharts.Axis#isXAxis
-                 * @type {boolean|undefined}
-                 */
-                axis.isXAxis = isXAxis;
-                /**
-                 * The collection where the axis belongs, for example `xAxis`, `yAxis`
-                 * or `colorAxis`. Corresponds to properties on Chart, for example
-                 * {@link Chart.xAxis}.
-                 *
-                 * @name Highcharts.Axis#coll
-                 * @type {string}
-                 */
-                axis.coll = axis.coll || (isXAxis ? 'xAxis' : 'yAxis');
-                fireEvent(this, 'init', { userOptions: userOptions });
-                axis.opposite = userOptions.opposite; // needed in setOptions
-                /**
-                 * The side on which the axis is rendered. 0 is top, 1 is right, 2
-                 * is bottom and 3 is left.
-                 *
-                 * @name Highcharts.Axis#side
-                 * @type {number}
-                 */
-                axis.side = userOptions.side || (axis.horiz ?
-                    (axis.opposite ? 0 : 2) : // top : bottom
-                    (axis.opposite ? 1 : 3)); // right : left
-                /**
-                 * Current options for the axis after merge of defaults and user's
-                 * options.
-                 *
-                 * @name Highcharts.Axis#options
-                 * @type {Highcharts.AxisOptions}
-                 */
-                axis.setOptions(userOptions);
-                var options = this.options,
-                    type = options.type;
-                axis.labelFormatter = (options.labels.formatter ||
-                    // can be overwritten by dynamic format
-                    axis.defaultLabelFormatter);
-                /**
-                 * User's options for this axis without defaults.
-                 *
-                 * @name Highcharts.Axis#userOptions
-                 * @type {Highcharts.AxisOptions}
-                 */
-                axis.userOptions = userOptions;
-                axis.minPixelPadding = 0;
-                /**
-                 * Whether the axis is reversed. Based on the `axis.reversed`,
-                 * option, but inverted charts have reversed xAxis by default.
-                 *
-                 * @name Highcharts.Axis#reversed
-                 * @type {boolean}
-                 */
-                axis.reversed = options.reversed;
-                axis.visible = options.visible !== false;
-                axis.zoomEnabled = options.zoomEnabled !== false;
-                // Initial categories
-                axis.hasNames =
-                    type === 'category' || options.categories === true;
-                /**
-                 * If categories are present for the axis, names are used instead of
-                 * numbers for that axis.
-                 *
-                 * Since Highcharts 3.0, categories can also be extracted by giving each
-                 * point a name and setting axis type to `category`. However, if you
-                 * have multiple series, best practice remains defining the `categories`
-                 * array.
-                 *
-                 * @see [xAxis.categories](/highcharts/xAxis.categories)
-                 *
-                 * @name Highcharts.Axis#categories
-                 * @type {Array<string>}
-                 * @readonly
-                 */
-                axis.categories = options.categories || axis.hasNames;
-                if (!axis.names) { // Preserve on update (#3830)
-                    axis.names = [];
-                    axis.names.keys = {};
-                }
-                // Placeholder for plotlines and plotbands groups
-                axis.plotLinesAndBandsGroups = {};
-                // Shorthand types
-                axis.positiveValuesOnly = !!axis.logarithmic;
-                // Flag, if axis is linked to another axis
-                axis.isLinked = defined(options.linkedTo);
-                /**
-                 * List of major ticks mapped by postition on axis.
-                 *
-                 * @see {@link Highcharts.Tick}
-                 *
-                 * @name Highcharts.Axis#ticks
-                 * @type {Highcharts.Dictionary<Highcharts.Tick>}
-                 */
-                axis.ticks = {};
-                axis.labelEdge = [];
-                /**
-                 * List of minor ticks mapped by position on the axis.
-                 *
-                 * @see {@link Highcharts.Tick}
-                 *
-                 * @name Highcharts.Axis#minorTicks
-                 * @type {Highcharts.Dictionary<Highcharts.Tick>}
-                 */
-                axis.minorTicks = {};
-                // List of plotLines/Bands
-                axis.plotLinesAndBands = [];
-                // Alternate bands
-                axis.alternateBands = {};
-                // Axis metrics
-                axis.len = 0;
-                axis.minRange = axis.userMinRange = options.minRange || options.maxZoom;
-                axis.range = options.range;
-                axis.offset = options.offset || 0;
-                /**
-                 * The maximum value of the axis. In a logarithmic axis, this is the
-                 * logarithm of the real value, and the real value can be obtained from
-                 * {@link Axis#getExtremes}.
-                 *
-                 * @name Highcharts.Axis#max
-                 * @type {number|null}
-                 */
-                axis.max = null;
-                /**
-                 * The minimum value of the axis. In a logarithmic axis, this is the
-                 * logarithm of the real value, and the real value can be obtained from
-                 * {@link Axis#getExtremes}.
-                 *
-                 * @name Highcharts.Axis#min
-                 * @type {number|null}
-                 */
-                axis.min = null;
-                /**
-                 * The processed crosshair options.
-                 *
-                 * @name Highcharts.Axis#crosshair
-                 * @type {boolean|Highcharts.AxisCrosshairOptions}
-                 */
-                axis.crosshair = pick(options.crosshair, splat(chart.options.tooltip.crosshairs)[isXAxis ? 0 : 1], false);
-                var events = axis.options.events;
-                // Register. Don't add it again on Axis.update().
-                if (chart.axes.indexOf(axis) === -1) { //
-                    if (isXAxis) { // #2713
-                        chart.axes.splice(chart.xAxis.length, 0, axis);
-                    }
-                    else {
-                        chart.axes.push(axis);
-                    }
-                    chart[axis.coll].push(axis);
-                }
-                /**
-                 * All series associated to the axis.
-                 *
-                 * @name Highcharts.Axis#series
-                 * @type {Array<Highcharts.Series>}
-                 */
-                axis.series = axis.series || []; // populated by Series
-                // Reversed axis
-                if (chart.inverted &&
-                    !axis.isZAxis &&
-                    isXAxis &&
-                    typeof axis.reversed === 'undefined') {
-                    axis.reversed = true;
-                }
-                axis.labelRotation = axis.options.labels.rotation;
-                // register event listeners
-                objectEach(events, function (event, eventType) {
-                    if (isFunction(event)) {
-                        addEvent(axis, eventType, event);
-                    }
-                });
-                fireEvent(this, 'afterInit');
-            };
-            /**
-             * Merge and set options.
-             *
-             * @private
-             * @function Highcharts.Axis#setOptions
-             *
-             * @param {Highcharts.AxisOptions} userOptions
-             * Axis options.
-             *
-             * @fires Highcharts.Axis#event:afterSetOptions
-             */
-            Axis.prototype.setOptions = function (userOptions) {
-                this.options = merge(Axis.defaultOptions, (this.coll === 'yAxis') && Axis.defaultYAxisOptions, [
-                    Axis.defaultTopAxisOptions,
-                    Axis.defaultRightAxisOptions,
-                    Axis.defaultBottomAxisOptions,
-                    Axis.defaultLeftAxisOptions
-                ][this.side], merge(
-                // if set in setOptions (#1053):
-                defaultOptions[this.coll], userOptions));
-                fireEvent(this, 'afterSetOptions', { userOptions: userOptions });
-            };
-            /**
-             * The default label formatter. The context is a special config object for
-             * the label. In apps, use the
-             * [labels.formatter](https://api.highcharts.com/highcharts/xAxis.labels.formatter)
-             * instead, except when a modification is needed.
-             *
-             * @function Highcharts.Axis#defaultLabelFormatter
-             *
-             * @param {Highcharts.AxisLabelsFormatterContextObject<number>|Highcharts.AxisLabelsFormatterContextObject<string>} this
-             * Formatter context of axis label.
-             *
-             * @return {string}
-             * The formatted label content.
-             */
-            Axis.prototype.defaultLabelFormatter = function () {
-                var axis = this.axis,
-                    value = isNumber(this.value) ? this.value : NaN,
-                    time = axis.chart.time,
-                    categories = axis.categories,
-                    dateTimeLabelFormat = this.dateTimeLabelFormat,
-                    lang = defaultOptions.lang,
-                    numericSymbols = lang.numericSymbols,
-                    numSymMagnitude = lang.numericSymbolMagnitude || 1000,
-                    i = numericSymbols && numericSymbols.length,
-                    multi,
-                    ret,
-                    formatOption = axis.options.labels.format, 
-                    // make sure the same symbol is added for all labels on a linear
-                    // axis
-                    numericSymbolDetector = axis.logarithmic ?
-                        Math.abs(value) :
-                        axis.tickInterval;
-                var chart = this.chart;
-                var numberFormatter = chart.numberFormatter;
-                if (formatOption) {
-                    ret = format(formatOption, this, chart);
-                }
-                else if (categories) {
-                    ret = "" + this.value;
-                }
-                else if (dateTimeLabelFormat) { // datetime axis
-                    ret = time.dateFormat(dateTimeLabelFormat, value);
-                }
-                else if (i && numericSymbolDetector >= 1000) {
-                    // Decide whether we should add a numeric symbol like k (thousands)
-                    // or M (millions). If we are to enable this in tooltip or other
-                    // places as well, we can move this logic to the numberFormatter and
-                    // enable it by a parameter.
-                    while (i-- && typeof ret === 'undefined') {
-                        multi = Math.pow(numSymMagnitude, i + 1);
-                        if (
-                        // Only accept a numeric symbol when the distance is more
-                        // than a full unit. So for example if the symbol is k, we
-                        // don't accept numbers like 0.5k.
-                        numericSymbolDetector >= multi &&
-                            // Accept one decimal before the symbol. Accepts 0.5k but
-                            // not 0.25k. How does this work with the previous?
-                            (value * 10) % multi === 0 &&
-                            numericSymbols[i] !== null &&
-                            value !== 0) { // #5480
-                            ret = numberFormatter(value / multi, -1) + numericSymbols[i];
-                        }
-                    }
-                }
-                if (typeof ret === 'undefined') {
-                    if (Math.abs(value) >= 10000) { // add thousands separators
-                        ret = numberFormatter(value, -1);
-                    }
-                    else { // small numbers
-                        ret = numberFormatter(value, -1, void 0, ''); // #2466
-                    }
-                }
-                return ret;
-            };
-            /**
-             * Get the minimum and maximum for the series of each axis. The function
-             * analyzes the axis series and updates `this.dataMin` and `this.dataMax`.
-             *
-             * @private
-             * @function Highcharts.Axis#getSeriesExtremes
-             *
-             * @fires Highcharts.Axis#event:afterGetSeriesExtremes
-             * @fires Highcharts.Axis#event:getSeriesExtremes
-             */
-            Axis.prototype.getSeriesExtremes = function () {
-                var axis = this,
-                    chart = axis.chart,
-                    xExtremes;
-                fireEvent(this, 'getSeriesExtremes', null, function () {
-                    axis.hasVisibleSeries = false;
-                    // Reset properties in case we're redrawing (#3353)
-                    axis.dataMin = axis.dataMax = axis.threshold = null;
-                    axis.softThreshold = !axis.isXAxis;
-                    if (axis.stacking) {
-                        axis.stacking.buildStacks();
-                    }
-                    // loop through this axis' series
-                    axis.series.forEach(function (series) {
-                        if (series.visible ||
-                            !chart.options.chart.ignoreHiddenSeries) {
-                            var seriesOptions = series.options,
-                                xData,
-                                threshold = seriesOptions.threshold,
-                                seriesDataMin,
-                                seriesDataMax;
-                            axis.hasVisibleSeries = true;
-                            // Validate threshold in logarithmic axes
-                            if (axis.positiveValuesOnly && threshold <= 0) {
-                                threshold = null;
-                            }
-                            // Get dataMin and dataMax for X axes
-                            if (axis.isXAxis) {
-                                xData = series.xData;
-                                if (xData.length) {
-                                    var isPositive = function (number) { return number > 0; };
-                                    xData = axis.logarithmic ?
-                                        xData.filter(axis.validatePositiveValue) :
-                                        xData;
-                                    xExtremes = series.getXExtremes(xData);
-                                    // If xData contains values which is not numbers,
-                                    // then filter them out. To prevent performance hit,
-                                    // we only do this after we have already found
-                                    // seriesDataMin because in most cases all data is
-                                    // valid. #5234.
-                                    seriesDataMin = xExtremes.min;
-                                    seriesDataMax = xExtremes.max;
-                                    if (!isNumber(seriesDataMin) &&
-                                        // #5010:
-                                        !(seriesDataMin instanceof Date)) {
-                                        xData = xData.filter(isNumber);
-                                        xExtremes = series.getXExtremes(xData);
-                                        // Do it again with valid data
-                                        seriesDataMin = xExtremes.min;
-                                        seriesDataMax = xExtremes.max;
-                                    }
-                                    if (xData.length) {
-                                        axis.dataMin = Math.min(pick(axis.dataMin, seriesDataMin), seriesDataMin);
-                                        axis.dataMax = Math.max(pick(axis.dataMax, seriesDataMax), seriesDataMax);
-                                    }
-                                }
-                                // Get dataMin and dataMax for Y axes, as well as handle
-                                // stacking and processed data
-                            }
-                            else {
-                                // Get this particular series extremes
-                                var dataExtremes = series.applyExtremes();
-                                // Get the dataMin and dataMax so far. If percentage is
-                                // used, the min and max are always 0 and 100. If
-                                // seriesDataMin and seriesDataMax is null, then series
-                                // doesn't have active y data, we continue with nulls
-                                if (isNumber(dataExtremes.dataMin)) {
-                                    seriesDataMin = dataExtremes.dataMin;
-                                    axis.dataMin = Math.min(pick(axis.dataMin, seriesDataMin), seriesDataMin);
-                                }
-                                if (isNumber(dataExtremes.dataMax)) {
-                                    seriesDataMax = dataExtremes.dataMax;
-                                    axis.dataMax = Math.max(pick(axis.dataMax, seriesDataMax), seriesDataMax);
-                                }
-                                // Adjust to threshold
-                                if (defined(threshold)) {
-                                    axis.threshold = threshold;
-                                }
-                                // If any series has a hard threshold, it takes
-                                // precedence
-                                if (!seriesOptions.softThreshold ||
-                                    axis.positiveValuesOnly) {
-                                    axis.softThreshold = false;
-                                }
-                            }
-                        }
-                    });
-                });
-                fireEvent(this, 'afterGetSeriesExtremes');
-            };
-            /**
-             * Translate from axis value to pixel position on the chart, or back. Use
-             * the `toPixels` and `toValue` functions in applications.
-             *
-             * @private
-             * @function Highcharts.Axis#translate
-             *
-             * @param {number} val
-             * TO-DO: parameter description
-             *
-             * @param {boolean|null} [backwards]
-             * TO-DO: parameter description
-             *
-             * @param {boolean|null} [cvsCoord]
-             * TO-DO: parameter description
-             *
-             * @param {boolean|null} [old]
-             * TO-DO: parameter description
-             *
-             * @param {boolean} [handleLog]
-             * TO-DO: parameter description
-             *
-             * @param {number} [pointPlacement]
-             * TO-DO: parameter description
-             *
-             * @return {number|undefined}
-             */
-            Axis.prototype.translate = function (val, backwards, cvsCoord, old, handleLog, pointPlacement) {
-                var axis = this.linkedParent || this, // #1417
-                    sign = 1,
-                    cvsOffset = 0,
-                    localA = old ? axis.oldTransA : axis.transA,
-                    localMin = old ? axis.oldMin : axis.min,
-                    returnValue = 0,
-                    minPixelPadding = axis.minPixelPadding,
-                    doPostTranslate = (axis.isOrdinal ||
-                        axis.brokenAxis && axis.brokenAxis.hasBreaks ||
-                        (axis.logarithmic && handleLog)) && axis.lin2val;
-                if (!localA) {
-                    localA = axis.transA;
-                }
-                // In vertical axes, the canvas coordinates start from 0 at the top like
-                // in SVG.
-                if (cvsCoord) {
-                    sign *= -1; // canvas coordinates inverts the value
-                    cvsOffset = axis.len;
-                }
-                // Handle reversed axis
-                if (axis.reversed) {
-                    sign *= -1;
-                    cvsOffset -= sign * (axis.sector || axis.len);
-                }
-                // From pixels to value
-                if (backwards) { // reverse translation
-                    val = val * sign + cvsOffset;
-                    val -= minPixelPadding;
-                    // from chart pixel to value:
-                    returnValue = val / localA + localMin;
-                    if (doPostTranslate) { // log and ordinal axes
-                        returnValue = axis.lin2val(returnValue);
-                    }
-                    // From value to pixels
-                }
-                else {
-                    if (doPostTranslate) { // log and ordinal axes
-                        val = axis.val2lin(val);
-                    }
-                    returnValue = isNumber(localMin) ?
-                        (sign * (val - localMin) * localA +
-                            cvsOffset +
-                            (sign * minPixelPadding) +
-                            (isNumber(pointPlacement) ?
-                                localA * pointPlacement :
-                                0)) :
-                        void 0;
-                }
-                return returnValue;
-            };
-            /**
-             * Translate a value in terms of axis units into pixels within the chart.
-             *
-             * @function Highcharts.Axis#toPixels
-             *
-             * @param {number} value
-             * A value in terms of axis units.
-             *
-             * @param {boolean} paneCoordinates
-             * Whether to return the pixel coordinate relative to the chart or just the
-             * axis/pane itself.
-             *
-             * @return {number}
-             * Pixel position of the value on the chart or axis.
-             */
-            Axis.prototype.toPixels = function (value, paneCoordinates) {
-                return this.translate(value, false, !this.horiz, null, true) +
-                    (paneCoordinates ? 0 : this.pos);
-            };
-            /**
-             * Translate a pixel position along the axis to a value in terms of axis
-             * units.
-             *
-             * @function Highcharts.Axis#toValue
-             *
-             * @param {number} pixel
-             * The pixel value coordinate.
-             *
-             * @param {boolean} [paneCoordinates=false]
-             * Whether the input pixel is relative to the chart or just the axis/pane
-             * itself.
-             *
-             * @return {number}
-             * The axis value.
-             */
-            Axis.prototype.toValue = function (pixel, paneCoordinates) {
-                return this.translate(pixel - (paneCoordinates ? 0 : this.pos), true, !this.horiz, null, true);
-            };
-            /**
-             * Create the path for a plot line that goes from the given value on
-             * this axis, across the plot to the opposite side. Also used internally for
-             * grid lines and crosshairs.
-             *
-             * @function Highcharts.Axis#getPlotLinePath
-             *
-             * @param {Highcharts.AxisPlotLinePathOptionsObject} options
-             * Options for the path.
-             *
-             * @return {Highcharts.SVGPathArray|null}
-             * The SVG path definition for the plot line.
-             */
-            Axis.prototype.getPlotLinePath = function (options) {
-                var axis = this,
-                    chart = axis.chart,
-                    axisLeft = axis.left,
-                    axisTop = axis.top,
-                    old = options.old,
-                    value = options.value,
-                    translatedValue = options.translatedValue,
-                    lineWidth = options.lineWidth,
-                    force = options.force,
-                    x1,
-                    y1,
-                    x2,
-                    y2,
-                    cHeight = (old && chart.oldChartHeight) || chart.chartHeight,
-                    cWidth = (old && chart.oldChartWidth) || chart.chartWidth,
-                    skip,
-                    transB = axis.transB,
-                    evt;
-                // eslint-disable-next-line valid-jsdoc
-                /**
-                 * Check if x is between a and b. If not, either move to a/b
-                 * or skip, depending on the force parameter.
-                 * @private
-                 */
-                function between(x, a, b) {
-                    if (force !== 'pass' && x < a || x > b) {
-                        if (force) {
-                            x = clamp(x, a, b);
-                        }
-                        else {
-                            skip = true;
-                        }
-                    }
-                    return x;
-                }
-                evt = {
-                    value: value,
-                    lineWidth: lineWidth,
-                    old: old,
-                    force: force,
-                    acrossPanes: options.acrossPanes,
-                    translatedValue: translatedValue
-                };
-                fireEvent(this, 'getPlotLinePath', evt, function (e) {
-                    translatedValue = pick(translatedValue, axis.translate(value, null, null, old));
-                    // Keep the translated value within sane bounds, and avoid Infinity
-                    // to fail the isNumber test (#7709).
-                    translatedValue = clamp(translatedValue, -1e5, 1e5);
-                    x1 = x2 = Math.round(translatedValue + transB);
-                    y1 = y2 = Math.round(cHeight - translatedValue - transB);
-                    if (!isNumber(translatedValue)) { // no min or max
-                        skip = true;
-                        force = false; // #7175, don't force it when path is invalid
-                    }
-                    else if (axis.horiz) {
-                        y1 = axisTop;
-                        y2 = cHeight - axis.bottom;
-                        x1 = x2 = between(x1, axisLeft, axisLeft + axis.width);
-                    }
-                    else {
-                        x1 = axisLeft;
-                        x2 = cWidth - axis.right;
-                        y1 = y2 = between(y1, axisTop, axisTop + axis.height);
-                    }
-                    e.path = skip && !force ?
-                        null :
-                        chart.renderer.crispLine([['M', x1, y1], ['L', x2, y2]], lineWidth || 1);
-                });
-                return evt.path;
-            };
-            /**
-             * Internal function to et the tick positions of a linear axis to round
-             * values like whole tens or every five.
-             *
-             * @function Highcharts.Axis#getLinearTickPositions
-             *
-             * @param {number} tickInterval
-             * The normalized tick interval.
-             *
-             * @param {number} min
-             * Axis minimum.
-             *
-             * @param {number} max
-             * Axis maximum.
-             *
-             * @return {Array<number>}
-             * An array of axis values where ticks should be placed.
-             */
-            Axis.prototype.getLinearTickPositions = function (tickInterval, min, max) {
-                var pos,
-                    lastPos,
-                    roundedMin = correctFloat(Math.floor(min / tickInterval) * tickInterval),
-                    roundedMax = correctFloat(Math.ceil(max / tickInterval) * tickInterval),
-                    tickPositions = [],
-                    precision;
-                // When the precision is higher than what we filter out in
-                // correctFloat, skip it (#6183).
-                if (correctFloat(roundedMin + tickInterval) === roundedMin) {
-                    precision = 20;
-                }
-                // For single points, add a tick regardless of the relative position
-                // (#2662, #6274)
-                if (this.single) {
-                    return [min];
-                }
-                // Populate the intermediate values
-                pos = roundedMin;
-                while (pos <= roundedMax) {
-                    // Place the tick on the rounded value
-                    tickPositions.push(pos);
-                    // Always add the raw tickInterval, not the corrected one.
-                    pos = correctFloat(pos + tickInterval, precision);
-                    // If the interval is not big enough in the current min - max range
-                    // to actually increase the loop variable, we need to break out to
-                    // prevent endless loop. Issue #619
-                    if (pos === lastPos) {
-                        break;
-                    }
-                    // Record the last value
-                    lastPos = pos;
-                }
-                return tickPositions;
-            };
-            /**
-             * Resolve the new minorTicks/minorTickInterval options into the legacy
-             * loosely typed minorTickInterval option.
-             *
-             * @function Highcharts.Axis#getMinorTickInterval
-             *
-             * @return {number|"auto"|null}
-             */
-            Axis.prototype.getMinorTickInterval = function () {
-                var options = this.options;
-                if (options.minorTicks === true) {
-                    return pick(options.minorTickInterval, 'auto');
-                }
-                if (options.minorTicks === false) {
-                    return null;
-                }
-                return options.minorTickInterval;
-            };
-            /**
-             * Internal function to return the minor tick positions. For logarithmic
-             * axes, the same logic as for major ticks is reused.
-             *
-             * @function Highcharts.Axis#getMinorTickPositions
-             *
-             * @return {Array<number>}
-             * An array of axis values where ticks should be placed.
-             */
-            Axis.prototype.getMinorTickPositions = function () {
-                var axis = this,
-                    options = axis.options,
-                    tickPositions = axis.tickPositions,
-                    minorTickInterval = axis.minorTickInterval,
-                    minorTickPositions = [],
-                    pos,
-                    pointRangePadding = axis.pointRangePadding || 0,
-                    min = axis.min - pointRangePadding, // #1498
-                    max = axis.max + pointRangePadding, // #1498
-                    range = max - min;
-                // If minor ticks get too dense, they are hard to read, and may cause
-                // long running script. So we don't draw them.
-                if (range && range / minorTickInterval < axis.len / 3) { // #3875
-                    var logarithmic_1 = axis.logarithmic;
-                    if (logarithmic_1) {
-                        // For each interval in the major ticks, compute the minor ticks
-                        // separately.
-                        this.paddedTicks.forEach(function (_pos, i, paddedTicks) {
-                            if (i) {
-                                minorTickPositions.push.apply(minorTickPositions, logarithmic_1.getLogTickPositions(minorTickInterval, paddedTicks[i - 1], paddedTicks[i], true));
-                            }
-                        });
-                    }
-                    else if (axis.dateTime &&
-                        this.getMinorTickInterval() === 'auto') { // #1314
-                        minorTickPositions = minorTickPositions.concat(axis.getTimeTicks(axis.dateTime.normalizeTimeTickInterval(minorTickInterval), min, max, options.startOfWeek));
-                    }
-                    else {
-                        for (pos = min + (tickPositions[0] - min) % minorTickInterval; pos <= max; pos += minorTickInterval) {
-                            // Very, very, tight grid lines (#5771)
-                            if (pos === minorTickPositions[0]) {
-                                break;
-                            }
-                            minorTickPositions.push(pos);
-                        }
-                    }
-                }
-                if (minorTickPositions.length !== 0) {
-                    axis.trimTicks(minorTickPositions); // #3652 #3743 #1498 #6330
-                }
-                return minorTickPositions;
-            };
-            /**
-             * Adjust the min and max for the minimum range. Keep in mind that the
-             * series data is not yet processed, so we don't have information on data
-             * cropping and grouping, or updated `axis.pointRange` or
-             * `series.pointRange`. The data can't be processed until we have finally
-             * established min and max.
-             *
-             * @private
-             * @function Highcharts.Axis#adjustForMinRange
-             */
-            Axis.prototype.adjustForMinRange = function () {
-                var axis = this,
-                    options = axis.options,
-                    min = axis.min,
-                    max = axis.max,
-                    log = axis.logarithmic,
-                    zoomOffset,
-                    spaceAvailable,
-                    closestDataRange,
-                    i,
-                    distance,
-                    xData,
-                    loopLength,
-                    minArgs,
-                    maxArgs,
-                    minRange;
-                // Set the automatic minimum range based on the closest point distance
-                if (axis.isXAxis &&
-                    typeof axis.minRange === 'undefined' &&
-                    !log) {
-                    if (defined(options.min) || defined(options.max)) {
-                        axis.minRange = null; // don't do this again
-                    }
-                    else {
-                        // Find the closest distance between raw data points, as opposed
-                        // to closestPointRange that applies to processed points
-                        // (cropped and grouped)
-                        axis.series.forEach(function (series) {
-                            xData = series.xData;
-                            loopLength = series.xIncrement ? 1 : xData.length - 1;
-                            for (i = loopLength; i > 0; i--) {
-                                distance = xData[i] - xData[i - 1];
-                                if (typeof closestDataRange === 'undefined' ||
-                                    distance < closestDataRange) {
-                                    closestDataRange = distance;
-                                }
-                            }
-                        });
-                        axis.minRange = Math.min(closestDataRange * 5, axis.dataMax - axis.dataMin);
-                    }
-                }
-                // if minRange is exceeded, adjust
-                if (max - min < axis.minRange) {
-                    spaceAvailable =
-                        axis.dataMax - axis.dataMin >=
-                            axis.minRange;
-                    minRange = axis.minRange;
-                    zoomOffset = (minRange - max + min) / 2;
-                    // if min and max options have been set, don't go beyond it
-                    minArgs = [
-                        min - zoomOffset,
-                        pick(options.min, min - zoomOffset)
-                    ];
-                    // If space is available, stay within the data range
-                    if (spaceAvailable) {
-                        minArgs[2] = axis.logarithmic ?
-                            axis.logarithmic.log2lin(axis.dataMin) :
-                            axis.dataMin;
-                    }
-                    min = arrayMax(minArgs);
-                    maxArgs = [
-                        min + minRange,
-                        pick(options.max, min + minRange)
-                    ];
-                    // If space is availabe, stay within the data range
-                    if (spaceAvailable) {
-                        maxArgs[2] = log ?
-                            log.log2lin(axis.dataMax) :
-                            axis.dataMax;
-                    }
-                    max = arrayMin(maxArgs);
-                    // now if the max is adjusted, adjust the min back
-                    if (max - min < minRange) {
-                        minArgs[0] = max - minRange;
-                        minArgs[1] = pick(options.min, max - minRange);
-                        min = arrayMax(minArgs);
-                    }
-                }
-                // Record modified extremes
-                axis.min = min;
-                axis.max = max;
-            };
-            // eslint-disable-next-line valid-jsdoc
-            /**
-             * Find the closestPointRange across all series.
-             *
-             * @private
-             * @function Highcharts.Axis#getClosest
-             */
-            Axis.prototype.getClosest = function () {
-                var ret;
-                if (this.categories) {
-                    ret = 1;
-                }
-                else {
-                    this.series.forEach(function (series) {
-                        var seriesClosest = series.closestPointRange,
-                            visible = series.visible ||
-                                !series.chart.options.chart.ignoreHiddenSeries;
-                        if (!series.noSharedTooltip &&
-                            defined(seriesClosest) &&
-                            visible) {
-                            ret = defined(ret) ?
-                                Math.min(ret, seriesClosest) :
-                                seriesClosest;
-                        }
-                    });
-                }
-                return ret;
-            };
-            /**
-             * When a point name is given and no x, search for the name in the existing
-             * categories, or if categories aren't provided, search names or create a
-             * new category (#2522).
-             * @private
-             * @function Highcharts.Axis#nameToX
-             *
-             * @param {Highcharts.Point} point
-             * The point to inspect.
-             *
-             * @return {number}
-             * The X value that the point is given.
-             */
-            Axis.prototype.nameToX = function (point) {
-                var explicitCategories = isArray(this.categories),
-                    names = explicitCategories ? this.categories : this.names,
-                    nameX = point.options.x,
-                    x;
-                point.series.requireSorting = false;
-                if (!defined(nameX)) {
-                    nameX = this.options.uniqueNames === false ?
-                        point.series.autoIncrement() :
-                        (explicitCategories ?
-                            names.indexOf(point.name) :
-                            pick(names.keys[point.name], -1));
-                }
-                if (nameX === -1) { // Not found in currenct categories
-                    if (!explicitCategories) {
-                        x = names.length;
-                    }
-                }
-                else {
-                    x = nameX;
-                }
-                // Write the last point's name to the names array
-                if (typeof x !== 'undefined') {
-                    this.names[x] = point.name;
-                    // Backwards mapping is much faster than array searching (#7725)
-                    this.names.keys[point.name] = x;
-                }
-                return x;
-            };
-            /**
-             * When changes have been done to series data, update the axis.names.
-             *
-             * @private
-             * @function Highcharts.Axis#updateNames
-             */
-            Axis.prototype.updateNames = function () {
-                var axis = this,
-                    names = this.names,
-                    i = names.length;
-                if (i > 0) {
-                    Object.keys(names.keys).forEach(function (key) {
-                        delete (names.keys)[key];
-                    });
-                    names.length = 0;
-                    this.minRange = this.userMinRange; // Reset
-                    (this.series || []).forEach(function (series) {
-                        // Reset incrementer (#5928)
-                        series.xIncrement = null;
-                        // When adding a series, points are not yet generated
-                        if (!series.points || series.isDirtyData) {
-                            // When we're updating the series with data that is longer
-                            // than it was, and cropThreshold is passed, we need to make
-                            // sure that the axis.max is increased _before_ running the
-                            // premature processData. Otherwise this early iteration of
-                            // processData will crop the points to axis.max, and the
-                            // names array will be too short (#5857).
-                            axis.max = Math.max(axis.max, series.xData.length - 1);
-                            series.processData();
-                            series.generatePoints();
-                        }
-                        series.data.forEach(function (point, i) {
-                            var x;
-                            if (point &&
-                                point.options &&
-                                typeof point.name !== 'undefined' // #9562
-                            ) {
-                                x = axis.nameToX(point);
-                                if (typeof x !== 'undefined' && x !== point.x) {
-                                    point.x = x;
-                                    series.xData[i] = x;
-                                }
-                            }
-                        });
-                    });
-                }
-            };
-            /**
-             * Update translation information.
-             *
-             * @private
-             * @function Highcharts.Axis#setAxisTranslation
-             *
-             * @param {boolean} [saveOld]
-             * TO-DO: parameter description
-             *
-             * @fires Highcharts.Axis#event:afterSetAxisTranslation
-             */
-            Axis.prototype.setAxisTranslation = function (saveOld) {
-                var axis = this,
-                    range = axis.max - axis.min,
-                    pointRange = axis.axisPointRange || 0,
-                    closestPointRange,
-                    minPointOffset = 0,
-                    pointRangePadding = 0,
-                    linkedParent = axis.linkedParent,
-                    ordinalCorrection,
-                    hasCategories = !!axis.categories,
-                    transA = axis.transA,
-                    isXAxis = axis.isXAxis;
-                // Adjust translation for padding. Y axis with categories need to go
-                // through the same (#1784).
-                if (isXAxis || hasCategories || pointRange) {
-                    // Get the closest points
-                    closestPointRange = axis.getClosest();
-                    if (linkedParent) {
-                        minPointOffset = linkedParent.minPointOffset;
-                        pointRangePadding = linkedParent.pointRangePadding;
-                    }
-                    else {
-                        axis.series.forEach(function (series) {
-                            var seriesPointRange = hasCategories ?
-                                    1 :
-                                    (isXAxis ?
-                                        pick(series.options.pointRange,
-                                closestPointRange, 0) :
-                                        (axis.axisPointRange || 0)), // #2806
-                                pointPlacement = series.options.pointPlacement;
-                            pointRange = Math.max(pointRange, seriesPointRange);
-                            if (!axis.single || hasCategories) {
-                                // TODO: series should internally set x- and y-
-                                // pointPlacement to simplify this logic.
-                                var isPointPlacementAxis = series.is('xrange') ? !isXAxis : isXAxis;
-                                // minPointOffset is the value padding to the left of
-                                // the axis in order to make room for points with a
-                                // pointRange, typically columns. When the
-                                // pointPlacement option is 'between' or 'on', this
-                                // padding does not apply.
-                                minPointOffset = Math.max(minPointOffset, isPointPlacementAxis && isString(pointPlacement) ?
-                                    0 :
-                                    seriesPointRange / 2);
-                                // Determine the total padding needed to the length of
-                                // the axis to make room for the pointRange. If the
-                                // series' pointPlacement is 'on', no padding is added.
-                                pointRangePadding = Math.max(pointRangePadding, isPointPlacementAxis && pointPlacement === 'on' ?
-                                    0 :
-                                    seriesPointRange);
-                            }
-                        });
-                    }
-                    // Record minPointOffset and pointRangePadding
-                    ordinalCorrection = axis.ordinal && axis.ordinal.slope && closestPointRange ?
-                        axis.ordinal.slope / closestPointRange :
-                        1; // #988, #1853
-                    axis.minPointOffset = minPointOffset =
-                        minPointOffset * ordinalCorrection;
-                    axis.pointRangePadding =
-                        pointRangePadding = pointRangePadding * ordinalCorrection;
-                    // pointRange means the width reserved for each point, like in a
-                    // column chart
-                    axis.pointRange = Math.min(pointRange, axis.single && hasCategories ? 1 : range);
-                    // closestPointRange means the closest distance between points. In
-                    // columns it is mostly equal to pointRange, but in lines pointRange
-                    // is 0 while closestPointRange is some other value
-                    if (isXAxis) {
-                        axis.closestPointRange = closestPointRange;
-                    }
-                }
-                // Secondary values
-                if (saveOld) {
-                    axis.oldTransA = transA;
-                }
-                axis.translationSlope = axis.transA = transA =
-                    axis.staticScale ||
-                        axis.len / ((range + pointRangePadding) || 1);
-                // Translation addend
-                axis.transB = axis.horiz ? axis.left : axis.bottom;
-                axis.minPixelPadding = transA * minPointOffset;
-                fireEvent(this, 'afterSetAxisTranslation');
-            };
-            /**
-             * @private
-             * @function Highcharts.Axis#minFromRange
-             *
-             * @return {number}
-             */
-            Axis.prototype.minFromRange = function () {
-                var axis = this;
-                return axis.max - axis.range;
-            };
-            /**
-             * Set the tick positions to round values and optionally extend the extremes
-             * to the nearest tick.
-             *
-             * @private
-             * @function Highcharts.Axis#setTickInterval
-             *
-             * @param {boolean} secondPass
-             * TO-DO: parameter description
-             *
-             * @fires Highcharts.Axis#event:foundExtremes
-             */
-            Axis.prototype.setTickInterval = function (secondPass) {
-                var axis = this,
-                    chart = axis.chart,
-                    log = axis.logarithmic,
-                    options = axis.options,
-                    isXAxis = axis.isXAxis,
-                    isLinked = axis.isLinked,
-                    maxPadding = options.maxPadding,
-                    minPadding = options.minPadding,
-                    length,
-                    linkedParentExtremes,
-                    tickIntervalOption = options.tickInterval,
-                    minTickInterval,
-                    tickPixelIntervalOption = options.tickPixelInterval,
-                    categories = axis.categories,
-                    threshold = isNumber(axis.threshold) ? axis.threshold : null,
-                    softThreshold = axis.softThreshold,
-                    thresholdMin,
-                    thresholdMax,
-                    hardMin,
-                    hardMax;
-                if (!axis.dateTime && !categories && !isLinked) {
-                    this.getTickAmount();
-                }
-                // Min or max set either by zooming/setExtremes or initial options
-                hardMin = pick(axis.userMin, options.min);
-                hardMax = pick(axis.userMax, options.max);
-                // Linked axis gets the extremes from the parent axis
-                if (isLinked) {
-                    axis.linkedParent = chart[axis.coll][options.linkedTo];
-                    linkedParentExtremes = axis.linkedParent.getExtremes();
-                    axis.min = pick(linkedParentExtremes.min, linkedParentExtremes.dataMin);
-                    axis.max = pick(linkedParentExtremes.max, linkedParentExtremes.dataMax);
-                    if (options.type !== axis.linkedParent.options.type) {
-                        // Can't link axes of different type
-                        error(11, 1, chart);
-                    }
-                    // Initial min and max from the extreme data values
-                }
-                else {
-                    // Adjust to hard threshold
-                    if (softThreshold && defined(threshold)) {
-                        if (axis.dataMin >= threshold) {
-                            thresholdMin = threshold;
-                            minPadding = 0;
-                        }
-                        else if (axis.dataMax <= threshold) {
-                            thresholdMax = threshold;
-                            maxPadding = 0;
-                        }
-                    }
-                    axis.min = pick(hardMin, thresholdMin, axis.dataMin);
-                    axis.max = pick(hardMax, thresholdMax, axis.dataMax);
-                }
-                if (log) {
-                    if (axis.positiveValuesOnly &&
-                        !secondPass &&
-                        Math.min(axis.min, pick(axis.dataMin, axis.min)) <= 0) { // #978
-                        // Can't plot negative values on log axis
-                        error(10, 1, chart);
-                    }
-                    // The correctFloat cures #934, float errors on full tens. But it
-                    // was too aggressive for #4360 because of conversion back to lin,
-                    // therefore use precision 15.
-                    axis.min = correctFloat(log.log2lin(axis.min), 16);
-                    axis.max = correctFloat(log.log2lin(axis.max), 16);
-                }
-                // handle zoomed range
-                if (axis.range && defined(axis.max)) {
-                    // #618, #6773:
-                    axis.userMin = axis.min = hardMin =
-                        Math.max(axis.dataMin, axis.minFromRange());
-                    axis.userMax = hardMax = axis.max;
-                    axis.range = null; // don't use it when running setExtremes
-                }
-                // Hook for Highstock Scroller. Consider combining with beforePadding.
-                fireEvent(axis, 'foundExtremes');
-                // Hook for adjusting this.min and this.max. Used by bubble series.
-                if (axis.beforePadding) {
-                    axis.beforePadding();
-                }
-                // adjust min and max for the minimum range
-                axis.adjustForMinRange();
-                // Pad the values to get clear of the chart's edges. To avoid
-                // tickInterval taking the padding into account, we do this after
-                // computing tick interval (#1337).
-                if (!categories &&
-                    !axis.axisPointRange &&
-                    !(axis.stacking && axis.stacking.usePercentage) &&
-                    !isLinked &&
-                    defined(axis.min) &&
-                    defined(axis.max)) {
-                    length = axis.max - axis.min;
-                    if (length) {
-                        if (!defined(hardMin) && minPadding) {
-                            axis.min -= length * minPadding;
-                        }
-                        if (!defined(hardMax) && maxPadding) {
-                            axis.max += length * maxPadding;
-                        }
-                    }
-                }
-                // Handle options for floor, ceiling, softMin and softMax (#6359)
-                if (!isNumber(axis.userMin)) {
-                    if (isNumber(options.softMin) && options.softMin < axis.min) {
-                        axis.min = hardMin = options.softMin; // #6894
-                    }
-                    if (isNumber(options.floor)) {
-                        axis.min = Math.max(axis.min, options.floor);
-                    }
-                }
-                if (!isNumber(axis.userMax)) {
-                    if (isNumber(options.softMax) && options.softMax > axis.max) {
-                        axis.max = hardMax = options.softMax; // #6894
-                    }
-                    if (isNumber(options.ceiling)) {
-                        axis.max = Math.min(axis.max, options.ceiling);
-                    }
-                }
-                // When the threshold is soft, adjust the extreme value only if the data
-                // extreme and the padded extreme land on either side of the threshold.
-                // For example, a series of [0, 1, 2, 3] would make the yAxis add a tick
-                // for -1 because of the default minPadding and startOnTick options.
-                // This is prevented by the softThreshold option.
-                if (softThreshold && defined(axis.dataMin)) {
-                    threshold = threshold || 0;
-                    if (!defined(hardMin) &&
-                        axis.min < threshold &&
-                        axis.dataMin >= threshold) {
-                        axis.min = axis.options.minRange ?
-                            Math.min(threshold, axis.max -
-                                axis.minRange) :
-                            threshold;
-                    }
-                    else if (!defined(hardMax) &&
-                        axis.max > threshold &&
-                        axis.dataMax <= threshold) {
-                        axis.max = axis.options.minRange ?
-                            Math.max(threshold, axis.min +
-                                axis.minRange) :
-                            threshold;
-                    }
-                }
-                // get tickInterval
-                if (axis.min === axis.max ||
-                    typeof axis.min === 'undefined' ||
-                    typeof axis.max === 'undefined') {
-                    axis.tickInterval = 1;
-                }
-                else if (isLinked &&
-                    !tickIntervalOption &&
-                    tickPixelIntervalOption ===
-                        axis.linkedParent.options.tickPixelInterval) {
-                    axis.tickInterval = tickIntervalOption =
-                        axis.linkedParent.tickInterval;
-                }
-                else {
-                    axis.tickInterval = pick(tickIntervalOption, this.tickAmount ?
-                        ((axis.max - axis.min) /
-                            Math.max(this.tickAmount - 1, 1)) :
-                        void 0, 
-                    // For categoried axis, 1 is default, for linear axis use
-                    // tickPix
-                    categories ?
-                        1 :
-                        // don't let it be more than the data range
-                        (axis.max - axis.min) *
-                            tickPixelIntervalOption /
-                            Math.max(axis.len, tickPixelIntervalOption));
-                }
-                // Now we're finished detecting min and max, crop and group series data.
-                // This is in turn needed in order to find tick positions in ordinal
-                // axes.
-                if (isXAxis && !secondPass) {
-                    axis.series.forEach(function (series) {
-                        series.processData(axis.min !== axis.oldMin || axis.max !== axis.oldMax);
-                    });
-                }
-                // set the translation factor used in translate function
-                axis.setAxisTranslation(true);
-                // hook for ordinal axes and radial axes
-                fireEvent(this, 'initialAxisTranslation');
-                // In column-like charts, don't cramp in more ticks than there are
-                // points (#1943, #4184)
-                if (axis.pointRange && !tickIntervalOption) {
-                    axis.tickInterval = Math.max(axis.pointRange, axis.tickInterval);
-                }
-                // Before normalizing the tick interval, handle minimum tick interval.
-                // This applies only if tickInterval is not defined.
-                minTickInterval = pick(options.minTickInterval, 
-                // In datetime axes, don't go below the data interval, except when
-                // there are scatter-like series involved (#13369).
-                axis.dateTime &&
-                    !axis.series.some(function (s) { return s.noSharedTooltip; }) ?
-                    axis.closestPointRange : 0);
-                if (!tickIntervalOption && axis.tickInterval < minTickInterval) {
-                    axis.tickInterval = minTickInterval;
-                }
-                // for linear axes, get magnitude and normalize the interval
-                if (!axis.dateTime && !axis.logarithmic && !tickIntervalOption) {
-                    axis.tickInterval = normalizeTickInterval(axis.tickInterval, void 0, getMagnitude(axis.tickInterval), pick(options.allowDecimals, 
-                    // If the tick interval is greather than 0.5, avoid
-                    // decimals, as linear axes are often used to render
-                    // discrete values. #3363. If a tick amount is set, allow
-                    // decimals by default, as it increases the chances for a
-                    // good fit.
-                    axis.tickInterval < 0.5 || this.tickAmount !== void 0), !!this.tickAmount);
-                }
-                // Prevent ticks from getting so close that we can't draw the labels
-                if (!this.tickAmount) {
-                    axis.tickInterval = axis.unsquish();
-                }
-                this.setTickPositions();
-            };
-            /**
-             * Now we have computed the normalized tickInterval, get the tick positions.
-             *
-             * @private
-             * @function Highcharts.Axis#setTickPositions
-             *
-             * @fires Highcharts.Axis#event:afterSetTickPositions
-             */
-            Axis.prototype.setTickPositions = function () {
-                var axis = this,
-                    options = this.options,
-                    tickPositions,
-                    tickPositionsOption = options.tickPositions,
-                    minorTickIntervalOption = this.getMinorTickInterval(),
-                    tickPositioner = options.tickPositioner,
-                    hasVerticalPanning = this.hasVerticalPanning(),
-                    isColorAxis = this.coll === 'colorAxis',
-                    startOnTick = (isColorAxis || !hasVerticalPanning) && options.startOnTick,
-                    endOnTick = (isColorAxis || !hasVerticalPanning) && options.endOnTick;
-                // Set the tickmarkOffset
-                this.tickmarkOffset = (this.categories &&
-                    options.tickmarkPlacement === 'between' &&
-                    this.tickInterval === 1) ? 0.5 : 0; // #3202
-                // get minorTickInterval
-                this.minorTickInterval =
-                    minorTickIntervalOption === 'auto' &&
-                        this.tickInterval ?
-                        this.tickInterval / 5 :
-                        minorTickIntervalOption;
-                // When there is only one point, or all points have the same value on
-                // this axis, then min and max are equal and tickPositions.length is 0
-                // or 1. In this case, add some padding in order to center the point,
-                // but leave it with one tick. #1337.
-                this.single =
-                    this.min === this.max &&
-                        defined(this.min) &&
-                        !this.tickAmount &&
-                        (
-                        // Data is on integer (#6563)
-                        parseInt(this.min, 10) === this.min ||
-                            // Between integers and decimals are not allowed (#6274)
-                            options.allowDecimals !== false);
-                /**
-                 * Contains the current positions that are laid out on the axis. The
-                 * positions are numbers in terms of axis values. In a category axis
-                 * they are integers, in a datetime axis they are also integers, but
-                 * designating milliseconds.
-                 *
-                 * This property is read only - for modifying the tick positions, use
-                 * the `tickPositioner` callback or [axis.tickPositions(
-                 * https://api.highcharts.com/highcharts/xAxis.tickPositions) option
-                 * instead.
-                 *
-                 * @name Highcharts.Axis#tickPositions
-                 * @type {Highcharts.AxisTickPositionsArray|undefined}
-                 */
-                this.tickPositions =
-                    // Find the tick positions. Work on a copy (#1565)
-                    tickPositions =
-                        (tickPositionsOption && tickPositionsOption.slice());
-                if (!tickPositions) {
-                    // Too many ticks (#6405). Create a friendly warning and provide two
-                    // ticks so at least we can show the data series.
-                    if ((!axis.ordinal || !axis.ordinal.positions) &&
-                        ((this.max - this.min) /
-                            this.tickInterval >
-                            Math.max(2 * this.len, 200))) {
-                        tickPositions = [this.min, this.max];
-                        error(19, false, this.chart);
-                    }
-                    else if (axis.dateTime) {
-                        tickPositions = axis.getTimeTicks(axis.dateTime.normalizeTimeTickInterval(this.tickInterval, options.units), this.min, this.max, options.startOfWeek, axis.ordinal && axis.ordinal.positions, this.closestPointRange, true);
-                    }
-                    else if (axis.logarithmic) {
-                        tickPositions = axis.logarithmic.getLogTickPositions(this.tickInterval, this.min, this.max);
-                    }
-                    else {
-                        tickPositions = this.getLinearTickPositions(this.tickInterval, this.min, this.max);
-                    }
-                    // Too dense ticks, keep only the first and last (#4477)
-                    if (tickPositions.length > this.len) {
-                        tickPositions = [tickPositions[0], tickPositions.pop()];
-                        // Reduce doubled value (#7339)
-                        if (tickPositions[0] === tickPositions[1]) {
-                            tickPositions.length = 1;
-                        }
-                    }
-                    this.tickPositions = tickPositions;
-                    // Run the tick positioner callback, that allows modifying auto tick
-                    // positions.
-                    if (tickPositioner) {
-                        tickPositioner = tickPositioner.apply(axis, [this.min, this.max]);
-                        if (tickPositioner) {
-                            this.tickPositions = tickPositions = tickPositioner;
-                        }
-                    }
-                }
-                // Reset min/max or remove extremes based on start/end on tick
-                this.paddedTicks = tickPositions.slice(0); // Used for logarithmic minor
-                this.trimTicks(tickPositions, startOnTick, endOnTick);
-                if (!this.isLinked) {
-                    // Substract half a unit (#2619, #2846, #2515, #3390),
-                    // but not in case of multiple ticks (#6897)
-                    if (this.single &&
-                        tickPositions.length < 2 &&
-                        !this.categories &&
-                        !this.series.some(function (s) {
-                            return (s.is('heatmap') && s.options.pointPlacement === 'between');
-                        })) {
-                        this.min -= 0.5;
-                        this.max += 0.5;
-                    }
-                    if (!tickPositionsOption && !tickPositioner) {
-                        this.adjustTickAmount();
-                    }
-                }
-                fireEvent(this, 'afterSetTickPositions');
-            };
-            /**
-             * Handle startOnTick and endOnTick by either adapting to padding min/max or
-             * rounded min/max. Also handle single data points.
-             *
-             * @private
-             * @function Highcharts.Axis#trimTicks
-             *
-             * @param {Array<number>} tickPositions
-             * TO-DO: parameter description
-             *
-             * @param {boolean} [startOnTick]
-             * TO-DO: parameter description
-             *
-             * @param {boolean} [endOnTick]
-             * TO-DO: parameter description
-             */
-            Axis.prototype.trimTicks = function (tickPositions, startOnTick, endOnTick) {
-                var roundedMin = tickPositions[0],
-                    roundedMax = tickPositions[tickPositions.length - 1],
-                    minPointOffset = (!this.isOrdinal && this.minPointOffset) || 0; // (#12716)
-                    fireEvent(this, 'trimTicks');
-                if (!this.isLinked) {
-                    if (startOnTick && roundedMin !== -Infinity) { // #6502
-                        this.min = roundedMin;
-                    }
-                    else {
-                        while (this.min - minPointOffset > tickPositions[0]) {
-                            tickPositions.shift();
-                        }
-                    }
-                    if (endOnTick) {
-                        this.max = roundedMax;
-                    }
-                    else {
-                        while (this.max + minPointOffset <
-                            tickPositions[tickPositions.length - 1]) {
-                            tickPositions.pop();
-                        }
-                    }
-                    // If no tick are left, set one tick in the middle (#3195)
-                    if (tickPositions.length === 0 &&
-                        defined(roundedMin) &&
-                        !this.options.tickPositions) {
-                        tickPositions.push((roundedMax + roundedMin) / 2);
-                    }
-                }
-            };
-            /**
-             * Check if there are multiple axes in the same pane.
-             *
-             * @private
-             * @function Highcharts.Axis#alignToOthers
-             *
-             * @return {boolean|undefined}
-             * True if there are other axes.
-             */
-            Axis.prototype.alignToOthers = function () {
-                var axis = this,
-                    others = // Whether there is another axis to pair with this one
-                     {},
-                    hasOther,
-                    options = axis.options;
-                if (
-                // Only if alignTicks is true
-                this.chart.options.chart.alignTicks !== false &&
-                    options.alignTicks !== false &&
-                    // Disabled when startOnTick or endOnTick are false (#7604)
-                    options.startOnTick !== false &&
-                    options.endOnTick !== false &&
-                    // Don't try to align ticks on a log axis, they are not evenly
-                    // spaced (#6021)
-                    !axis.logarithmic) {
-                    this.chart[this.coll].forEach(function (axis) {
-                        var otherOptions = axis.options, horiz = axis.horiz, key = [
-                                horiz ? otherOptions.left : otherOptions.top,
-                                otherOptions.width,
-                                otherOptions.height,
-                                otherOptions.pane
-                            ].join(',');
-                        if (axis.series.length) { // #4442
-                            if (others[key]) {
-                                hasOther = true; // #4201
-                            }
-                            else {
-                                others[key] = 1;
-                            }
-                        }
-                    });
-                }
-                return hasOther;
-            };
-            /**
-             * Find the max ticks of either the x and y axis collection, and record it
-             * in `this.tickAmount`.
-             *
-             * @private
-             * @function Highcharts.Axis#getTickAmount
-             */
-            Axis.prototype.getTickAmount = function () {
-                var axis = this,
-                    options = this.options,
-                    tickAmount = options.tickAmount,
-                    tickPixelInterval = options.tickPixelInterval;
-                if (!defined(options.tickInterval) &&
-                    !tickAmount && this.len < tickPixelInterval &&
-                    !this.isRadial &&
-                    !axis.logarithmic &&
-                    options.startOnTick &&
-                    options.endOnTick) {
-                    tickAmount = 2;
-                }
-                if (!tickAmount && this.alignToOthers()) {
-                    // Add 1 because 4 tick intervals require 5 ticks (including first
-                    // and last)
-                    tickAmount = Math.ceil(this.len / tickPixelInterval) + 1;
-                }
-                // For tick amounts of 2 and 3, compute five ticks and remove the
-                // intermediate ones. This prevents the axis from adding ticks that are
-                // too far away from the data extremes.
-                if (tickAmount < 4) {
-                    this.finalTickAmt = tickAmount;
-                    tickAmount = 5;
-                }
-                this.tickAmount = tickAmount;
-            };
-            /**
-             * When using multiple axes, adjust the number of ticks to match the highest
-             * number of ticks in that group.
-             *
-             * @private
-             * @function Highcharts.Axis#adjustTickAmount
-             */
-            Axis.prototype.adjustTickAmount = function () {
-                var axis = this,
-                    axisOptions = axis.options,
-                    tickInterval = axis.tickInterval,
-                    tickPositions = axis.tickPositions,
-                    tickAmount = axis.tickAmount,
-                    finalTickAmt = axis.finalTickAmt,
-                    currentTickAmount = tickPositions && tickPositions.length,
-                    threshold = pick(axis.threshold,
-                    axis.softThreshold ? 0 : null),
-                    min,
-                    len,
-                    i;
-                if (axis.hasData()) {
-                    if (currentTickAmount < tickAmount) {
-                        min = axis.min;
-                        while (tickPositions.length < tickAmount) {
-                            // Extend evenly for both sides unless we're on the
-                            // threshold (#3965)
-                            if (tickPositions.length % 2 ||
-                                min === threshold) {
-                                // to the end
-                                tickPositions.push(correctFloat(tickPositions[tickPositions.length - 1] +
-                                    tickInterval));
-                            }
-                            else {
-                                // to the start
-                                tickPositions.unshift(correctFloat(tickPositions[0] - tickInterval));
-                            }
-                        }
-                        axis.transA *= (currentTickAmount - 1) / (tickAmount - 1);
-                        // Do not crop when ticks are not extremes (#9841)
-                        axis.min = axisOptions.startOnTick ?
-                            tickPositions[0] :
-                            Math.min(axis.min, tickPositions[0]);
-                        axis.max = axisOptions.endOnTick ?
-                            tickPositions[tickPositions.length - 1] :
-                            Math.max(axis.max, tickPositions[tickPositions.length - 1]);
-                        // We have too many ticks, run second pass to try to reduce ticks
-                    }
-                    else if (currentTickAmount > tickAmount) {
-                        axis.tickInterval *= 2;
-                        axis.setTickPositions();
-                    }
-                    // The finalTickAmt property is set in getTickAmount
-                    if (defined(finalTickAmt)) {
-                        i = len = tickPositions.length;
-                        while (i--) {
-                            if (
-                            // Remove every other tick
-                            (finalTickAmt === 3 && i % 2 === 1) ||
-                                // Remove all but first and last
-                                (finalTickAmt <= 2 && i > 0 && i < len - 1)) {
-                                tickPositions.splice(i, 1);
-                            }
-                        }
-                        axis.finalTickAmt = void 0;
-                    }
-                }
-            };
-            /**
-             * Set the scale based on data min and max, user set min and max or options.
-             *
-             * @private
-             * @function Highcharts.Axis#setScale
-             *
-             * @fires Highcharts.Axis#event:afterSetScale
-             */
-            Axis.prototype.setScale = function () {
-                var axis = this,
-                    isDirtyAxisLength,
-                    isDirtyData = false,
-                    isXAxisDirty = false;
-                axis.series.forEach(function (series) {
-                    var _a;
-                    isDirtyData = isDirtyData || series.isDirtyData || series.isDirty;
-                    // When x axis is dirty, we need new data extremes for y as
-                    // well:
-                    isXAxisDirty = isXAxisDirty || ((_a = series.xAxis) === null || _a === void 0 ? void 0 : _a.isDirty) || false;
-                });
-                axis.oldMin = axis.min;
-                axis.oldMax = axis.max;
-                axis.oldAxisLength = axis.len;
-                // set the new axisLength
-                axis.setAxisSize();
-                isDirtyAxisLength = axis.len !== axis.oldAxisLength;
-                // do we really need to go through all this?
-                if (isDirtyAxisLength ||
-                    isDirtyData ||
-                    isXAxisDirty ||
-                    axis.isLinked ||
-                    axis.forceRedraw ||
-                    axis.userMin !== axis.oldUserMin ||
-                    axis.userMax !== axis.oldUserMax ||
-                    axis.alignToOthers()) {
-                    if (axis.stacking) {
-                        axis.stacking.resetStacks();
-                    }
-                    axis.forceRedraw = false;
-                    // get data extremes if needed
-                    axis.getSeriesExtremes();
-                    // get fixed positions based on tickInterval
-                    axis.setTickInterval();
-                    // record old values to decide whether a rescale is necessary later
-                    // on (#540)
-                    axis.oldUserMin = axis.userMin;
-                    axis.oldUserMax = axis.userMax;
-                    // Mark as dirty if it is not already set to dirty and extremes have
-                    // changed. #595.
-                    if (!axis.isDirty) {
-                        axis.isDirty =
-                            isDirtyAxisLength ||
-                                axis.min !== axis.oldMin ||
-                                axis.max !== axis.oldMax;
-                    }
-                }
-                else if (axis.stacking) {
-                    axis.stacking.cleanStacks();
-                }
-                // Recalculate panning state object, when the data
-                // has changed. It is required when vertical panning is enabled.
-                if (isDirtyData && axis.panningState) {
-                    axis.panningState.isDirty = true;
-                }
-                fireEvent(this, 'afterSetScale');
-            };
-            /**
-             * Set the minimum and maximum of the axes after render time. If the
-             * `startOnTick` and `endOnTick` options are true, the minimum and maximum
-             * values are rounded off to the nearest tick. To prevent this, these
-             * options can be set to false before calling setExtremes. Also, setExtremes
-             * will not allow a range lower than the `minRange` option, which by default
-             * is the range of five points.
-             *
-             * @sample highcharts/members/axis-setextremes/
-             *         Set extremes from a button
-             * @sample highcharts/members/axis-setextremes-datetime/
-             *         Set extremes on a datetime axis
-             * @sample highcharts/members/axis-setextremes-off-ticks/
-             *         Set extremes off ticks
-             * @sample stock/members/axis-setextremes/
-             *         Set extremes in Highstock
-             * @sample maps/members/axis-setextremes/
-             *         Set extremes in Highmaps
-             *
-             * @function Highcharts.Axis#setExtremes
-             *
-             * @param {number} [newMin]
-             *        The new minimum value.
-             *
-             * @param {number} [newMax]
-             *        The new maximum value.
-             *
-             * @param {boolean} [redraw=true]
-             *        Whether to redraw the chart or wait for an explicit call to
-             *        {@link Highcharts.Chart#redraw}
-             *
-             * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation=true]
-             *        Enable or modify animations.
-             *
-             * @param {*} [eventArguments]
-             *        Arguments to be accessed in event handler.
-             *
-             * @fires Highcharts.Axis#event:setExtremes
-             */
-            Axis.prototype.setExtremes = function (newMin, newMax, redraw, animation, eventArguments) {
-                var axis = this,
-                    chart = axis.chart;
-                redraw = pick(redraw, true); // defaults to true
-                axis.series.forEach(function (serie) {
-                    delete serie.kdTree;
-                });
-                // Extend the arguments with min and max
-                eventArguments = extend(eventArguments, {
-                    min: newMin,
-                    max: newMax
-                });
-                // Fire the event
-                fireEvent(axis, 'setExtremes', eventArguments, function () {
-                    axis.userMin = newMin;
-                    axis.userMax = newMax;
-                    axis.eventArgs = eventArguments;
-                    if (redraw) {
-                        chart.redraw(animation);
-                    }
-                });
-            };
-            /**
-             * Overridable method for zooming chart. Pulled out in a separate method to
-             * allow overriding in stock charts.
-             * @private
-             * @function Highcharts.Axis#zoom
-             *
-             * @param {number} newMin
-             * TO-DO: parameter description
-             *
-             * @param {number} newMax
-             * TO-DO: parameter description
-             *
-             * @return {boolean}
-             */
-            Axis.prototype.zoom = function (newMin, newMax) {
-                var axis = this,
-                    dataMin = this.dataMin,
-                    dataMax = this.dataMax,
-                    options = this.options,
-                    min = Math.min(dataMin,
-                    pick(options.min,
-                    dataMin)),
-                    max = Math.max(dataMax,
-                    pick(options.max,
-                    dataMax)),
-                    evt = {
-                        newMin: newMin,
-                        newMax: newMax
-                    };
-                fireEvent(this, 'zoom', evt, function (e) {
-                    // Use e.newMin and e.newMax - event handlers may have altered them
-                    var newMin = e.newMin,
-                        newMax = e.newMax;
-                    if (newMin !== axis.min || newMax !== axis.max) { // #5790
-                        // Prevent pinch zooming out of range. Check for defined is for
-                        // #1946. #1734.
-                        if (!axis.allowZoomOutside) {
-                            // #6014, sometimes newMax will be smaller than min (or
-                            // newMin will be larger than max).
-                            if (defined(dataMin)) {
-                                if (newMin < min) {
-                                    newMin = min;
-                                }
-                                if (newMin > max) {
-                                    newMin = max;
-                                }
-                            }
-                            if (defined(dataMax)) {
-                                if (newMax < min) {
-                                    newMax = min;
-                                }
-                                if (newMax > max) {
-                                    newMax = max;
-                                }
-                            }
-                        }
-                        // In full view, displaying the reset zoom button is not
-                        // required
-                        axis.displayBtn = (typeof newMin !== 'undefined' ||
-                            typeof newMax !== 'undefined');
-                        // Do it
-                        axis.setExtremes(newMin, newMax, false, void 0, { trigger: 'zoom' });
-                    }
-                    e.zoomed = true;
-                });
-                return evt.zoomed;
-            };
-            /**
-             * Update the axis metrics.
-             *
-             * @private
-             * @function Highcharts.Axis#setAxisSize
-             */
-            Axis.prototype.setAxisSize = function () {
-                var chart = this.chart,
-                    options = this.options, 
-                    // [top, right, bottom, left]
-                    offsets = options.offsets || [0, 0, 0, 0],
-                    horiz = this.horiz, 
-                    // Check for percentage based input values. Rounding fixes problems
-                    // with column overflow and plot line filtering (#4898, #4899)
-                    width = this.width = Math.round(relativeLength(pick(options.width,
-                    chart.plotWidth - offsets[3] + offsets[1]),
-                    chart.plotWidth)),
-                    height = this.height = Math.round(relativeLength(pick(options.height,
-                    chart.plotHeight - offsets[0] + offsets[2]),
-                    chart.plotHeight)),
-                    top = this.top = Math.round(relativeLength(pick(options.top,
-                    chart.plotTop + offsets[0]),
-                    chart.plotHeight,
-                    chart.plotTop)),
-                    left = this.left = Math.round(relativeLength(pick(options.left,
-                    chart.plotLeft + offsets[3]),
-                    chart.plotWidth,
-                    chart.plotLeft));
-                // Expose basic values to use in Series object and navigator
-                this.bottom = chart.chartHeight - height - top;
-                this.right = chart.chartWidth - width - left;
-                // Direction agnostic properties
-                this.len = Math.max(horiz ? width : height, 0); // Math.max fixes #905
-                this.pos = horiz ? left : top; // distance from SVG origin
-            };
-            /**
-             * Get the current extremes for the axis.
-             *
-             * @sample highcharts/members/axis-getextremes/
-             *         Report extremes by click on a button
-             * @sample maps/members/axis-getextremes/
-             *         Get extremes in Highmaps
-             *
-             * @function Highcharts.Axis#getExtremes
-             *
-             * @return {Highcharts.ExtremesObject}
-             * An object containing extremes information.
-             */
-            Axis.prototype.getExtremes = function () {
-                var axis = this;
-                var log = axis.logarithmic;
-                return {
-                    min: log ?
-                        correctFloat(log.lin2log(axis.min)) :
-                        axis.min,
-                    max: log ?
-                        correctFloat(log.lin2log(axis.max)) :
-                        axis.max,
-                    dataMin: axis.dataMin,
-                    dataMax: axis.dataMax,
-                    userMin: axis.userMin,
-                    userMax: axis.userMax
-                };
-            };
-            /**
-             * Get the zero plane either based on zero or on the min or max value.
-             * Used in bar and area plots.
-             *
-             * @function Highcharts.Axis#getThreshold
-             *
-             * @param {number} threshold
-             * The threshold in axis values.
-             *
-             * @return {number|undefined}
-             * The translated threshold position in terms of pixels, and corrected to
-             * stay within the axis bounds.
-             */
-            Axis.prototype.getThreshold = function (threshold) {
-                var axis = this,
-                    log = axis.logarithmic,
-                    realMin = log ? log.lin2log(axis.min) : axis.min,
-                    realMax = log ? log.lin2log(axis.max) : axis.max;
-                if (threshold === null || threshold === -Infinity) {
-                    threshold = realMin;
-                }
-                else if (threshold === Infinity) {
-                    threshold = realMax;
-                }
-                else if (realMin > threshold) {
-                    threshold = realMin;
-                }
-                else if (realMax < threshold) {
-                    threshold = realMax;
-                }
-                return axis.translate(threshold, 0, 1, 0, 1);
-            };
-            /**
-             * Compute auto alignment for the axis label based on which side the axis is
-             * on and the given rotation for the label.
-             *
-             * @private
-             * @function Highcharts.Axis#autoLabelAlign
-             *
-             * @param {number} rotation
-             * The rotation in degrees as set by either the `rotation` or `autoRotation`
-             * options.
-             *
-             * @return {Highcharts.AlignValue}
-             * Can be `"center"`, `"left"` or `"right"`.
-             */
-            Axis.prototype.autoLabelAlign = function (rotation) {
-                var angle = (pick(rotation, 0) - (this.side * 90) + 720) % 360,
-                    evt = { align: 'center' };
-                fireEvent(this, 'autoLabelAlign', evt, function (e) {
-                    if (angle > 15 && angle < 165) {
-                        e.align = 'right';
-                    }
-                    else if (angle > 195 && angle < 345) {
-                        e.align = 'left';
-                    }
-                });
-                return evt.align;
-            };
-            /**
-             * Get the tick length and width for the axis based on axis options.
-             * @private
-             * @function Highcharts.Axis#tickSize
-             *
-             * @param {string} [prefix]
-             * 'tick' or 'minorTick'
-             *
-             * @return {Array<number,number>|undefined}
-             * An array of tickLength and tickWidth
-             */
-            Axis.prototype.tickSize = function (prefix) {
-                var options = this.options, tickLength = options[prefix === 'tick' ? 'tickLength' : 'minorTickLength'], tickWidth = pick(options[prefix === 'tick' ? 'tickWidth' : 'minorTickWidth'], 
-                    // Default to 1 on linear and datetime X axes
-                    prefix === 'tick' && this.isXAxis && !this.categories ? 1 : 0), e, tickSize;
-                if (tickWidth && tickLength) {
-                    // Negate the length
-                    if (options[prefix + 'Position'] === 'inside') {
-                        tickLength = -tickLength;
-                    }
-                    tickSize = [tickLength, tickWidth];
-                }
-                e = { tickSize: tickSize };
-                fireEvent(this, 'afterTickSize', e);
-                return e.tickSize;
-            };
-            /**
-             * Return the size of the labels.
-             *
-             * @private
-             * @function Highcharts.Axis#labelMetrics
-             *
-             * @return {Highcharts.FontMetricsObject}
-             */
-            Axis.prototype.labelMetrics = function () {
-                var index = this.tickPositions && this.tickPositions[0] || 0;
-                return this.chart.renderer.fontMetrics(this.options.labels.style &&
-                    this.options.labels.style.fontSize, this.ticks[index] && this.ticks[index].label);
-            };
-            /**
-             * Prevent the ticks from getting so close we can't draw the labels. On a
-             * horizontal axis, this is handled by rotating the labels, removing ticks
-             * and adding ellipsis. On a vertical axis remove ticks and add ellipsis.
-             *
-             * @private
-             * @function Highcharts.Axis#unsquish
-             *
-             * @return {number}
-             */
-            Axis.prototype.unsquish = function () {
-                var labelOptions = this.options.labels,
-                    horiz = this.horiz,
-                    tickInterval = this.tickInterval,
-                    newTickInterval = tickInterval,
-                    slotSize = this.len / (((this.categories ? 1 : 0) +
-                        this.max -
-                        this.min) /
-                        tickInterval),
-                    rotation,
-                    rotationOption = labelOptions.rotation,
-                    labelMetrics = this.labelMetrics(),
-                    step,
-                    bestScore = Number.MAX_VALUE,
-                    autoRotation,
-                    range = this.max - this.min, 
-                    // Return the multiple of tickInterval that is needed to avoid
-                    // collision
-                    getStep = function (spaceNeeded) {
-                        var step = spaceNeeded / (slotSize || 1);
-                    step = step > 1 ? Math.ceil(step) : 1;
-                    // Guard for very small or negative angles (#9835)
-                    if (step * tickInterval > range &&
-                        spaceNeeded !== Infinity &&
-                        slotSize !== Infinity &&
-                        range) {
-                        step = Math.ceil(range / tickInterval);
-                    }
-                    return correctFloat(step * tickInterval);
-                };
-                if (horiz) {
-                    autoRotation = !labelOptions.staggerLines &&
-                        !labelOptions.step &&
-                        ( // #3971
-                        defined(rotationOption) ?
-                            [rotationOption] :
-                            slotSize < pick(labelOptions.autoRotationLimit, 80) && labelOptions.autoRotation);
-                    if (autoRotation) {
-                        // Loop over the given autoRotation options, and determine
-                        // which gives the best score. The best score is that with
-                        // the lowest number of steps and a rotation closest
-                        // to horizontal.
-                        autoRotation.forEach(function (rot) {
-                            var score;
-                            if (rot === rotationOption ||
-                                (rot && rot >= -90 && rot <= 90)) { // #3891
-                                step = getStep(Math.abs(labelMetrics.h / Math.sin(deg2rad * rot)));
-                                score = step + Math.abs(rot / 360);
-                                if (score < bestScore) {
-                                    bestScore = score;
-                                    rotation = rot;
-                                    newTickInterval = step;
-                                }
-                            }
-                        });
-                    }
-                }
-                else if (!labelOptions.step) { // #4411
-                    newTickInterval = getStep(labelMetrics.h);
-                }
-                this.autoRotation = autoRotation;
-                this.labelRotation = pick(rotation, rotationOption);
-                return newTickInterval;
-            };
-            /**
-             * Get the general slot width for labels/categories on this axis. This may
-             * change between the pre-render (from Axis.getOffset) and the final tick
-             * rendering and placement.
-             *
-             * @private
-             * @function Highcharts.Axis#getSlotWidth
-             *
-             * @param {Highcharts.Tick} [tick] Optionally, calculate the slot width
-             * basing on tick label. It is used in highcharts-3d module, where the slots
-             * has different widths depending on perspective angles.
-             *
-             * @return {number}
-             * The pixel width allocated to each axis label.
-             */
-            Axis.prototype.getSlotWidth = function (tick) {
-                var _a;
-                // #5086, #1580, #1931
-                var chart = this.chart,
-                    horiz = this.horiz,
-                    labelOptions = this.options.labels,
-                    slotCount = Math.max(this.tickPositions.length - (this.categories ? 0 : 1), 1),
-                    marginLeft = chart.margin[3];
-                // Used by grid axis
-                if (tick && isNumber(tick.slotWidth)) { // #13221, can be 0
-                    return tick.slotWidth;
-                }
-                if (horiz &&
-                    labelOptions &&
-                    (labelOptions.step || 0) < 2) {
-                    if (labelOptions.rotation) { // #4415
-                        return 0;
-                    }
-                    return ((this.staggerLines || 1) * this.len) / slotCount;
-                }
-                if (!horiz) {
-                    // #7028
-                    var cssWidth = (_a = labelOptions === null || labelOptions === void 0 ? void 0 : labelOptions.style) === null || _a === void 0 ? void 0 : _a.width;
-                    if (cssWidth !== void 0) {
-                        return parseInt(cssWidth, 10);
-                    }
-                    if (marginLeft) {
-                        return marginLeft - chart.spacing[3];
-                    }
-                }
-                // Last resort, a fraction of the available size
-                return chart.chartWidth * 0.33;
-            };
-            /**
-             * Render the axis labels and determine whether ellipsis or rotation need to
-             * be applied.
-             *
-             * @private
-             * @function Highcharts.Axis#renderUnsquish
-             */
-            Axis.prototype.renderUnsquish = function () {
-                var chart = this.chart,
-                    renderer = chart.renderer,
-                    tickPositions = this.tickPositions,
-                    ticks = this.ticks,
-                    labelOptions = this.options.labels,
-                    labelStyleOptions = (labelOptions && labelOptions.style || {}),
-                    horiz = this.horiz,
-                    slotWidth = this.getSlotWidth(),
-                    innerWidth = Math.max(1,
-                    Math.round(slotWidth - 2 * (labelOptions.padding || 5))),
-                    attr = {},
-                    labelMetrics = this.labelMetrics(),
-                    textOverflowOption = (labelOptions.style &&
-                        labelOptions.style.textOverflow),
-                    commonWidth,
-                    commonTextOverflow,
-                    maxLabelLength = 0,
-                    label,
-                    i,
-                    pos;
-                // Set rotation option unless it is "auto", like in gauges
-                if (!isString(labelOptions.rotation)) {
-                    // #4443:
-                    attr.rotation = labelOptions.rotation || 0;
-                }
-                // Get the longest label length
-                tickPositions.forEach(function (tick) {
-                    tick = ticks[tick];
-                    // Replace label - sorting animation
-                    if (tick.movedLabel) {
-                        tick.replaceMovedLabel();
-                    }
-                    if (tick &&
-                        tick.label &&
-                        tick.label.textPxLength > maxLabelLength) {
-                        maxLabelLength = tick.label.textPxLength;
-                    }
-                });
-                this.maxLabelLength = maxLabelLength;
-                // Handle auto rotation on horizontal axis
-                if (this.autoRotation) {
-                    // Apply rotation only if the label is too wide for the slot, and
-                    // the label is wider than its height.
-                    if (maxLabelLength > innerWidth &&
-                        maxLabelLength > labelMetrics.h) {
-                        attr.rotation = this.labelRotation;
-                    }
-                    else {
-                        this.labelRotation = 0;
-                    }
-                    // Handle word-wrap or ellipsis on vertical axis
-                }
-                else if (slotWidth) {
-                    // For word-wrap or ellipsis
-                    commonWidth = innerWidth;
-                    if (!textOverflowOption) {
-                        commonTextOverflow = 'clip';
-                        // On vertical axis, only allow word wrap if there is room
-                        // for more lines.
-                        i = tickPositions.length;
-                        while (!horiz && i--) {
-                            pos = tickPositions[i];
-                            label = ticks[pos].label;
-                            if (label) {
-                                // Reset ellipsis in order to get the correct
-                                // bounding box (#4070)
-                                if (label.styles &&
-                                    label.styles.textOverflow === 'ellipsis') {
-                                    label.css({ textOverflow: 'clip' });
-                                    // Set the correct width in order to read
-                                    // the bounding box height (#4678, #5034)
-                                }
-                                else if (label.textPxLength > slotWidth) {
-                                    label.css({ width: slotWidth + 'px' });
-                                }
-                                if (label.getBBox().height > (this.len / tickPositions.length -
-                                    (labelMetrics.h - labelMetrics.f))) {
-                                    label.specificTextOverflow = 'ellipsis';
-                                }
-                            }
-                        }
-                    }
-                }
-                // Add ellipsis if the label length is significantly longer than ideal
-                if (attr.rotation) {
-                    commonWidth = (maxLabelLength > chart.chartHeight * 0.5 ?
-                        chart.chartHeight * 0.33 :
-                        maxLabelLength);
-                    if (!textOverflowOption) {
-                        commonTextOverflow = 'ellipsis';
-                    }
-                }
-                // Set the explicit or automatic label alignment
-                this.labelAlign = labelOptions.align ||
-                    this.autoLabelAlign(this.labelRotation);
-                if (this.labelAlign) {
-                    attr.align = this.labelAlign;
-                }
-                // Apply general and specific CSS
-                tickPositions.forEach(function (pos) {
-                    var tick = ticks[pos],
-                        label = tick && tick.label,
-                        widthOption = labelStyleOptions.width,
-                        css = {};
-                    if (label) {
-                        // This needs to go before the CSS in old IE (#4502)
-                        label.attr(attr);
-                        if (tick.shortenLabel) {
-                            tick.shortenLabel();
-                        }
-                        else if (commonWidth &&
-                            !widthOption &&
-                            // Setting width in this case messes with the bounding box
-                            // (#7975)
-                            labelStyleOptions.whiteSpace !== 'nowrap' &&
-                            (
-                            // Speed optimizing, #7656
-                            commonWidth < label.textPxLength ||
-                                // Resetting CSS, #4928
-                                label.element.tagName === 'SPAN')) {
-                            css.width = commonWidth + 'px';
-                            if (!textOverflowOption) {
-                                css.textOverflow = (label.specificTextOverflow ||
-                                    commonTextOverflow);
-                            }
-                            label.css(css);
-                            // Reset previously shortened label (#8210)
-                        }
-                        else if (label.styles &&
-                            label.styles.width &&
-                            !css.width &&
-                            !widthOption) {
-                            label.css({ width: null });
-                        }
-                        delete label.specificTextOverflow;
-                        tick.rotation = attr.rotation;
-                    }
-                }, this);
-                // Note: Why is this not part of getLabelPosition?
-                this.tickRotCorr = renderer.rotCorr(labelMetrics.b, this.labelRotation || 0, this.side !== 0);
-            };
-            /**
-             * Return true if the axis has associated data.
-             *
-             * @function Highcharts.Axis#hasData
-             *
-             * @return {boolean}
-             * True if the axis has associated visible series and those series have
-             * either valid data points or explicit `min` and `max` settings.
-             */
-            Axis.prototype.hasData = function () {
-                return this.series.some(function (s) {
-                    return s.hasData();
-                }) ||
-                    (this.options.showEmpty &&
-                        defined(this.min) &&
-                        defined(this.max));
-            };
-            /**
-             * Adds the title defined in axis.options.title.
-             *
-             * @function Highcharts.Axis#addTitle
-             *
-             * @param {boolean} [display]
-             * Whether or not to display the title.
-             */
-            Axis.prototype.addTitle = function (display) {
-                var axis = this,
-                    renderer = axis.chart.renderer,
-                    horiz = axis.horiz,
-                    opposite = axis.opposite,
-                    options = axis.options,
-                    axisTitleOptions = options.title,
-                    textAlign,
-                    styledMode = axis.chart.styledMode;
-                if (!axis.axisTitle) {
-                    textAlign = axisTitleOptions.textAlign;
-                    if (!textAlign) {
-                        textAlign = (horiz ? {
-                            low: 'left',
-                            middle: 'center',
-                            high: 'right'
-                        } : {
-                            low: opposite ? 'right' : 'left',
-                            middle: 'center',
-                            high: opposite ? 'left' : 'right'
-                        })[axisTitleOptions.align];
-                    }
-                    axis.axisTitle = renderer
-                        .text(axisTitleOptions.text, 0, 0, axisTitleOptions.useHTML)
-                        .attr({
-                        zIndex: 7,
-                        rotation: axisTitleOptions.rotation || 0,
-                        align: textAlign
-                    })
-                        .addClass('highcharts-axis-title');
-                    // #7814, don't mutate style option
-                    if (!styledMode) {
-                        axis.axisTitle.css(merge(axisTitleOptions.style));
-                    }
-                    axis.axisTitle.add(axis.axisGroup);
-                    axis.axisTitle.isNew = true;
-                }
-                // Max width defaults to the length of the axis
-                if (!styledMode &&
-                    !axisTitleOptions.style.width &&
-                    !axis.isRadial) {
-                    axis.axisTitle.css({
-                        width: axis.len + 'px'
-                    });
-                }
-                // hide or show the title depending on whether showEmpty is set
-                axis.axisTitle[display ? 'show' : 'hide'](display);
-            };
-            /**
-             * Generates a tick for initial positioning.
-             *
-             * @private
-             * @function Highcharts.Axis#generateTick
-             *
-             * @param {number} pos
-             * The tick position in axis values.
-             *
-             * @param {number} [i]
-             * The index of the tick in {@link Axis.tickPositions}.
-             */
-            Axis.prototype.generateTick = function (pos) {
-                var axis = this;
-                var ticks = axis.ticks;
-                if (!ticks[pos]) {
-                    ticks[pos] = new Tick(axis, pos);
-                }
-                else {
-                    ticks[pos].addLabel(); // update labels depending on tick interval
-                }
-            };
-            /**
-             * Render the tick labels to a preliminary position to get their sizes
-             *
-             * @private
-             * @function Highcharts.Axis#getOffset
-             *
-             * @fires Highcharts.Axis#event:afterGetOffset
-             */
-            Axis.prototype.getOffset = function () {
-                var axis = this,
-                    chart = axis.chart,
-                    renderer = chart.renderer,
-                    options = axis.options,
-                    tickPositions = axis.tickPositions,
-                    ticks = axis.ticks,
-                    horiz = axis.horiz,
-                    side = axis.side,
-                    invertedSide = chart.inverted &&
-                        !axis.isZAxis ? [1, 0, 3, 2][side] : side,
-                    hasData,
-                    showAxis,
-                    titleOffset = 0,
-                    titleOffsetOption,
-                    titleMargin = 0,
-                    axisTitleOptions = options.title,
-                    labelOptions = options.labels,
-                    labelOffset = 0, // reset
-                    labelOffsetPadded,
-                    axisOffset = chart.axisOffset,
-                    clipOffset = chart.clipOffset,
-                    clip,
-                    directionFactor = [-1, 1, 1, -1][side],
-                    className = options.className,
-                    axisParent = axis.axisParent, // Used in color axis
-                    lineHeightCorrection;
-                // For reuse in Axis.render
-                hasData = axis.hasData();
-                axis.showAxis = showAxis = hasData || pick(options.showEmpty, true);
-                // Set/reset staggerLines
-                axis.staggerLines = axis.horiz && labelOptions.staggerLines;
-                // Create the axisGroup and gridGroup elements on first iteration
-                if (!axis.axisGroup) {
-                    axis.gridGroup = renderer.g('grid')
-                        .attr({ zIndex: options.gridZIndex || 1 })
-                        .addClass('highcharts-' + this.coll.toLowerCase() + '-grid ' +
-                        (className || ''))
-                        .add(axisParent);
-                    axis.axisGroup = renderer.g('axis')
-                        .attr({ zIndex: options.zIndex || 2 })
-                        .addClass('highcharts-' + this.coll.toLowerCase() + ' ' +
-                        (className || ''))
-                        .add(axisParent);
-                    axis.labelGroup = renderer.g('axis-labels')
-                        .attr({ zIndex: labelOptions.zIndex || 7 })
-                        .addClass('highcharts-' + axis.coll.toLowerCase() + '-labels ' +
-                        (className || ''))
-                        .add(axisParent);
-                }
-                if (hasData || axis.isLinked) {
-                    // Generate ticks
-                    tickPositions.forEach(function (pos, i) {
-                        // i is not used here, but may be used in overrides
-                        axis.generateTick(pos, i);
-                    });
-                    axis.renderUnsquish();
-                    // Left side must be align: right and right side must
-                    // have align: left for labels
-                    axis.reserveSpaceDefault = (side === 0 ||
-                        side === 2 ||
-                        { 1: 'left', 3: 'right' }[side] === axis.labelAlign);
-                    if (pick(labelOptions.reserveSpace, axis.labelAlign === 'center' ? true : null, axis.reserveSpaceDefault)) {
-                        tickPositions.forEach(function (pos) {
-                            // get the highest offset
-                            labelOffset = Math.max(ticks[pos].getLabelSize(), labelOffset);
-                        });
-                    }
-                    if (axis.staggerLines) {
-                        labelOffset *= axis.staggerLines;
-                    }
-                    axis.labelOffset = labelOffset * (axis.opposite ? -1 : 1);
-                }
-                else { // doesn't have data
-                    objectEach(ticks, function (tick, n) {
-                        tick.destroy();
-                        delete ticks[n];
-                    });
-                }
-                if (axisTitleOptions &&
-                    axisTitleOptions.text &&
-                    axisTitleOptions.enabled !== false) {
-                    axis.addTitle(showAxis);
-                    if (showAxis && axisTitleOptions.reserveSpace !== false) {
-                        axis.titleOffset = titleOffset =
-                            axis.axisTitle.getBBox()[horiz ? 'height' : 'width'];
-                        titleOffsetOption = axisTitleOptions.offset;
-                        titleMargin = defined(titleOffsetOption) ?
-                            0 :
-                            pick(axisTitleOptions.margin, horiz ? 5 : 10);
-                    }
-                }
-                // Render the axis line
-                axis.renderLine();
-                // handle automatic or user set offset
-                axis.offset = directionFactor * pick(options.offset, axisOffset[side] ? axisOffset[side] + (options.margin || 0) : 0);
-                axis.tickRotCorr = axis.tickRotCorr || { x: 0, y: 0 }; // polar
-                if (side === 0) {
-                    lineHeightCorrection = -axis.labelMetrics().h;
-                }
-                else if (side === 2) {
-                    lineHeightCorrection = axis.tickRotCorr.y;
-                }
-                else {
-                    lineHeightCorrection = 0;
-                }
-                // Find the padded label offset
-                labelOffsetPadded = Math.abs(labelOffset) + titleMargin;
-                if (labelOffset) {
-                    labelOffsetPadded -= lineHeightCorrection;
-                    labelOffsetPadded += directionFactor * (horiz ?
-                        pick(labelOptions.y, axis.tickRotCorr.y + directionFactor * 8) :
-                        labelOptions.x);
-                }
-                axis.axisTitleMargin = pick(titleOffsetOption, labelOffsetPadded);
-                if (axis.getMaxLabelDimensions) {
-                    axis.maxLabelDimensions = axis.getMaxLabelDimensions(ticks, tickPositions);
-                }
-                // Due to GridAxis.tickSize, tickSize should be calculated after ticks
-                // has rendered.
-                var tickSize = this.tickSize('tick');
-                axisOffset[side] = Math.max(axisOffset[side], axis.axisTitleMargin + titleOffset +
-                    directionFactor * axis.offset, labelOffsetPadded, // #3027
-                tickPositions && tickPositions.length && tickSize ?
-                    tickSize[0] + directionFactor * axis.offset :
-                    0 // #4866
-                );
-                // Decide the clipping needed to keep the graph inside
-                // the plot area and axis lines
-                clip = options.offset ?
-                    0 :
-                    // #4308, #4371:
-                    Math.floor(axis.axisLine.strokeWidth() / 2) * 2;
-                clipOffset[invertedSide] =
-                    Math.max(clipOffset[invertedSide], clip);
-                fireEvent(this, 'afterGetOffset');
-            };
-            /**
-             * Internal function to get the path for the axis line. Extended for polar
-             * charts.
-             *
-             * @function Highcharts.Axis#getLinePath
-             *
-             * @param {number} lineWidth
-             * The line width in pixels.
-             *
-             * @return {Highcharts.SVGPathArray}
-             * The SVG path definition in array form.
-             */
-            Axis.prototype.getLinePath = function (lineWidth) {
-                var chart = this.chart,
-                    opposite = this.opposite,
-                    offset = this.offset,
-                    horiz = this.horiz,
-                    lineLeft = this.left + (opposite ? this.width : 0) + offset,
-                    lineTop = chart.chartHeight - this.bottom -
-                        (opposite ? this.height : 0) + offset;
-                if (opposite) {
-                    lineWidth *= -1; // crispify the other way - #1480, #1687
-                }
-                return chart.renderer
-                    .crispLine([
-                    [
-                        'M',
-                        horiz ?
-                            this.left :
-                            lineLeft,
-                        horiz ?
-                            lineTop :
-                            this.top
-                    ],
-                    [
-                        'L',
-                        horiz ?
-                            chart.chartWidth - this.right :
-                            lineLeft,
-                        horiz ?
-                            lineTop :
-                            chart.chartHeight - this.bottom
-                    ]
-                ], lineWidth);
-            };
-            /**
-             * Render the axis line. Called internally when rendering and redrawing the
-             * axis.
-             *
-             * @function Highcharts.Axis#renderLine
-             */
-            Axis.prototype.renderLine = function () {
-                if (!this.axisLine) {
-                    this.axisLine = this.chart.renderer.path()
-                        .addClass('highcharts-axis-line')
-                        .add(this.axisGroup);
-                    if (!this.chart.styledMode) {
-                        this.axisLine.attr({
-                            stroke: this.options.lineColor,
-                            'stroke-width': this.options.lineWidth,
-                            zIndex: 7
-                        });
-                    }
-                }
-            };
-            /**
-             * Position the axis title.
-             *
-             * @private
-             * @function Highcharts.Axis#getTitlePosition
-             *
-             * @return {Highcharts.PositionObject}
-             * X and Y positions for the title.
-             */
-            Axis.prototype.getTitlePosition = function () {
-                // compute anchor points for each of the title align options
-                var horiz = this.horiz,
-                    axisLeft = this.left,
-                    axisTop = this.top,
-                    axisLength = this.len,
-                    axisTitleOptions = this.options.title,
-                    margin = horiz ? axisLeft : axisTop,
-                    opposite = this.opposite,
-                    offset = this.offset,
-                    xOption = axisTitleOptions.x || 0,
-                    yOption = axisTitleOptions.y || 0,
-                    axisTitle = this.axisTitle,
-                    fontMetrics = this.chart.renderer.fontMetrics(axisTitleOptions.style &&
-                        axisTitleOptions.style.fontSize,
-                    axisTitle), 
-                    // The part of a multiline text that is below the baseline of the
-                    // first line. Subtract 1 to preserve pixel-perfectness from the
-                    // old behaviour (v5.0.12), where only one line was allowed.
-                    textHeightOvershoot = Math.max(axisTitle.getBBox(null, 0).height - fontMetrics.h - 1, 0), 
-                    // the position in the length direction of the axis
-                    alongAxis = {
-                        low: margin + (horiz ? 0 : axisLength),
-                        middle: margin + axisLength / 2,
-                        high: margin + (horiz ? axisLength : 0)
-                    }[axisTitleOptions.align], 
-                    // the position in the perpendicular direction of the axis
-                    offAxis = (horiz ? axisTop + this.height : axisLeft) +
-                        (horiz ? 1 : -1) * // horizontal axis reverses the margin
-                            (opposite ? -1 : 1) * // so does opposite axes
-                            this.axisTitleMargin +
-                        [
-                            -textHeightOvershoot,
-                            textHeightOvershoot,
-                            fontMetrics.f,
-                            -textHeightOvershoot // left
-                        ][this.side],
-                    titlePosition = {
-                        x: horiz ?
-                            alongAxis + xOption :
-                            offAxis + (opposite ? this.width : 0) + offset + xOption,
-                        y: horiz ?
-                            offAxis + yOption - (opposite ? this.height : 0) + offset :
-                            alongAxis + yOption
-                    };
-                fireEvent(this, 'afterGetTitlePosition', { titlePosition: titlePosition });
-                return titlePosition;
-            };
-            /**
-             * Render a minor tick into the given position. If a minor tick already
-             * exists in this position, move it.
-             *
-             * @function Highcharts.Axis#renderMinorTick
-             *
-             * @param {number} pos
-             * The position in axis values.
-             */
-            Axis.prototype.renderMinorTick = function (pos) {
-                var axis = this;
-                var slideInTicks = axis.chart.hasRendered && isNumber(axis.oldMin);
-                var minorTicks = axis.minorTicks;
-                if (!minorTicks[pos]) {
-                    minorTicks[pos] = new Tick(axis, pos, 'minor');
-                }
-                // Render new ticks in old position
-                if (slideInTicks && minorTicks[pos].isNew) {
-                    minorTicks[pos].render(null, true);
-                }
-                minorTicks[pos].render(null, false, 1);
-            };
-            /**
-             * Render a major tick into the given position. If a tick already exists
-             * in this position, move it.
-             *
-             * @function Highcharts.Axis#renderTick
-             *
-             * @param {number} pos
-             * The position in axis values.
-             *
-             * @param {number} i
-             * The tick index.
-             */
-            Axis.prototype.renderTick = function (pos, i) {
-                var _a;
-                var axis = this;
-                var isLinked = axis.isLinked;
-                var ticks = axis.ticks;
-                var slideInTicks = axis.chart.hasRendered && isNumber(axis.oldMin);
-                // Linked axes need an extra check to find out if
-                if (!isLinked ||
-                    (pos >= axis.min && pos <= axis.max) || ((_a = axis.grid) === null || _a === void 0 ? void 0 : _a.isColumn)) {
-                    if (!ticks[pos]) {
-                        ticks[pos] = new Tick(axis, pos);
-                    }
-                    // NOTE this seems like overkill. Could be handled in tick.render by
-                    // setting old position in attr, then set new position in animate.
-                    // render new ticks in old position
-                    if (slideInTicks && ticks[pos].isNew) {
-                        // Start with negative opacity so that it is visible from
-                        // halfway into the animation
-                        ticks[pos].render(i, true, -1);
-                    }
-                    ticks[pos].render(i);
-                }
-            };
-            /**
-             * Render the axis.
-             *
-             * @private
-             * @function Highcharts.Axis#render
-             *
-             * @fires Highcharts.Axis#event:afterRender
-             */
-            Axis.prototype.render = function () {
-                var axis = this,
-                    chart = axis.chart,
-                    log = axis.logarithmic,
-                    renderer = chart.renderer,
-                    options = axis.options,
-                    isLinked = axis.isLinked,
-                    tickPositions = axis.tickPositions,
-                    axisTitle = axis.axisTitle,
-                    ticks = axis.ticks,
-                    minorTicks = axis.minorTicks,
-                    alternateBands = axis.alternateBands,
-                    stackLabelOptions = options.stackLabels,
-                    alternateGridColor = options.alternateGridColor,
-                    tickmarkOffset = axis.tickmarkOffset,
-                    axisLine = axis.axisLine,
-                    showAxis = axis.showAxis,
-                    animation = animObject(renderer.globalAnimation),
-                    from,
-                    to;
-                // Reset
-                axis.labelEdge.length = 0;
-                axis.overlap = false;
-                // Mark all elements inActive before we go over and mark the active ones
-                [ticks, minorTicks, alternateBands].forEach(function (coll) {
-                    objectEach(coll, function (tick) {
-                        tick.isActive = false;
-                    });
-                });
-                // If the series has data draw the ticks. Else only the line and title
-                if (axis.hasData() || isLinked) {
-                    // minor ticks
-                    if (axis.minorTickInterval && !axis.categories) {
-                        axis.getMinorTickPositions().forEach(function (pos) {
-                            axis.renderMinorTick(pos);
-                        });
-                    }
-                    // Major ticks. Pull out the first item and render it last so that
-                    // we can get the position of the neighbour label. #808.
-                    if (tickPositions.length) { // #1300
-                        tickPositions.forEach(function (pos, i) {
-                            axis.renderTick(pos, i);
-                        });
-                        // In a categorized axis, the tick marks are displayed
-                        // between labels. So we need to add a tick mark and
-                        // grid line at the left edge of the X axis.
-                        if (tickmarkOffset && (axis.min === 0 || axis.single)) {
-                            if (!ticks[-1]) {
-                                ticks[-1] = new Tick(axis, -1, null, true);
-                            }
-                            ticks[-1].render(-1);
-                        }
-                    }
-                    // alternate grid color
-                    if (alternateGridColor) {
-                        tickPositions.forEach(function (pos, i) {
-                            to = typeof tickPositions[i + 1] !== 'undefined' ?
-                                tickPositions[i + 1] + tickmarkOffset :
-                                axis.max - tickmarkOffset;
-                            if (i % 2 === 0 &&
-                                pos < axis.max &&
-                                to <= axis.max + (chart.polar ?
-                                    -tickmarkOffset :
-                                    tickmarkOffset)) { // #2248, #4660
-                                if (!alternateBands[pos]) {
-                                    // Should be imported from PlotLineOrBand.js, but
-                                    // the dependency cycle with axis is a problem
-                                    alternateBands[pos] = new H.PlotLineOrBand(axis);
-                                }
-                                from = pos + tickmarkOffset; // #949
-                                alternateBands[pos].options = {
-                                    from: log ? log.lin2log(from) : from,
-                                    to: log ? log.lin2log(to) : to,
-                                    color: alternateGridColor,
-                                    className: 'highcharts-alternate-grid'
-                                };
-                                alternateBands[pos].render();
-                                alternateBands[pos].isActive = true;
-                            }
-                        });
-                    }
-                    // custom plot lines and bands
-                    if (!axis._addedPlotLB) { // only first time
-                        (options.plotLines || [])
-                            .concat(options.plotBands || [])
-                            .forEach(function (plotLineOptions) {
-                            axis.addPlotBandOrLine(plotLineOptions);
-                        });
-                        axis._addedPlotLB = true;
-                    }
-                } // end if hasData
-                // Remove inactive ticks
-                [ticks, minorTicks, alternateBands].forEach(function (coll) {
-                    var i,
-                        forDestruction = [],
-                        delay = animation.duration,
-                        destroyInactiveItems = function () {
-                            i = forDestruction.length;
-                        while (i--) {
-                            // When resizing rapidly, the same items
-                            // may be destroyed in different timeouts,
-                            // or the may be reactivated
-                            if (coll[forDestruction[i]] &&
-                                !coll[forDestruction[i]].isActive) {
-                                coll[forDestruction[i]].destroy();
-                                delete coll[forDestruction[i]];
-                            }
-                        }
-                    };
-                    objectEach(coll, function (tick, pos) {
-                        if (!tick.isActive) {
-                            // Render to zero opacity
-                            tick.render(pos, false, 0);
-                            tick.isActive = false;
-                            forDestruction.push(pos);
-                        }
-                    });
-                    // When the objects are finished fading out, destroy them
-                    syncTimeout(destroyInactiveItems, coll === alternateBands ||
-                        !chart.hasRendered ||
-                        !delay ?
-                        0 :
-                        delay);
-                });
-                // Set the axis line path
-                if (axisLine) {
-                    axisLine[axisLine.isPlaced ? 'animate' : 'attr']({
-                        d: this.getLinePath(axisLine.strokeWidth())
-                    });
-                    axisLine.isPlaced = true;
-                    // Show or hide the line depending on options.showEmpty
-                    axisLine[showAxis ? 'show' : 'hide'](showAxis);
-                }
-                if (axisTitle && showAxis) {
-                    var titleXy = axis.getTitlePosition();
-                    if (isNumber(titleXy.y)) {
-                        axisTitle[axisTitle.isNew ? 'attr' : 'animate'](titleXy);
-                        axisTitle.isNew = false;
-                    }
-                    else {
-                        axisTitle.attr('y', -9999);
-                        axisTitle.isNew = true;
-                    }
-                }
-                // Stacked totals:
-                if (stackLabelOptions && stackLabelOptions.enabled && axis.stacking) {
-                    axis.stacking.renderStackTotals();
-                }
-                // End stacked totals
-                axis.isDirty = false;
-                fireEvent(this, 'afterRender');
-            };
-            /**
-             * Redraw the axis to reflect changes in the data or axis extremes. Called
-             * internally from Highcharts.Chart#redraw.
-             *
-             * @private
-             * @function Highcharts.Axis#redraw
-             */
-            Axis.prototype.redraw = function () {
-                if (this.visible) {
-                    // render the axis
-                    this.render();
-                    // move plot lines and bands
-                    this.plotLinesAndBands.forEach(function (plotLine) {
-                        plotLine.render();
-                    });
-                }
-                // mark associated series as dirty and ready for redraw
-                this.series.forEach(function (series) {
-                    series.isDirty = true;
-                });
-            };
-            /**
-             * Returns an array of axis properties, that should be untouched during
-             * reinitialization.
-             *
-             * @private
-             * @function Highcharts.Axis#getKeepProps
-             *
-             * @return {Array<string>}
-             */
-            Axis.prototype.getKeepProps = function () {
-                return (this.keepProps || Axis.keepProps);
-            };
-            /**
-             * Destroys an Axis instance. See {@link Axis#remove} for the API endpoint
-             * to fully remove the axis.
-             *
-             * @private
-             * @function Highcharts.Axis#destroy
-             *
-             * @param {boolean} [keepEvents]
-             * Whether to preserve events, used internally in Axis.update.
-             */
-            Axis.prototype.destroy = function (keepEvents) {
-                var axis = this,
-                    plotLinesAndBands = axis.plotLinesAndBands,
-                    plotGroup,
-                    i;
-                fireEvent(this, 'destroy', { keepEvents: keepEvents });
-                // Remove the events
-                if (!keepEvents) {
-                    removeEvent(axis);
-                }
-                // Destroy collections
-                [axis.ticks, axis.minorTicks, axis.alternateBands].forEach(function (coll) {
-                    destroyObjectProperties(coll);
-                });
-                if (plotLinesAndBands) {
-                    i = plotLinesAndBands.length;
-                    while (i--) { // #1975
-                        plotLinesAndBands[i].destroy();
-                    }
-                }
-                // Destroy elements
-                ['axisLine', 'axisTitle', 'axisGroup',
-                    'gridGroup', 'labelGroup', 'cross', 'scrollbar'].forEach(function (prop) {
-                    if (axis[prop]) {
-                        axis[prop] = axis[prop].destroy();
-                    }
-                });
-                // Destroy each generated group for plotlines and plotbands
-                for (plotGroup in axis.plotLinesAndBandsGroups) { // eslint-disable-line guard-for-in
-                    axis.plotLinesAndBandsGroups[plotGroup] =
-                        axis.plotLinesAndBandsGroups[plotGroup].destroy();
-                }
-                // Delete all properties and fall back to the prototype.
-                objectEach(axis, function (val, key) {
-                    if (axis.getKeepProps().indexOf(key) === -1) {
-                        delete axis[key];
-                    }
-                });
-            };
-            /**
-             * Internal function to draw a crosshair.
-             *
-             * @function Highcharts.Axis#drawCrosshair
-             *
-             * @param {Highcharts.PointerEventObject} [e]
-             * The event arguments from the modified pointer event, extended with
-             * `chartX` and `chartY`
-             *
-             * @param {Highcharts.Point} [point]
-             * The Point object if the crosshair snaps to points.
-             *
-             * @fires Highcharts.Axis#event:afterDrawCrosshair
-             * @fires Highcharts.Axis#event:drawCrosshair
-             */
-            Axis.prototype.drawCrosshair = function (e, point) {
-                var path,
-                    options = this.crosshair,
-                    snap = pick(options.snap,
-                    true),
-                    pos,
-                    categorized,
-                    graphic = this.cross,
-                    crossOptions,
-                    chart = this.chart;
-                fireEvent(this, 'drawCrosshair', { e: e, point: point });
-                // Use last available event when updating non-snapped crosshairs without
-                // mouse interaction (#5287)
-                if (!e) {
-                    e = this.cross && this.cross.e;
-                }
-                if (
-                // Disabled in options
-                !this.crosshair ||
-                    // Snap
-                    ((defined(point) || !snap) === false)) {
-                    this.hideCrosshair();
-                }
-                else {
-                    // Get the path
-                    if (!snap) {
-                        pos = e &&
-                            (this.horiz ?
-                                e.chartX - this.pos :
-                                this.len - e.chartY + this.pos);
-                    }
-                    else if (defined(point)) {
-                        // #3834
-                        pos = pick(this.coll !== 'colorAxis' ?
-                            point.crosshairPos : // 3D axis extension
-                            null, this.isXAxis ?
-                            point.plotX :
-                            this.len - point.plotY);
-                    }
-                    if (defined(pos)) {
-                        crossOptions = {
-                            // value, only used on radial
-                            value: point && (this.isXAxis ?
-                                point.x :
-                                pick(point.stackY, point.y)),
-                            translatedValue: pos
-                        };
-                        if (chart.polar) {
-                            // Additional information required for crosshairs in
-                            // polar chart
-                            extend(crossOptions, {
-                                isCrosshair: true,
-                                chartX: e && e.chartX,
-                                chartY: e && e.chartY,
-                                point: point
-                            });
-                        }
-                        path = this.getPlotLinePath(crossOptions) ||
-                            null; // #3189
-                    }
-                    if (!defined(path)) {
-                        this.hideCrosshair();
-                        return;
-                    }
-                    categorized = this.categories && !this.isRadial;
-                    // Draw the cross
-                    if (!graphic) {
-                        this.cross = graphic = chart.renderer
-                            .path()
-                            .addClass('highcharts-crosshair highcharts-crosshair-' +
-                            (categorized ? 'category ' : 'thin ') +
-                            options.className)
-                            .attr({
-                            zIndex: pick(options.zIndex, 2)
-                        })
-                            .add();
-                        // Presentational attributes
-                        if (!chart.styledMode) {
-                            graphic.attr({
-                                stroke: options.color ||
-                                    (categorized ?
-                                        Color
-                                            .parse('#ccd6eb')
-                                            .setOpacity(0.25)
-                                            .get() :
-                                        '#cccccc'),
-                                'stroke-width': pick(options.width, 1)
-                            }).css({
-                                'pointer-events': 'none'
-                            });
-                            if (options.dashStyle) {
-                                graphic.attr({
-                                    dashstyle: options.dashStyle
-                                });
-                            }
-                        }
-                    }
-                    graphic.show().attr({
-                        d: path
-                    });
-                    if (categorized && !options.width) {
-                        graphic.attr({
-                            'stroke-width': this.transA
-                        });
-                    }
-                    this.cross.e = e;
-                }
-                fireEvent(this, 'afterDrawCrosshair', { e: e, point: point });
-            };
-            /**
-             * Hide the crosshair if visible.
-             *
-             * @function Highcharts.Axis#hideCrosshair
-             */
-            Axis.prototype.hideCrosshair = function () {
-                if (this.cross) {
-                    this.cross.hide();
-                }
-                fireEvent(this, 'afterHideCrosshair');
-            };
-            /**
-            * Check whether the chart has vertical panning ('y' or 'xy' type).
-            *
-            * @private
-            * @function Highcharts.Axis#hasVerticalPanning
-            * @return {boolean}
-            *
-            */
-            Axis.prototype.hasVerticalPanning = function () {
-                var _a,
-                    _b;
-                return /y/.test(((_b = (_a = this.chart.options.chart) === null || _a === void 0 ? void 0 : _a.panning) === null || _b === void 0 ? void 0 : _b.type) || '');
-            };
-            /**
-            * Check whether the given value is a positive valid axis value.
-            *
-            * @private
-            * @function Highcharts.Axis#validatePositiveValue
-            *
-            * @param {unknown} value
-            * The axis value
-            * @return {boolean}
-            *
-            */
-            Axis.prototype.validatePositiveValue = function (value) {
-                return isNumber(value) && value > 0;
-            };
-            /* *
-             *
-             *  Static Properties
-             *
-             * */
-            /**
-             * The X axis or category axis. Normally this is the horizontal axis,
-             * though if the chart is inverted this is the vertical axis. In case of
-             * multiple axes, the xAxis node is an array of configuration objects.
-             *
-             * See the [Axis class](/class-reference/Highcharts.Axis) for programmatic
-             * access to the axis.
-             *
-             * @productdesc {highmaps}
-             * In Highmaps, the axis is hidden, but it is used behind the scenes to
-             * control features like zooming and panning. Zooming is in effect the same
-             * as setting the extremes of one of the exes.
-             *
-             * @type         {*|Array<*>}
-             * @optionparent xAxis
-             *
-             * @private
-             */
-            Axis.defaultOptions = {
-                /**
-                 * When using multiple axis, the ticks of two or more opposite axes
-                 * will automatically be aligned by adding ticks to the axis or axes
-                 * with the least ticks, as if `tickAmount` were specified.
-                 *
-                 * This can be prevented by setting `alignTicks` to false. If the grid
-                 * lines look messy, it's a good idea to hide them for the secondary
-                 * axis by setting `gridLineWidth` to 0.
-                 *
-                 * If `startOnTick` or `endOnTick` in an Axis options are set to false,
-                 * then the `alignTicks ` will be disabled for the Axis.
-                 *
-                 * Disabled for logarithmic axes.
-                 *
-                 * @type      {boolean}
-                 * @default   true
-                 * @product   highcharts highstock gantt
-                 * @apioption xAxis.alignTicks
-                 */
-                /**
-                 * Whether to allow decimals in this axis' ticks. When counting
-                 * integers, like persons or hits on a web page, decimals should
-                 * be avoided in the labels.
-                 *
-                 * @see [minTickInterval](#xAxis.minTickInterval)
-                 *
-                 * @sample {highcharts|highstock} highcharts/yaxis/allowdecimals-true/
-                 *         True by default
-                 * @sample {highcharts|highstock} highcharts/yaxis/allowdecimals-false/
-                 *         False
-                 *
-                 * @type      {boolean}
-                 * @default   true
-                 * @since     2.0
-                 * @apioption xAxis.allowDecimals
-                 */
-                /**
-                 * When using an alternate grid color, a band is painted across the
-                 * plot area between every other grid line.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/alternategridcolor/
-                 *         Alternate grid color on the Y axis
-                 * @sample {highstock} stock/xaxis/alternategridcolor/
-                 *         Alternate grid color on the Y axis
-                 *
-                 * @type      {Highcharts.ColorType}
-                 * @apioption xAxis.alternateGridColor
-                 */
-                /**
-                 * An array defining breaks in the axis, the sections defined will be
-                 * left out and all the points shifted closer to each other.
-                 *
-                 * @productdesc {highcharts}
-                 * Requires that the broken-axis.js module is loaded.
-                 *
-                 * @sample {highcharts} highcharts/axisbreak/break-simple/
-                 *         Simple break
-                 * @sample {highcharts|highstock} highcharts/axisbreak/break-visualized/
-                 *         Advanced with callback
-                 * @sample {highstock} stock/demo/intraday-breaks/
-                 *         Break on nights and weekends
-                 *
-                 * @type      {Array<*>}
-                 * @since     4.1.0
-                 * @product   highcharts highstock gantt
-                 * @apioption xAxis.breaks
-                 */
-                /**
-                 * A number indicating how much space should be left between the start
-                 * and the end of the break. The break size is given in axis units,
-                 * so for instance on a `datetime` axis, a break size of 3600000 would
-                 * indicate the equivalent of an hour.
-                 *
-                 * @type      {number}
-                 * @default   0
-                 * @since     4.1.0
-                 * @product   highcharts highstock gantt
-                 * @apioption xAxis.breaks.breakSize
-                 */
-                /**
-                 * The point where the break starts.
-                 *
-                 * @type      {number}
-                 * @since     4.1.0
-                 * @product   highcharts highstock gantt
-                 * @apioption xAxis.breaks.from
-                 */
-                /**
-                 * Defines an interval after which the break appears again. By default
-                 * the breaks do not repeat.
-                 *
-                 * @type      {number}
-                 * @default   0
-                 * @since     4.1.0
-                 * @product   highcharts highstock gantt
-                 * @apioption xAxis.breaks.repeat
-                 */
-                /**
-                 * The point where the break ends.
-                 *
-                 * @type      {number}
-                 * @since     4.1.0
-                 * @product   highcharts highstock gantt
-                 * @apioption xAxis.breaks.to
-                 */
-                /**
-                 * If categories are present for the xAxis, names are used instead of
-                 * numbers for that axis.
-                 *
-                 * Since Highcharts 3.0, categories can also
-                 * be extracted by giving each point a [name](#series.data) and setting
-                 * axis [type](#xAxis.type) to `category`. However, if you have multiple
-                 * series, best practice remains defining the `categories` array.
-                 *
-                 * Example: `categories: ['Apples', 'Bananas', 'Oranges']`
-                 *
-                 * @sample {highcharts} highcharts/demo/line-labels/
-                 *         With
-                 * @sample {highcharts} highcharts/xaxis/categories/
-                 *         Without
-                 *
-                 * @type      {Array<string>}
-                 * @product   highcharts gantt
-                 * @apioption xAxis.categories
-                 */
-                /**
-                 * The highest allowed value for automatically computed axis extremes.
-                 *
-                 * @see [floor](#xAxis.floor)
-                 *
-                 * @sample {highcharts|highstock} highcharts/yaxis/floor-ceiling/
-                 *         Floor and ceiling
-                 *
-                 * @type       {number}
-                 * @since      4.0
-                 * @product    highcharts highstock gantt
-                 * @apioption  xAxis.ceiling
-                 */
-                /**
-                 * A class name that opens for styling the axis by CSS, especially in
-                 * Highcharts styled mode. The class name is applied to group elements
-                 * for the grid, axis elements and labels.
-                 *
-                 * @sample {highcharts|highstock|highmaps} highcharts/css/axis/
-                 *         Multiple axes with separate styling
-                 *
-                 * @type      {string}
-                 * @since     5.0.0
-                 * @apioption xAxis.className
-                 */
-                /**
-                 * Configure a crosshair that follows either the mouse pointer or the
-                 * hovered point.
-                 *
-                 * In styled mode, the crosshairs are styled in the
-                 * `.highcharts-crosshair`, `.highcharts-crosshair-thin` or
-                 * `.highcharts-xaxis-category` classes.
-                 *
-                 * @productdesc {highstock}
-                 * In Highstock, by default, the crosshair is enabled on the X axis and
-                 * disabled on the Y axis.
-                 *
-                 * @sample {highcharts} highcharts/xaxis/crosshair-both/
-                 *         Crosshair on both axes
-                 * @sample {highstock} stock/xaxis/crosshairs-xy/
-                 *         Crosshair on both axes
-                 * @sample {highmaps} highcharts/xaxis/crosshair-both/
-                 *         Crosshair on both axes
-                 *
-                 * @declare   Highcharts.AxisCrosshairOptions
-                 * @type      {boolean|*}
-                 * @default   false
-                 * @since     4.1
-                 * @apioption xAxis.crosshair
-                 */
-                /**
-                 * A class name for the crosshair, especially as a hook for styling.
-                 *
-                 * @type      {string}
-                 * @since     5.0.0
-                 * @apioption xAxis.crosshair.className
-                 */
-                /**
-                 * The color of the crosshair. Defaults to `#cccccc` for numeric and
-                 * datetime axes, and `rgba(204,214,235,0.25)` for category axes, where
-                 * the crosshair by default highlights the whole category.
-                 *
-                 * @sample {highcharts|highstock|highmaps} highcharts/xaxis/crosshair-customized/
-                 *         Customized crosshairs
-                 *
-                 * @type      {Highcharts.ColorType}
-                 * @default   #cccccc
-                 * @since     4.1
-                 * @apioption xAxis.crosshair.color
-                 */
-                /**
-                 * The dash style for the crosshair. See
-                 * [plotOptions.series.dashStyle](#plotOptions.series.dashStyle)
-                 * for possible values.
-                 *
-                 * @sample {highcharts|highmaps} highcharts/xaxis/crosshair-dotted/
-                 *         Dotted crosshair
-                 * @sample {highstock} stock/xaxis/crosshair-dashed/
-                 *         Dashed X axis crosshair
-                 *
-                 * @type      {Highcharts.DashStyleValue}
-                 * @default   Solid
-                 * @since     4.1
-                 * @apioption xAxis.crosshair.dashStyle
-                 */
-                /**
-                 * A label on the axis next to the crosshair.
-                 *
-                 * In styled mode, the label is styled with the
-                 * `.highcharts-crosshair-label` class.
-                 *
-                 * @sample {highstock} stock/xaxis/crosshair-label/
-                 *         Crosshair labels
-                 * @sample {highstock} highcharts/css/crosshair-label/
-                 *         Style mode
-                 *
-                 * @declare   Highcharts.AxisCrosshairLabelOptions
-                 * @since     2.1
-                 * @product   highstock
-                 * @apioption xAxis.crosshair.label
-                 */
-                /**
-                 * Alignment of the label compared to the axis. Defaults to `"left"` for
-                 * right-side axes, `"right"` for left-side axes and `"center"` for
-                 * horizontal axes.
-                 *
-                 * @type      {Highcharts.AlignValue}
-                 * @since     2.1
-                 * @product   highstock
-                 * @apioption xAxis.crosshair.label.align
-                 */
-                /**
-                 * The background color for the label. Defaults to the related series
-                 * color, or `#666666` if that is not available.
-                 *
-                 * @type      {Highcharts.ColorType}
-                 * @since     2.1
-                 * @product   highstock
-                 * @apioption xAxis.crosshair.label.backgroundColor
-                 */
-                /**
-                 * The border color for the crosshair label
-                 *
-                 * @type      {Highcharts.ColorType}
-                 * @since     2.1
-                 * @product   highstock
-                 * @apioption xAxis.crosshair.label.borderColor
-                 */
-                /**
-                 * The border corner radius of the crosshair label.
-                 *
-                 * @type      {number}
-                 * @default   3
-                 * @since     2.1.10
-                 * @product   highstock
-                 * @apioption xAxis.crosshair.label.borderRadius
-                 */
-                /**
-                 * The border width for the crosshair label.
-                 *
-                 * @type      {number}
-                 * @default   0
-                 * @since     2.1
-                 * @product   highstock
-                 * @apioption xAxis.crosshair.label.borderWidth
-                 */
-                /**
-                 * Flag to enable crosshair's label.
-                 *
-                 * @sample {highstock} stock/xaxis/crosshairs-xy/
-                 *         Enabled label for yAxis' crosshair
-                 *
-                 * @type      {boolean}
-                 * @default   false
-                 * @since     2.1
-                 * @product   highstock
-                 * @apioption xAxis.crosshair.label.enabled
-                 */
-                /**
-                 * A format string for the crosshair label. Defaults to `{value}` for
-                 * numeric axes and `{value:%b %d, %Y}` for datetime axes.
-                 *
-                 * @type      {string}
-                 * @since     2.1
-                 * @product   highstock
-                 * @apioption xAxis.crosshair.label.format
-                 */
-                /**
-                 * Formatter function for the label text.
-                 *
-                 * @type      {Highcharts.XAxisCrosshairLabelFormatterCallbackFunction}
-                 * @since     2.1
-                 * @product   highstock
-                 * @apioption xAxis.crosshair.label.formatter
-                 */
-                /**
-                 * Padding inside the crosshair label.
-                 *
-                 * @type      {number}
-                 * @default   8
-                 * @since     2.1
-                 * @product   highstock
-                 * @apioption xAxis.crosshair.label.padding
-                 */
-                /**
-                 * The shape to use for the label box.
-                 *
-                 * @type      {string}
-                 * @default   callout
-                 * @since     2.1
-                 * @product   highstock
-                 * @apioption xAxis.crosshair.label.shape
-                 */
-                /**
-                 * Text styles for the crosshair label.
-                 *
-                 * @type      {Highcharts.CSSObject}
-                 * @default   {"color": "white", "fontWeight": "normal", "fontSize": "11px", "textAlign": "center"}
-                 * @since     2.1
-                 * @product   highstock
-                 * @apioption xAxis.crosshair.label.style
-                 */
-                /**
-                 * Whether the crosshair should snap to the point or follow the pointer
-                 * independent of points.
-                 *
-                 * @sample {highcharts|highstock} highcharts/xaxis/crosshair-snap-false/
-                 *         True by default
-                 * @sample {highmaps} maps/demo/latlon-advanced/
-                 *         Snap is false
-                 *
-                 * @type      {boolean}
-                 * @default   true
-                 * @since     4.1
-                 * @apioption xAxis.crosshair.snap
-                 */
-                /**
-                 * The pixel width of the crosshair. Defaults to 1 for numeric or
-                 * datetime axes, and for one category width for category axes.
-                 *
-                 * @sample {highcharts} highcharts/xaxis/crosshair-customized/
-                 *         Customized crosshairs
-                 * @sample {highstock} highcharts/xaxis/crosshair-customized/
-                 *         Customized crosshairs
-                 * @sample {highmaps} highcharts/xaxis/crosshair-customized/
-                 *         Customized crosshairs
-                 *
-                 * @type      {number}
-                 * @default   1
-                 * @since     4.1
-                 * @apioption xAxis.crosshair.width
-                 */
-                /**
-                 * The Z index of the crosshair. Higher Z indices allow drawing the
-                 * crosshair on top of the series or behind the grid lines.
-                 *
-                 * @type      {number}
-                 * @default   2
-                 * @since     4.1
-                 * @apioption xAxis.crosshair.zIndex
-                 */
-                /**
-                 * Whether to zoom axis. If `chart.zoomType` is set, the option allows
-                 * to disable zooming on an individual axis.
-                 *
-                 * @sample {highcharts} highcharts/xaxis/zoomenabled/
-                 *         Zoom enabled is false
-                 *
-                 *
-                 * @type      {boolean}
-                 * @default   enabled
-                 * @apioption xAxis.zoomEnabled
-                 */
-                /**
-                 * For a datetime axis, the scale will automatically adjust to the
-                 * appropriate unit. This member gives the default string
-                 * representations used for each unit. For intermediate values,
-                 * different units may be used, for example the `day` unit can be used
-                 * on midnight and `hour` unit be used for intermediate values on the
-                 * same axis.
-                 *
-                 * For an overview of the replacement codes, see
-                 * [dateFormat](/class-reference/Highcharts#dateFormat).
-                 *
-                 * Defaults to:
-                 * ```js
-                 * {
-                 *     millisecond: '%H:%M:%S.%L',
-                 *     second: '%H:%M:%S',
-                 *     minute: '%H:%M',
-                 *     hour: '%H:%M',
-                 *     day: '%e. %b',
-                 *     week: '%e. %b',
-                 *     month: '%b \'%y',
-                 *     year: '%Y'
-                 * }
-                 * ```
-                 *
-                 * @sample {highcharts} highcharts/xaxis/datetimelabelformats/
-                 *         Different day format on X axis
-                 * @sample {highstock} stock/xaxis/datetimelabelformats/
-                 *         More information in x axis labels
-                 *
-                 * @declare Highcharts.AxisDateTimeLabelFormatsOptions
-                 * @product highcharts highstock gantt
-                 */
-                dateTimeLabelFormats: {
-                    /**
-                     * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject
-                     * @type {string|*}
-                     */
-                    millisecond: {
-                        main: '%H:%M:%S.%L',
-                        range: false
-                    },
-                    /**
-                     * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject
-                     * @type {string|*}
-                     */
-                    second: {
-                        main: '%H:%M:%S',
-                        range: false
-                    },
-                    /**
-                     * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject
-                     * @type {string|*}
-                     */
-                    minute: {
-                        main: '%H:%M',
-                        range: false
-                    },
-                    /**
-                     * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject
-                     * @type {string|*}
-                     */
-                    hour: {
-                        main: '%H:%M',
-                        range: false
-                    },
-                    /**
-                     * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject
-                     * @type {string|*}
-                     */
-                    day: {
-                        main: '%e. %b'
-                    },
-                    /**
-                     * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject
-                     * @type {string|*}
-                     */
-                    week: {
-                        main: '%e. %b'
-                    },
-                    /**
-                     * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject
-                     * @type {string|*}
-                     */
-                    month: {
-                        main: '%b \'%y'
-                    },
-                    /**
-                     * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject
-                     * @type {string|*}
-                     */
-                    year: {
-                        main: '%Y'
-                    }
-                },
-                /**
-                 * Whether to force the axis to end on a tick. Use this option with
-                 * the `maxPadding` option to control the axis end.
-                 *
-                 * @productdesc {highstock}
-                 * In Highstock, `endOnTick` is always `false` when the navigator
-                 * is enabled, to prevent jumpy scrolling.
-                 *
-                 * @sample {highcharts} highcharts/chart/reflow-true/
-                 *         True by default
-                 * @sample {highcharts} highcharts/yaxis/endontick/
-                 *         False
-                 * @sample {highstock} stock/demo/basic-line/
-                 *         True by default
-                 * @sample {highstock} stock/xaxis/endontick/
-                 *         False
-                 *
-                 * @since 1.2.0
-                 */
-                endOnTick: false,
-                /**
-                 * Event handlers for the axis.
-                 *
-                 * @type      {*}
-                 * @apioption xAxis.events
-                 */
-                /**
-                 * An event fired after the breaks have rendered.
-                 *
-                 * @see [breaks](#xAxis.breaks)
-                 *
-                 * @sample {highcharts} highcharts/axisbreak/break-event/
-                 *         AfterBreak Event
-                 *
-                 * @type      {Highcharts.AxisEventCallbackFunction}
-                 * @since     4.1.0
-                 * @product   highcharts gantt
-                 * @apioption xAxis.events.afterBreaks
-                 */
-                /**
-                 * As opposed to the `setExtremes` event, this event fires after the
-                 * final min and max values are computed and corrected for `minRange`.
-                 *
-                 * Fires when the minimum and maximum is set for the axis, either by
-                 * calling the `.setExtremes()` method or by selecting an area in the
-                 * chart. One parameter, `event`, is passed to the function, containing
-                 * common event information.
-                 *
-                 * The new user set minimum and maximum values can be found by
-                 * `event.min` and `event.max`. These reflect the axis minimum and
-                 * maximum in axis values. The actual data extremes are found in
-                 * `event.dataMin` and `event.dataMax`.
-                 *
-                 * @type      {Highcharts.AxisSetExtremesEventCallbackFunction}
-                 * @since     2.3
-                 * @context   Highcharts.Axis
-                 * @apioption xAxis.events.afterSetExtremes
-                 */
-                /**
-                 * An event fired when a break from this axis occurs on a point.
-                 *
-                 * @see [breaks](#xAxis.breaks)
-                 *
-                 * @sample {highcharts} highcharts/axisbreak/break-visualized/
-                 *         Visualization of a Break
-                 *
-                 * @type      {Highcharts.AxisPointBreakEventCallbackFunction}
-                 * @since     4.1.0
-                 * @product   highcharts gantt
-                 * @context   Highcharts.Axis
-                 * @apioption xAxis.events.pointBreak
-                 */
-                /**
-                 * An event fired when a point falls inside a break from this axis.
-                 *
-                 * @type      {Highcharts.AxisPointBreakEventCallbackFunction}
-                 * @product   highcharts highstock gantt
-                 * @context   Highcharts.Axis
-                 * @apioption xAxis.events.pointInBreak
-                 */
-                /**
-                 * Fires when the minimum and maximum is set for the axis, either by
-                 * calling the `.setExtremes()` method or by selecting an area in the
-                 * chart. One parameter, `event`, is passed to the function,
-                 * containing common event information.
-                 *
-                 * The new user set minimum and maximum values can be found by
-                 * `event.min` and `event.max`. These reflect the axis minimum and
-                 * maximum in data values. When an axis is zoomed all the way out from
-                 * the "Reset zoom" button, `event.min` and `event.max` are null, and
-                 * the new extremes are set based on `this.dataMin` and `this.dataMax`.
-                 *
-                 * @sample {highstock} stock/xaxis/events-setextremes/
-                 *         Log new extremes on x axis
-                 *
-                 * @type      {Highcharts.AxisSetExtremesEventCallbackFunction}
-                 * @since     1.2.0
-                 * @context   Highcharts.Axis
-                 * @apioption xAxis.events.setExtremes
-                 */
-                /**
-                 * The lowest allowed value for automatically computed axis extremes.
-                 *
-                 * @see [ceiling](#yAxis.ceiling)
-                 *
-                 * @sample {highcharts} highcharts/yaxis/floor-ceiling/
-                 *         Floor and ceiling
-                 * @sample {highstock} stock/demo/lazy-loading/
-                 *         Prevent negative stock price on Y axis
-                 *
-                 * @type      {number}
-                 * @since     4.0
-                 * @product   highcharts highstock gantt
-                 * @apioption xAxis.floor
-                 */
-                /**
-                 * The dash or dot style of the grid lines. For possible values, see
-                 * [this demonstration](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/series-dashstyle-all/).
-                 *
-                 * @sample {highcharts} highcharts/yaxis/gridlinedashstyle/
-                 *         Long dashes
-                 * @sample {highstock} stock/xaxis/gridlinedashstyle/
-                 *         Long dashes
-                 *
-                 * @type      {Highcharts.DashStyleValue}
-                 * @default   Solid
-                 * @since     1.2
-                 * @apioption xAxis.gridLineDashStyle
-                 */
-                /**
-                 * The Z index of the grid lines.
-                 *
-                 * @sample {highcharts|highstock} highcharts/xaxis/gridzindex/
-                 *         A Z index of 4 renders the grid above the graph
-                 *
-                 * @type      {number}
-                 * @default   1
-                 * @product   highcharts highstock gantt
-                 * @apioption xAxis.gridZIndex
-                 */
-                /**
-                 * An id for the axis. This can be used after render time to get
-                 * a pointer to the axis object through `chart.get()`.
-                 *
-                 * @sample {highcharts} highcharts/xaxis/id/
-                 *         Get the object
-                 * @sample {highstock} stock/xaxis/id/
-                 *         Get the object
-                 *
-                 * @type      {string}
-                 * @since     1.2.0
-                 * @apioption xAxis.id
-                 */
-                /**
-                 * The axis labels show the number or category for each tick.
-                 *
-                 * Since v8.0.0: Labels are animated in categorized x-axis with
-                 * updating data if `tickInterval` and `step` is set to 1.
-                 *
-                 * @productdesc {highmaps}
-                 * X and Y axis labels are by default disabled in Highmaps, but the
-                 * functionality is inherited from Highcharts and used on `colorAxis`,
-                 * and can be enabled on X and Y axes too.
-                 */
-                labels: {
-                    /**
-                     * What part of the string the given position is anchored to.
-                     * If `left`, the left side of the string is at the axis position.
-                     * Can be one of `"left"`, `"center"` or `"right"`. Defaults to
-                     * an intelligent guess based on which side of the chart the axis
-                     * is on and the rotation of the label.
-                     *
-                     * @see [reserveSpace](#xAxis.labels.reserveSpace)
-                     *
-                     * @sample {highcharts} highcharts/xaxis/labels-align-left/
-                     *         Left
-                     * @sample {highcharts} highcharts/xaxis/labels-align-right/
-                     *         Right
-                     * @sample {highcharts} highcharts/xaxis/labels-reservespace-true/
-                     *         Left-aligned labels on a vertical category axis
-                     *
-                     * @type       {Highcharts.AlignValue}
-                     * @apioption  xAxis.labels.align
-                     */
-                    /**
-                     * For horizontal axes, the allowed degrees of label rotation
-                     * to prevent overlapping labels. If there is enough space,
-                     * labels are not rotated. As the chart gets narrower, it
-                     * will start rotating the labels -45 degrees, then remove
-                     * every second label and try again with rotations 0 and -45 etc.
-                     * Set it to `false` to disable rotation, which will
-                     * cause the labels to word-wrap if possible.
-                     *
-                     * @sample {highcharts|highstock} highcharts/xaxis/labels-autorotation-default/
-                     *         Default auto rotation of 0 or -45
-                     * @sample {highcharts|highstock} highcharts/xaxis/labels-autorotation-0-90/
-                     *         Custom graded auto rotation
-                     *
-                     * @type      {Array<number>|false}
-                     * @default   [-45]
-                     * @since     4.1.0
-                     * @product   highcharts highstock gantt
-                     * @apioption xAxis.labels.autoRotation
-                     */
-                    /**
-                     * When each category width is more than this many pixels, we don't
-                     * apply auto rotation. Instead, we lay out the axis label with word
-                     * wrap. A lower limit makes sense when the label contains multiple
-                     * short words that don't extend the available horizontal space for
-                     * each label.
-                     *
-                     * @sample {highcharts} highcharts/xaxis/labels-autorotationlimit/
-                     *         Lower limit
-                     *
-                     * @type      {number}
-                     * @default   80
-                     * @since     4.1.5
-                     * @product   highcharts gantt
-                     * @apioption xAxis.labels.autoRotationLimit
-                     */
-                    /**
-                     * Polar charts only. The label's pixel distance from the perimeter
-                     * of the plot area.
-                     *
-                     * @type      {number}
-                     * @default   15
-                     * @product   highcharts gantt
-                     * @apioption xAxis.labels.distance
-                     */
-                    /**
-                     * Enable or disable the axis labels.
-                     *
-                     * @sample {highcharts} highcharts/xaxis/labels-enabled/
-                     *         X axis labels disabled
-                     * @sample {highstock} stock/xaxis/labels-enabled/
-                     *         X axis labels disabled
-                     *
-                     * @default {highcharts|highstock|gantt} true
-                     * @default {highmaps} false
-                     */
-                    enabled: true,
-                    /**
-                     * A [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting)
-                     * for the axis label.
-                     *
-                     * @sample {highcharts|highstock} highcharts/yaxis/labels-format/
-                     *         Add units to Y axis label
-                     *
-                     * @type      {string}
-                     * @default   {value}
-                     * @since     3.0
-                     * @apioption xAxis.labels.format
-                     */
-                    /**
-                     * Callback JavaScript function to format the label. The value
-                     * is given by `this.value`. Additional properties for `this` are
-                     * `axis`, `chart`, `isFirst` and `isLast`. The value of the default
-                     * label formatter can be retrieved by calling
-                     * `this.axis.defaultLabelFormatter.call(this)` within the function.
-                     *
-                     * Defaults to:
-                     * ```js
-                     * function() {
-                     *     return this.value;
-                     * }
-                     * ```
-                     *
-                     * @sample {highcharts} highcharts/xaxis/labels-formatter-linked/
-                     *         Linked category names
-                     * @sample {highcharts} highcharts/xaxis/labels-formatter-extended/
-                     *         Modified numeric labels
-                     * @sample {highstock} stock/xaxis/labels-formatter/
-                     *         Added units on Y axis
-                     *
-                     * @type      {Highcharts.AxisLabelsFormatterCallbackFunction}
-                     * @apioption xAxis.labels.formatter
-                     */
-                    /**
-                     * The number of pixels to indent the labels per level in a treegrid
-                     * axis.
-                     *
-                     * @sample gantt/treegrid-axis/demo
-                     *         Indentation 10px by default.
-                     * @sample gantt/treegrid-axis/indentation-0px
-                     *         Indentation set to 0px.
-                     *
-                     * @product gantt
-                     */
-                    indentation: 10,
-                    /**
-                     * Horizontal axis only. When `staggerLines` is not set,
-                     * `maxStaggerLines` defines how many lines the axis is allowed to
-                     * add to automatically avoid overlapping X labels. Set to `1` to
-                     * disable overlap detection.
-                     *
-                     * @deprecated
-                     * @type      {number}
-                     * @default   5
-                     * @since     1.3.3
-                     * @apioption xAxis.labels.maxStaggerLines
-                     */
-                    /**
-                     * How to handle overflowing labels on horizontal axis. If set to
-                     * `"allow"`, it will not be aligned at all. By default it
-                     * `"justify"` labels inside the chart area. If there is room to
-                     * move it, it will be aligned to the edge, else it will be removed.
-                     *
-                     * @type       {string}
-                     * @default    justify
-                     * @since      2.2.5
-                     * @validvalue ["allow", "justify"]
-                     * @apioption  xAxis.labels.overflow
-                     */
-                    /**
-                     * The pixel padding for axis labels, to ensure white space between
-                     * them.
-                     *
-                     * @type      {number}
-                     * @default   5
-                     * @product   highcharts gantt
-                     * @apioption xAxis.labels.padding
-                     */
-                    /**
-                     * Whether to reserve space for the labels. By default, space is
-                     * reserved for the labels in these cases:
-                     *
-                     * * On all horizontal axes.
-                     * * On vertical axes if `label.align` is `right` on a left-side
-                     * axis or `left` on a right-side axis.
-                     * * On vertical axes if `label.align` is `center`.
-                     *
-                     * This can be turned off when for example the labels are rendered
-                     * inside the plot area instead of outside.
-                     *
-                     * @see [labels.align](#xAxis.labels.align)
-                     *
-                     * @sample {highcharts} highcharts/xaxis/labels-reservespace/
-                     *         No reserved space, labels inside plot
-                     * @sample {highcharts} highcharts/xaxis/labels-reservespace-true/
-                     *         Left-aligned labels on a vertical category axis
-                     *
-                     * @type      {boolean}
-                     * @since     4.1.10
-                     * @product   highcharts gantt
-                     * @apioption xAxis.labels.reserveSpace
-                     */
-                    /**
-                     * Rotation of the labels in degrees.
-                     *
-                     * @sample {highcharts} highcharts/xaxis/labels-rotation/
-                     *         X axis labels rotated 90°
-                     *
-                     * @type      {number}
-                     * @default   0
-                     * @apioption xAxis.labels.rotation
-                     */
-                    /**
-                     * Horizontal axes only. The number of lines to spread the labels
-                     * over to make room or tighter labels.
-                     *
-                     * @sample {highcharts} highcharts/xaxis/labels-staggerlines/
-                     *         Show labels over two lines
-                     * @sample {highstock} stock/xaxis/labels-staggerlines/
-                     *         Show labels over two lines
-                     *
-                     * @type      {number}
-                     * @since     2.1
-                     * @apioption xAxis.labels.staggerLines
-                     */
-                    /**
-                     * To show only every _n_'th label on the axis, set the step to _n_.
-                     * Setting the step to 2 shows every other label.
-                     *
-                     * By default, the step is calculated automatically to avoid
-                     * overlap. To prevent this, set it to 1\. This usually only
-                     * happens on a category axis, and is often a sign that you have
-                     * chosen the wrong axis type.
-                     *
-                     * Read more at
-                     * [Axis docs](https://www.highcharts.com/docs/chart-concepts/axes)
-                     * => What axis should I use?
-                     *
-                     * @sample {highcharts} highcharts/xaxis/labels-step/
-                     *         Showing only every other axis label on a categorized
-                     *         x-axis
-                     * @sample {highcharts} highcharts/xaxis/labels-step-auto/
-                     *         Auto steps on a category axis
-                     *
-                     * @type      {number}
-                     * @since     2.1
-                     * @apioption xAxis.labels.step
-                     */
-                    /**
-                     * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html)
-                     * to render the labels.
-                     *
-                     * @type      {boolean}
-                     * @default   false
-                     * @apioption xAxis.labels.useHTML
-                     */
-                    /**
-                     * The x position offset of all labels relative to the tick
-                     * positions on the axis.
-                     *
-                     * @sample {highcharts} highcharts/xaxis/labels-x/
-                     *         Y axis labels placed on grid lines
-                     */
-                    x: 0,
-                    /**
-                     * The y position offset of all labels relative to the tick
-                     * positions on the axis. The default makes it adapt to the font
-                     * size of the bottom axis.
-                     *
-                     * @sample {highcharts} highcharts/xaxis/labels-x/
-                     *         Y axis labels placed on grid lines
-                     *
-                     * @type      {number}
-                     * @apioption xAxis.labels.y
-                     */
-                    /**
-                     * The Z index for the axis labels.
-                     *
-                     * @type      {number}
-                     * @default   7
-                     * @apioption xAxis.labels.zIndex
-                     */
-                    /**
-                     * CSS styles for the label. Use `whiteSpace: 'nowrap'` to prevent
-                     * wrapping of category labels. Use `textOverflow: 'none'` to
-                     * prevent ellipsis (dots).
-                     *
-                     * In styled mode, the labels are styled with the
-                     * `.highcharts-axis-labels` class.
-                     *
-                     * @sample {highcharts} highcharts/xaxis/labels-style/
-                     *         Red X axis labels
-                     *
-                     * @type      {Highcharts.CSSObject}
-                     */
-                    style: {
-                        /** @internal */
-                        color: '#666666',
-                        /** @internal */
-                        cursor: 'default',
-                        /** @internal */
-                        fontSize: '11px'
-                    }
-                },
-                /**
-                 * The left position as the horizontal axis. If it's a number, it is
-                 * interpreted as pixel position relative to the chart.
-                 *
-                 * Since Highcharts v5.0.13: If it's a percentage string, it is
-                 * interpreted as percentages of the plot width, offset from plot area
-                 * left.
-                 *
-                 * @type      {number|string}
-                 * @product   highcharts highstock
-                 * @apioption xAxis.left
-                 */
-                /**
-                 * The top position as the vertical axis. If it's a number, it is
-                 * interpreted as pixel position relative to the chart.
-                 *
-                 * Since Highcharts 2: If it's a percentage string, it is interpreted
-                 * as percentages of the plot height, offset from plot area top.
-                 *
-                 * @type      {number|string}
-                 * @product   highcharts highstock
-                 * @apioption xAxis.top
-                 */
-                /**
-                 * Index of another axis that this axis is linked to. When an axis is
-                 * linked to a master axis, it will take the same extremes as
-                 * the master, but as assigned by min or max or by setExtremes.
-                 * It can be used to show additional info, or to ease reading the
-                 * chart by duplicating the scales.
-                 *
-                 * @sample {highcharts} highcharts/xaxis/linkedto/
-                 *         Different string formats of the same date
-                 * @sample {highcharts} highcharts/yaxis/linkedto/
-                 *         Y values on both sides
-                 *
-                 * @type      {number}
-                 * @since     2.0.2
-                 * @product   highcharts highstock gantt
-                 * @apioption xAxis.linkedTo
-                 */
-                /**
-                 * The maximum value of the axis. If `null`, the max value is
-                 * automatically calculated.
-                 *
-                 * If the [endOnTick](#yAxis.endOnTick) option is true, the `max` value
-                 * might be rounded up.
-                 *
-                 * If a [tickAmount](#yAxis.tickAmount) is set, the axis may be extended
-                 * beyond the set max in order to reach the given number of ticks. The
-                 * same may happen in a chart with multiple axes, determined by [chart.
-                 * alignTicks](#chart), where a `tickAmount` is applied internally.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/max-200/
-                 *         Y axis max of 200
-                 * @sample {highcharts} highcharts/yaxis/max-logarithmic/
-                 *         Y axis max on logarithmic axis
-                 * @sample {highstock} stock/xaxis/min-max/
-                 *         Fixed min and max on X axis
-                 * @sample {highmaps} maps/axis/min-max/
-                 *         Pre-zoomed to a specific area
-                 *
-                 * @type      {number|null}
-                 * @apioption xAxis.max
-                 */
-                /**
-                 * Padding of the max value relative to the length of the axis. A
-                 * padding of 0.05 will make a 100px axis 5px longer. This is useful
-                 * when you don't want the highest data value to appear on the edge
-                 * of the plot area. When the axis' `max` option is set or a max extreme
-                 * is set using `axis.setExtremes()`, the maxPadding will be ignored.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/maxpadding/
-                 *         Max padding of 0.25 on y axis
-                 * @sample {highstock} stock/xaxis/minpadding-maxpadding/
-                 *         Greater min- and maxPadding
-                 * @sample {highmaps} maps/chart/plotbackgroundcolor-gradient/
-                 *         Add some padding
-                 *
-                 * @default   {highcharts} 0.01
-                 * @default   {highstock|highmaps} 0
-                 * @since     1.2.0
-                 */
-                maxPadding: 0.01,
-                /**
-                 * Deprecated. Use `minRange` instead.
-                 *
-                 * @deprecated
-                 * @type      {number}
-                 * @product   highcharts highstock
-                 * @apioption xAxis.maxZoom
-                 */
-                /**
-                 * The minimum value of the axis. If `null` the min value is
-                 * automatically calculated.
-                 *
-                 * If the [startOnTick](#yAxis.startOnTick) option is true (default),
-                 * the `min` value might be rounded down.
-                 *
-                 * The automatically calculated minimum value is also affected by
-                 * [floor](#yAxis.floor), [softMin](#yAxis.softMin),
-                 * [minPadding](#yAxis.minPadding), [minRange](#yAxis.minRange)
-                 * as well as [series.threshold](#plotOptions.series.threshold)
-                 * and [series.softThreshold](#plotOptions.series.softThreshold).
-                 *
-                 * @sample {highcharts} highcharts/yaxis/min-startontick-false/
-                 *         -50 with startOnTick to false
-                 * @sample {highcharts} highcharts/yaxis/min-startontick-true/
-                 *         -50 with startOnTick true by default
-                 * @sample {highstock} stock/xaxis/min-max/
-                 *         Set min and max on X axis
-                 * @sample {highmaps} maps/axis/min-max/
-                 *         Pre-zoomed to a specific area
-                 *
-                 * @type      {number|null}
-                 * @apioption xAxis.min
-                 */
-                /**
-                 * The dash or dot style of the minor grid lines. For possible values,
-                 * see [this demonstration](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/series-dashstyle-all/).
-                 *
-                 * @sample {highcharts} highcharts/yaxis/minorgridlinedashstyle/
-                 *         Long dashes on minor grid lines
-                 * @sample {highstock} stock/xaxis/minorgridlinedashstyle/
-                 *         Long dashes on minor grid lines
-                 *
-                 * @type      {Highcharts.DashStyleValue}
-                 * @default   Solid
-                 * @since     1.2
-                 * @apioption xAxis.minorGridLineDashStyle
-                 */
-                /**
-                 * Specific tick interval in axis units for the minor ticks. On a linear
-                 * axis, if `"auto"`, the minor tick interval is calculated as a fifth
-                 * of the tickInterval. If `null` or `undefined`, minor ticks are not
-                 * shown.
-                 *
-                 * On logarithmic axes, the unit is the power of the value. For example,
-                 * setting the minorTickInterval to 1 puts one tick on each of 0.1, 1,
-                 * 10, 100 etc. Setting the minorTickInterval to 0.1 produces 9 ticks
-                 * between 1 and 10, 10 and 100 etc.
-                 *
-                 * If user settings dictate minor ticks to become too dense, they don't
-                 * make sense, and will be ignored to prevent performance problems.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/minortickinterval-null/
-                 *         Null by default
-                 * @sample {highcharts} highcharts/yaxis/minortickinterval-5/
-                 *         5 units
-                 * @sample {highcharts} highcharts/yaxis/minortickinterval-log-auto/
-                 *         "auto"
-                 * @sample {highcharts} highcharts/yaxis/minortickinterval-log/
-                 *         0.1
-                 * @sample {highstock} stock/demo/basic-line/
-                 *         Null by default
-                 * @sample {highstock} stock/xaxis/minortickinterval-auto/
-                 *         "auto"
-                 *
-                 * @type      {number|string|null}
-                 * @apioption xAxis.minorTickInterval
-                 */
-                /**
-                 * The pixel length of the minor tick marks.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/minorticklength/
-                 *         10px on Y axis
-                 * @sample {highstock} stock/xaxis/minorticks/
-                 *         10px on Y axis
-                 */
-                minorTickLength: 2,
-                /**
-                 * The position of the minor tick marks relative to the axis line.
-                 *  Can be one of `inside` and `outside`.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/minortickposition-outside/
-                 *         Outside by default
-                 * @sample {highcharts} highcharts/yaxis/minortickposition-inside/
-                 *         Inside
-                 * @sample {highstock} stock/xaxis/minorticks/
-                 *         Inside
-                 *
-                 * @validvalue ["inside", "outside"]
-                 */
-                minorTickPosition: 'outside',
-                /**
-                 * Enable or disable minor ticks. Unless
-                 * [minorTickInterval](#xAxis.minorTickInterval) is set, the tick
-                 * interval is calculated as a fifth of the `tickInterval`.
-                 *
-                 * On a logarithmic axis, minor ticks are laid out based on a best
-                 * guess, attempting to enter approximately 5 minor ticks between
-                 * each major tick.
-                 *
-                 * Prior to v6.0.0, ticks were unabled in auto layout by setting
-                 * `minorTickInterval` to `"auto"`.
-                 *
-                 * @productdesc {highcharts}
-                 * On axes using [categories](#xAxis.categories), minor ticks are not
-                 * supported.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/minorticks-true/
-                 *         Enabled on linear Y axis
-                 *
-                 * @type      {boolean}
-                 * @default   false
-                 * @since     6.0.0
-                 * @apioption xAxis.minorTicks
-                 */
-                /**
-                 * The pixel width of the minor tick mark.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/minortickwidth/
-                 *         3px width
-                 * @sample {highstock} stock/xaxis/minorticks/
-                 *         1px width
-                 *
-                 * @type      {number}
-                 * @default   0
-                 * @apioption xAxis.minorTickWidth
-                 */
-                /**
-                 * Padding of the min value relative to the length of the axis. A
-                 * padding of 0.05 will make a 100px axis 5px longer. This is useful
-                 * when you don't want the lowest data value to appear on the edge
-                 * of the plot area. When the axis' `min` option is set or a min extreme
-                 * is set using `axis.setExtremes()`, the minPadding will be ignored.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/minpadding/
-                 *         Min padding of 0.2
-                 * @sample {highstock} stock/xaxis/minpadding-maxpadding/
-                 *         Greater min- and maxPadding
-                 * @sample {highmaps} maps/chart/plotbackgroundcolor-gradient/
-                 *         Add some padding
-                 *
-                 * @default    {highcharts} 0.01
-                 * @default    {highstock|highmaps} 0
-                 * @since      1.2.0
-                 * @product    highcharts highstock gantt
-                 */
-                minPadding: 0.01,
-                /**
-                 * The minimum range to display on this axis. The entire axis will not
-                 * be allowed to span over a smaller interval than this. For example,
-                 * for a datetime axis the main unit is milliseconds. If minRange is
-                 * set to 3600000, you can't zoom in more than to one hour.
-                 *
-                 * The default minRange for the x axis is five times the smallest
-                 * interval between any of the data points.
-                 *
-                 * On a logarithmic axis, the unit for the minimum range is the power.
-                 * So a minRange of 1 means that the axis can be zoomed to 10-100,
-                 * 100-1000, 1000-10000 etc.
-                 *
-                 * **Note**: The `minPadding`, `maxPadding`, `startOnTick` and
-                 * `endOnTick` settings also affect how the extremes of the axis
-                 * are computed.
-                 *
-                 * @sample {highcharts} highcharts/xaxis/minrange/
-                 *         Minimum range of 5
-                 * @sample {highstock} stock/xaxis/minrange/
-                 *         Max zoom of 6 months overrides user selections
-                 * @sample {highmaps} maps/axis/minrange/
-                 *         Minimum range of 1000
-                 *
-                 * @type      {number}
-                 * @apioption xAxis.minRange
-                 */
-                /**
-                 * The minimum tick interval allowed in axis values. For example on
-                 * zooming in on an axis with daily data, this can be used to prevent
-                 * the axis from showing hours. Defaults to the closest distance between
-                 * two points on the axis.
-                 *
-                 * @type      {number}
-                 * @since     2.3.0
-                 * @apioption xAxis.minTickInterval
-                 */
-                /**
-                 * The distance in pixels from the plot area to the axis line.
-                 * A positive offset moves the axis with it's line, labels and ticks
-                 * away from the plot area. This is typically used when two or more
-                 * axes are displayed on the same side of the plot. With multiple
-                 * axes the offset is dynamically adjusted to avoid collision, this
-                 * can be overridden by setting offset explicitly.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/offset/
-                 *         Y axis offset of 70
-                 * @sample {highcharts} highcharts/yaxis/offset-centered/
-                 *         Axes positioned in the center of the plot
-                 * @sample {highstock} stock/xaxis/offset/
-                 *         Y axis offset by 70 px
-                 *
-                 * @type      {number}
-                 * @default   0
-                 * @apioption xAxis.offset
-                 */
-                /**
-                 * Whether to display the axis on the opposite side of the normal. The
-                 * normal is on the left side for vertical axes and bottom for
-                 * horizontal, so the opposite sides will be right and top respectively.
-                 * This is typically used with dual or multiple axes.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/opposite/
-                 *         Secondary Y axis opposite
-                 * @sample {highstock} stock/xaxis/opposite/
-                 *         Y axis on left side
-                 *
-                 * @type      {boolean}
-                 * @default   {highcharts|highstock|highmaps} false
-                 * @default   {gantt} true
-                 * @apioption xAxis.opposite
-                 */
-                /**
-                 * In an ordinal axis, the points are equally spaced in the chart
-                 * regardless of the actual time or x distance between them. This means
-                 * that missing data periods (e.g. nights or weekends for a stock chart)
-                 * will not take up space in the chart.
-                 * Having `ordinal: false` will show any gaps created by the `gapSize`
-                 * setting proportionate to their duration.
-                 *
-                 * In stock charts the X axis is ordinal by default, unless
-                 * the boost module is used and at least one of the series' data length
-                 * exceeds the [boostThreshold](#series.line.boostThreshold).
-                 *
-                 * @sample {highstock} stock/xaxis/ordinal-true/
-                 *         True by default
-                 * @sample {highstock} stock/xaxis/ordinal-false/
-                 *         False
-                 *
-                 * @type      {boolean}
-                 * @default   true
-                 * @since     1.1
-                 * @product   highstock
-                 * @apioption xAxis.ordinal
-                 */
-                /**
-                 * Additional range on the right side of the xAxis. Works similar to
-                 * `xAxis.maxPadding`, but value is set in milliseconds. Can be set for
-                 * both main `xAxis` and the navigator's `xAxis`.
-                 *
-                 * @sample {highstock} stock/xaxis/overscroll/
-                 *         One minute overscroll with live data
-                 *
-                 * @type      {number}
-                 * @default   0
-                 * @since     6.0.0
-                 * @product   highstock
-                 * @apioption xAxis.overscroll
-                 */
-                /**
-                 * Refers to the index in the [panes](#panes) array. Used for circular
-                 * gauges and polar charts. When the option is not set then first pane
-                 * will be used.
-                 *
-                 * @sample highcharts/demo/gauge-vu-meter
-                 *         Two gauges with different center
-                 *
-                 * @type      {number}
-                 * @product   highcharts
-                 * @apioption xAxis.pane
-                 */
-                /**
-                 * The zoomed range to display when only defining one or none of `min`
-                 * or `max`. For example, to show the latest month, a range of one month
-                 * can be set.
-                 *
-                 * @sample {highstock} stock/xaxis/range/
-                 *         Setting a zoomed range when the rangeSelector is disabled
-                 *
-                 * @type      {number}
-                 * @product   highstock
-                 * @apioption xAxis.range
-                 */
-                /**
-                 * Whether to reverse the axis so that the highest number is closest
-                 * to the origin. If the chart is inverted, the x axis is reversed by
-                 * default.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/reversed/
-                 *         Reversed Y axis
-                 * @sample {highstock} stock/xaxis/reversed/
-                 *         Reversed Y axis
-                 *
-                 * @type      {boolean}
-                 * @default   false
-                 * @apioption xAxis.reversed
-                 */
-                // reversed: false,
-                /**
-                 * This option determines how stacks should be ordered within a group.
-                 * For example reversed xAxis also reverses stacks, so first series
-                 * comes last in a group. To keep order like for non-reversed xAxis
-                 * enable this option.
-                 *
-                 * @sample {highcharts} highcharts/xaxis/reversedstacks/
-                 *         Reversed stacks comparison
-                 * @sample {highstock} highcharts/xaxis/reversedstacks/
-                 *         Reversed stacks comparison
-                 *
-                 * @type      {boolean}
-                 * @default   false
-                 * @since     6.1.1
-                 * @product   highcharts highstock
-                 * @apioption xAxis.reversedStacks
-                 */
-                /**
-                 * An optional scrollbar to display on the X axis in response to
-                 * limiting the minimum and maximum of the axis values.
-                 *
-                 * In styled mode, all the presentational options for the scrollbar are
-                 * replaced by the classes `.highcharts-scrollbar-thumb`,
-                 * `.highcharts-scrollbar-arrow`, `.highcharts-scrollbar-button`,
-                 * `.highcharts-scrollbar-rifles` and `.highcharts-scrollbar-track`.
-                 *
-                 * @sample {highstock} stock/yaxis/heatmap-scrollbars/
-                 *         Heatmap with both scrollbars
-                 *
-                 * @extends   scrollbar
-                 * @since     4.2.6
-                 * @product   highstock
-                 * @apioption xAxis.scrollbar
-                 */
-                /**
-                 * Whether to show the axis line and title when the axis has no data.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/showempty/
-                 *         When clicking the legend to hide series, one axis preserves
-                 *         line and title, the other doesn't
-                 * @sample {highstock} highcharts/yaxis/showempty/
-                 *         When clicking the legend to hide series, one axis preserves
-                 *         line and title, the other doesn't
-                 *
-                 * @since     1.1
-                 */
-                showEmpty: true,
-                /**
-                 * Whether to show the first tick label.
-                 *
-                 * @sample {highcharts} highcharts/xaxis/showfirstlabel-false/
-                 *         Set to false on X axis
-                 * @sample {highstock} stock/xaxis/showfirstlabel/
-                 *         Labels below plot lines on Y axis
-                 *
-                 * @type      {boolean}
-                 * @default   true
-                 * @apioption xAxis.showFirstLabel
-                 */
-                /**
-                 * Whether to show the last tick label. Defaults to `true` on cartesian
-                 * charts, and `false` on polar charts.
-                 *
-                 * @sample {highcharts} highcharts/xaxis/showlastlabel-true/
-                 *         Set to true on X axis
-                 * @sample {highstock} stock/xaxis/showfirstlabel/
-                 *         Labels below plot lines on Y axis
-                 *
-                 * @type      {boolean}
-                 * @default   true
-                 * @product   highcharts highstock gantt
-                 * @apioption xAxis.showLastLabel
-                 */
-                /**
-                 * A soft maximum for the axis. If the series data maximum is less than
-                 * this, the axis will stay at this maximum, but if the series data
-                 * maximum is higher, the axis will flex to show all data.
-                 *
-                 * @sample highcharts/yaxis/softmin-softmax/
-                 *         Soft min and max
-                 *
-                 * @type      {number}
-                 * @since     5.0.1
-                 * @product   highcharts highstock gantt
-                 * @apioption xAxis.softMax
-                 */
-                /**
-                 * A soft minimum for the axis. If the series data minimum is greater
-                 * than this, the axis will stay at this minimum, but if the series
-                 * data minimum is lower, the axis will flex to show all data.
-                 *
-                 * @sample highcharts/yaxis/softmin-softmax/
-                 *         Soft min and max
-                 *
-                 * @type      {number}
-                 * @since     5.0.1
-                 * @product   highcharts highstock gantt
-                 * @apioption xAxis.softMin
-                 */
-                /**
-                 * For datetime axes, this decides where to put the tick between weeks.
-                 *  0 = Sunday, 1 = Monday.
-                 *
-                 * @sample {highcharts} highcharts/xaxis/startofweek-monday/
-                 *         Monday by default
-                 * @sample {highcharts} highcharts/xaxis/startofweek-sunday/
-                 *         Sunday
-                 * @sample {highstock} stock/xaxis/startofweek-1
-                 *         Monday by default
-                 * @sample {highstock} stock/xaxis/startofweek-0
-                 *         Sunday
-                 *
-                 * @product highcharts highstock gantt
-                 */
-                startOfWeek: 1,
-                /**
-                 * Whether to force the axis to start on a tick. Use this option with
-                 * the `minPadding` option to control the axis start.
-                 *
-                 * @productdesc {highstock}
-                 * In Highstock, `startOnTick` is always `false` when the navigator
-                 * is enabled, to prevent jumpy scrolling.
-                 *
-                 * @sample {highcharts} highcharts/xaxis/startontick-false/
-                 *         False by default
-                 * @sample {highcharts} highcharts/xaxis/startontick-true/
-                 *         True
-                 *
-                 * @since 1.2.0
-                 */
-                startOnTick: false,
-                /**
-                 * The amount of ticks to draw on the axis. This opens up for aligning
-                 * the ticks of multiple charts or panes within a chart. This option
-                 * overrides the `tickPixelInterval` option.
-                 *
-                 * This option only has an effect on linear axes. Datetime, logarithmic
-                 * or category axes are not affected.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/tickamount/
-                 *         8 ticks on Y axis
-                 * @sample {highstock} highcharts/yaxis/tickamount/
-                 *         8 ticks on Y axis
-                 *
-                 * @type      {number}
-                 * @since     4.1.0
-                 * @product   highcharts highstock gantt
-                 * @apioption xAxis.tickAmount
-                 */
-                /**
-                 * The interval of the tick marks in axis units. When `undefined`, the
-                 * tick interval is computed to approximately follow the
-                 * [tickPixelInterval](#xAxis.tickPixelInterval) on linear and datetime
-                 * axes. On categorized axes, a `undefined` tickInterval will default to
-                 * 1, one category. Note that datetime axes are based on milliseconds,
-                 * so for example an interval of one day is expressed as
-                 * `24 * 3600 * 1000`.
-                 *
-                 * On logarithmic axes, the tickInterval is based on powers, so a
-                 * tickInterval of 1 means one tick on each of 0.1, 1, 10, 100 etc. A
-                 * tickInterval of 2 means a tick of 0.1, 10, 1000 etc. A tickInterval
-                 * of 0.2 puts a tick on 0.1, 0.2, 0.4, 0.6, 0.8, 1, 2, 4, 6, 8, 10, 20,
-                 * 40 etc.
-                 *
-                 *
-                 * If the tickInterval is too dense for labels to be drawn, Highcharts
-                 * may remove ticks.
-                 *
-                 * If the chart has multiple axes, the [alignTicks](#chart.alignTicks)
-                 * option may interfere with the `tickInterval` setting.
-                 *
-                 * @see [tickPixelInterval](#xAxis.tickPixelInterval)
-                 * @see [tickPositions](#xAxis.tickPositions)
-                 * @see [tickPositioner](#xAxis.tickPositioner)
-                 *
-                 * @sample {highcharts} highcharts/xaxis/tickinterval-5/
-                 *         Tick interval of 5 on a linear axis
-                 * @sample {highstock} stock/xaxis/tickinterval/
-                 *         Tick interval of 0.01 on Y axis
-                 *
-                 * @type      {number}
-                 * @apioption xAxis.tickInterval
-                 */
-                /**
-                 * The pixel length of the main tick marks.
-                 *
-                 * @sample {highcharts} highcharts/xaxis/ticklength/
-                 *         20 px tick length on the X axis
-                 * @sample {highstock} stock/xaxis/ticks/
-                 *         Formatted ticks on X axis
-                 */
-                tickLength: 10,
-                /**
-                 * If tickInterval is `null` this option sets the approximate pixel
-                 * interval of the tick marks. Not applicable to categorized axis.
-                 *
-                 * The tick interval is also influenced by the [minTickInterval](
-                 * #xAxis.minTickInterval) option, that, by default prevents ticks from
-                 * being denser than the data points.
-                 *
-                 * @see [tickInterval](#xAxis.tickInterval)
-                 * @see [tickPositioner](#xAxis.tickPositioner)
-                 * @see [tickPositions](#xAxis.tickPositions)
-                 *
-                 * @sample {highcharts} highcharts/xaxis/tickpixelinterval-50/
-                 *         50 px on X axis
-                 * @sample {highstock} stock/xaxis/tickpixelinterval/
-                 *         200 px on X axis
-                 */
-                tickPixelInterval: 100,
-                /**
-                 * For categorized axes only. If `on` the tick mark is placed in the
-                 * center of the category, if `between` the tick mark is placed between
-                 * categories. The default is `between` if the `tickInterval` is 1, else
-                 * `on`.
-                 *
-                 * @sample {highcharts} highcharts/xaxis/tickmarkplacement-between/
-                 *         "between" by default
-                 * @sample {highcharts} highcharts/xaxis/tickmarkplacement-on/
-                 *         "on"
-                 *
-                 * @product    highcharts gantt
-                 * @validvalue ["on", "between"]
-                 */
-                tickmarkPlacement: 'between',
-                /**
-                 * The position of the major tick marks relative to the axis line.
-                 * Can be one of `inside` and `outside`.
-                 *
-                 * @sample {highcharts} highcharts/xaxis/tickposition-outside/
-                 *         "outside" by default
-                 * @sample {highcharts} highcharts/xaxis/tickposition-inside/
-                 *         "inside"
-                 * @sample {highstock} stock/xaxis/ticks/
-                 *         Formatted ticks on X axis
-                 *
-                 * @validvalue ["inside", "outside"]
-                 */
-                tickPosition: 'outside',
-                /**
-                 * A callback function returning array defining where the ticks are
-                 * laid out on the axis. This overrides the default behaviour of
-                 * [tickPixelInterval](#xAxis.tickPixelInterval) and [tickInterval](
-                 * #xAxis.tickInterval). The automatic tick positions are accessible
-                 * through `this.tickPositions` and can be modified by the callback.
-                 *
-                 * @see [tickPositions](#xAxis.tickPositions)
-                 *
-                 * @sample {highcharts} highcharts/xaxis/tickpositions-tickpositioner/
-                 *         Demo of tickPositions and tickPositioner
-                 * @sample {highstock} highcharts/xaxis/tickpositions-tickpositioner/
-                 *         Demo of tickPositions and tickPositioner
-                 *
-                 * @type      {Highcharts.AxisTickPositionerCallbackFunction}
-                 * @apioption xAxis.tickPositioner
-                 */
-                /**
-                 * An array defining where the ticks are laid out on the axis. This
-                 * overrides the default behaviour of [tickPixelInterval](
-                 * #xAxis.tickPixelInterval) and [tickInterval](#xAxis.tickInterval).
-                 *
-                 * @see [tickPositioner](#xAxis.tickPositioner)
-                 *
-                 * @sample {highcharts} highcharts/xaxis/tickpositions-tickpositioner/
-                 *         Demo of tickPositions and tickPositioner
-                 * @sample {highstock} highcharts/xaxis/tickpositions-tickpositioner/
-                 *         Demo of tickPositions and tickPositioner
-                 *
-                 * @type      {Array<number>}
-                 * @apioption xAxis.tickPositions
-                 */
-                /**
-                 * The pixel width of the major tick marks. Defaults to 0 on category
-                 * axes, otherwise 1.
-                 *
-                 * In styled mode, the stroke width is given in the `.highcharts-tick`
-                 * class, but in order for the element to be generated on category axes,
-                 * the option must be explicitly set to 1.
-                 *
-                 * @sample {highcharts} highcharts/xaxis/tickwidth/
-                 *         10 px width
-                 * @sample {highcharts} highcharts/css/axis-grid/
-                 *         Styled mode
-                 * @sample {highstock} stock/xaxis/ticks/
-                 *         Formatted ticks on X axis
-                 * @sample {highstock} highcharts/css/axis-grid/
-                 *         Styled mode
-                 *
-                 * @type      {undefined|number}
-                 * @default   {highstock} 1
-                 * @default   {highmaps} 0
-                 * @apioption xAxis.tickWidth
-                 */
-                /**
-                 * The axis title, showing next to the axis line.
-                 *
-                 * @productdesc {highmaps}
-                 * In Highmaps, the axis is hidden by default, but adding an axis title
-                 * is still possible. X axis and Y axis titles will appear at the bottom
-                 * and left by default.
-                 */
-                title: {
-                    /**
-                     * Deprecated. Set the `text` to `null` to disable the title.
-                     *
-                     * @deprecated
-                     * @type      {boolean}
-                     * @product   highcharts
-                     * @apioption xAxis.title.enabled
-                     */
-                    /**
-                     * The pixel distance between the axis labels or line and the title.
-                     * Defaults to 0 for horizontal axes, 10 for vertical
-                     *
-                     * @sample {highcharts} highcharts/xaxis/title-margin/
-                     *         Y axis title margin of 60
-                     *
-                     * @type      {number}
-                     * @apioption xAxis.title.margin
-                     */
-                    /**
-                     * The distance of the axis title from the axis line. By default,
-                     * this distance is computed from the offset width of the labels,
-                     * the labels' distance from the axis and the title's margin.
-                     * However when the offset option is set, it overrides all this.
-                     *
-                     * @sample {highcharts} highcharts/yaxis/title-offset/
-                     *         Place the axis title on top of the axis
-                     * @sample {highstock} highcharts/yaxis/title-offset/
-                     *         Place the axis title on top of the Y axis
-                     *
-                     * @type      {number}
-                     * @since     2.2.0
-                     * @apioption xAxis.title.offset
-                     */
-                    /**
-                     * Whether to reserve space for the title when laying out the axis.
-                     *
-                     * @type      {boolean}
-                     * @default   true
-                     * @since     5.0.11
-                     * @product   highcharts highstock gantt
-                     * @apioption xAxis.title.reserveSpace
-                     */
-                    /**
-                     * The rotation of the text in degrees. 0 is horizontal, 270 is
-                     * vertical reading from bottom to top.
-                     *
-                     * @sample {highcharts} highcharts/yaxis/title-offset/
-                     *         Horizontal
-                     *
-                     * @type      {number}
-                     * @default   0
-                     * @apioption xAxis.title.rotation
-                     */
-                    /**
-                     * The actual text of the axis title. It can contain basic HTML tags
-                     * like `b`, `i` and `span` with style.
-                     *
-                     * @sample {highcharts} highcharts/xaxis/title-text/
-                     *         Custom HTML
-                     * @sample {highstock} stock/xaxis/title-text/
-                     *         Titles for both axes
-                     *
-                     * @type      {string|null}
-                     * @apioption xAxis.title.text
-                     */
-                    /**
-                     * Alignment of the text, can be `"left"`, `"right"` or `"center"`.
-                     * Default alignment depends on the
-                     * [title.align](xAxis.title.align):
-                     *
-                     * Horizontal axes:
-                     * - for `align` = `"low"`, `textAlign` is set to `left`
-                     * - for `align` = `"middle"`, `textAlign` is set to `center`
-                     * - for `align` = `"high"`, `textAlign` is set to `right`
-                     *
-                     * Vertical axes:
-                     * - for `align` = `"low"` and `opposite` = `true`, `textAlign` is
-                     *   set to `right`
-                     * - for `align` = `"low"` and `opposite` = `false`, `textAlign` is
-                     *   set to `left`
-                     * - for `align` = `"middle"`, `textAlign` is set to `center`
-                     * - for `align` = `"high"` and `opposite` = `true` `textAlign` is
-                     *   set to `left`
-                     * - for `align` = `"high"` and `opposite` = `false` `textAlign` is
-                     *   set to `right`
-                     *
-                     * @type      {Highcharts.AlignValue}
-                     * @apioption xAxis.title.textAlign
-                     */
-                    /**
-                     * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html)
-                     * to render the axis title.
-                     *
-                     * @type      {boolean}
-                     * @default   false
-                     * @product   highcharts highstock gantt
-                     * @apioption xAxis.title.useHTML
-                     */
-                    /**
-                     * Horizontal pixel offset of the title position.
-                     *
-                     * @type      {number}
-                     * @default   0
-                     * @since     4.1.6
-                     * @product   highcharts highstock gantt
-                     * @apioption xAxis.title.x
-                     */
-                    /**
-                     * Vertical pixel offset of the title position.
-                     *
-                     * @type      {number}
-                     * @product   highcharts highstock gantt
-                     * @apioption xAxis.title.y
-                     */
-                    /**
-                     * Alignment of the title relative to the axis values. Possible
-                     * values are "low", "middle" or "high".
-                     *
-                     * @sample {highcharts} highcharts/xaxis/title-align-low/
-                     *         "low"
-                     * @sample {highcharts} highcharts/xaxis/title-align-center/
-                     *         "middle" by default
-                     * @sample {highcharts} highcharts/xaxis/title-align-high/
-                     *         "high"
-                     * @sample {highcharts} highcharts/yaxis/title-offset/
-                     *         Place the Y axis title on top of the axis
-                     * @sample {highstock} stock/xaxis/title-align/
-                     *         Aligned to "high" value
-                     *
-                     * @type {Highcharts.AxisTitleAlignValue}
-                     */
-                    align: 'middle',
-                    /**
-                     * CSS styles for the title. If the title text is longer than the
-                     * axis length, it will wrap to multiple lines by default. This can
-                     * be customized by setting `textOverflow: 'ellipsis'`, by
-                     * setting a specific `width` or by setting `whiteSpace: 'nowrap'`.
-                     *
-                     * In styled mode, the stroke width is given in the
-                     * `.highcharts-axis-title` class.
-                     *
-                     * @sample {highcharts} highcharts/xaxis/title-style/
-                     *         Red
-                     * @sample {highcharts} highcharts/css/axis/
-                     *         Styled mode
-                     *
-                     * @type    {Highcharts.CSSObject}
-                     */
-                    style: {
-                        /** @internal */
-                        color: '#666666'
-                    }
-                },
-                /**
-                 * The type of axis. Can be one of `linear`, `logarithmic`, `datetime`
-                 * or `category`. In a datetime axis, the numbers are given in
-                 * milliseconds, and tick marks are placed on appropriate values like
-                 * full hours or days. In a category axis, the
-                 * [point names](#series.line.data.name) of the chart's series are used
-                 * for categories, if not a [categories](#xAxis.categories) array is
-                 * defined.
-                 *
-                 * @sample {highcharts} highcharts/xaxis/type-linear/
-                 *         Linear
-                 * @sample {highcharts} highcharts/yaxis/type-log/
-                 *         Logarithmic
-                 * @sample {highcharts} highcharts/yaxis/type-log-minorgrid/
-                 *         Logarithmic with minor grid lines
-                 * @sample {highcharts} highcharts/xaxis/type-log-both/
-                 *         Logarithmic on two axes
-                 * @sample {highcharts} highcharts/yaxis/type-log-negative/
-                 *         Logarithmic with extension to emulate negative values
-                 *
-                 * @type    {Highcharts.AxisTypeValue}
-                 * @product highcharts gantt
-                 */
-                type: 'linear',
-                /**
-                 * If there are multiple axes on the same side of the chart, the pixel
-                 * margin between the axes. Defaults to 0 on vertical axes, 15 on
-                 * horizontal axes.
-                 *
-                 * @type      {number}
-                 * @since     7.0.3
-                 * @apioption xAxis.margin
-                 */
-                /**
-                 * Applies only when the axis `type` is `category`. When `uniqueNames`
-                 * is true, points are placed on the X axis according to their names.
-                 * If the same point name is repeated in the same or another series,
-                 * the point is placed on the same X position as other points of the
-                 * same name. When `uniqueNames` is false, the points are laid out in
-                 * increasing X positions regardless of their names, and the X axis
-                 * category will take the name of the last point in each position.
-                 *
-                 * @sample {highcharts} highcharts/xaxis/uniquenames-true/
-                 *         True by default
-                 * @sample {highcharts} highcharts/xaxis/uniquenames-false/
-                 *         False
-                 *
-                 * @type      {boolean}
-                 * @default   true
-                 * @since     4.2.7
-                 * @product   highcharts gantt
-                 * @apioption xAxis.uniqueNames
-                 */
-                /**
-                 * Datetime axis only. An array determining what time intervals the
-                 * ticks are allowed to fall on. Each array item is an array where the
-                 * first value is the time unit and the second value another array of
-                 * allowed multiples.
-                 *
-                 * Defaults to:
-                 * ```js
-                 * units: [[
-                 *     'millisecond', // unit name
-                 *     [1, 2, 5, 10, 20, 25, 50, 100, 200, 500] // allowed multiples
-                 * ], [
-                 *     'second',
-                 *     [1, 2, 5, 10, 15, 30]
-                 * ], [
-                 *     'minute',
-                 *     [1, 2, 5, 10, 15, 30]
-                 * ], [
-                 *     'hour',
-                 *     [1, 2, 3, 4, 6, 8, 12]
-                 * ], [
-                 *     'day',
-                 *     [1]
-                 * ], [
-                 *     'week',
-                 *     [1]
-                 * ], [
-                 *     'month',
-                 *     [1, 3, 6]
-                 * ], [
-                 *     'year',
-                 *     null
-                 * ]]
-                 * ```
-                 *
-                 * @type      {Array<Array<string,(Array<number>|null)>>}
-                 * @product   highcharts highstock gantt
-                 * @apioption xAxis.units
-                 */
-                /**
-                 * Whether axis, including axis title, line, ticks and labels, should
-                 * be visible.
-                 *
-                 * @type      {boolean}
-                 * @default   true
-                 * @since     4.1.9
-                 * @product   highcharts highstock gantt
-                 * @apioption xAxis.visible
-                 */
-                /**
-                 * Color of the minor, secondary grid lines.
-                 *
-                 * In styled mode, the stroke width is given in the
-                 * `.highcharts-minor-grid-line` class.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/minorgridlinecolor/
-                 *         Bright grey lines from Y axis
-                 * @sample {highcharts|highstock} highcharts/css/axis-grid/
-                 *         Styled mode
-                 * @sample {highstock} stock/xaxis/minorgridlinecolor/
-                 *         Bright grey lines from Y axis
-                 *
-                 * @type    {Highcharts.ColorType}
-                 * @default #f2f2f2
-                 */
-                minorGridLineColor: '#f2f2f2',
-                /**
-                 * Width of the minor, secondary grid lines.
-                 *
-                 * In styled mode, the stroke width is given in the
-                 * `.highcharts-grid-line` class.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/minorgridlinewidth/
-                 *         2px lines from Y axis
-                 * @sample {highcharts|highstock} highcharts/css/axis-grid/
-                 *         Styled mode
-                 * @sample {highstock} stock/xaxis/minorgridlinewidth/
-                 *         2px lines from Y axis
-                 */
-                minorGridLineWidth: 1,
-                /**
-                 * Color for the minor tick marks.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/minortickcolor/
-                 *         Black tick marks on Y axis
-                 * @sample {highstock} stock/xaxis/minorticks/
-                 *         Black tick marks on Y axis
-                 *
-                 * @type    {Highcharts.ColorType}
-                 * @default #999999
-                 */
-                minorTickColor: '#999999',
-                /**
-                 * The color of the line marking the axis itself.
-                 *
-                 * In styled mode, the line stroke is given in the
-                 * `.highcharts-axis-line` or `.highcharts-xaxis-line` class.
-                 *
-                 * @productdesc {highmaps}
-                 * In Highmaps, the axis line is hidden by default, because the axis is
-                 * not visible by default.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/linecolor/
-                 *         A red line on Y axis
-                 * @sample {highcharts|highstock} highcharts/css/axis/
-                 *         Axes in styled mode
-                 * @sample {highstock} stock/xaxis/linecolor/
-                 *         A red line on X axis
-                 *
-                 * @type    {Highcharts.ColorType}
-                 * @default #ccd6eb
-                 */
-                lineColor: '#ccd6eb',
-                /**
-                 * The width of the line marking the axis itself.
-                 *
-                 * In styled mode, the stroke width is given in the
-                 * `.highcharts-axis-line` or `.highcharts-xaxis-line` class.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/linecolor/
-                 *         A 1px line on Y axis
-                 * @sample {highcharts|highstock} highcharts/css/axis/
-                 *         Axes in styled mode
-                 * @sample {highstock} stock/xaxis/linewidth/
-                 *         A 2px line on X axis
-                 *
-                 * @default {highcharts|highstock} 1
-                 * @default {highmaps} 0
-                 */
-                lineWidth: 1,
-                /**
-                 * Color of the grid lines extending the ticks across the plot area.
-                 *
-                 * In styled mode, the stroke is given in the `.highcharts-grid-line`
-                 * class.
-                 *
-                 * @productdesc {highmaps}
-                 * In Highmaps, the grid lines are hidden by default.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/gridlinecolor/
-                 *         Green lines
-                 * @sample {highcharts|highstock} highcharts/css/axis-grid/
-                 *         Styled mode
-                 * @sample {highstock} stock/xaxis/gridlinecolor/
-                 *         Green lines
-                 *
-                 * @type    {Highcharts.ColorType}
-                 * @default #e6e6e6
-                 */
-                gridLineColor: '#e6e6e6',
-                // gridLineDashStyle: 'solid',
-                /**
-                 * The width of the grid lines extending the ticks across the plot area.
-                 *
-                 * In styled mode, the stroke width is given in the
-                 * `.highcharts-grid-line` class.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/gridlinewidth/
-                 *         2px lines
-                 * @sample {highcharts|highstock} highcharts/css/axis-grid/
-                 *         Styled mode
-                 * @sample {highstock} stock/xaxis/gridlinewidth/
-                 *         2px lines
-                 *
-                 * @type      {number}
-                 * @default   0
-                 * @apioption xAxis.gridLineWidth
-                 */
-                // gridLineWidth: 0,
-                /**
-                 * The height as the vertical axis. If it's a number, it is
-                 * interpreted as pixels.
-                 *
-                 * Since Highcharts 2: If it's a percentage string, it is interpreted
-                 * as percentages of the total plot height.
-                 *
-                 * @type      {number|string}
-                 * @product   highcharts highstock
-                 * @apioption xAxis.height
-                 */
-                /**
-                 * The width as the horizontal axis. If it's a number, it is interpreted
-                 * as pixels.
-                 *
-                 * Since Highcharts v5.0.13: If it's a percentage string, it is
-                 * interpreted as percentages of the total plot width.
-                 *
-                 * @type      {number|string}
-                 * @product   highcharts highstock
-                 * @apioption xAxis.width
-                 */
-                /**
-                 * Color for the main tick marks.
-                 *
-                 * In styled mode, the stroke is given in the `.highcharts-tick`
-                 * class.
-                 *
-                 * @sample {highcharts} highcharts/xaxis/tickcolor/
-                 *         Red ticks on X axis
-                 * @sample {highcharts|highstock} highcharts/css/axis-grid/
-                 *         Styled mode
-                 * @sample {highstock} stock/xaxis/ticks/
-                 *         Formatted ticks on X axis
-                 *
-                 * @type    {Highcharts.ColorType}
-                 * @default #ccd6eb
-                 */
-                tickColor: '#ccd6eb'
-                // tickWidth: 1
-            };
-            /**
-             * The Y axis or value axis. Normally this is the vertical axis,
-             * though if the chart is inverted this is the horizontal axis.
-             * In case of multiple axes, the yAxis node is an array of
-             * configuration objects.
-             *
-             * See [the Axis object](/class-reference/Highcharts.Axis) for programmatic
-             * access to the axis.
-             *
-             * @type         {*|Array<*>}
-             * @extends      xAxis
-             * @excluding    currentDateIndicator,ordinal,overscroll
-             * @optionparent yAxis
-             *
-             * @private
-             */
-            Axis.defaultYAxisOptions = {
-                /**
-                 * The type of axis. Can be one of `linear`, `logarithmic`, `datetime`,
-                 * `category` or `treegrid`. Defaults to `treegrid` for Gantt charts,
-                 * `linear` for other chart types.
-                 *
-                 * In a datetime axis, the numbers are given in milliseconds, and tick
-                 * marks are placed on appropriate values, like full hours or days. In a
-                 * category or treegrid axis, the [point names](#series.line.data.name)
-                 * of the chart's series are used for categories, if a
-                 * [categories](#xAxis.categories) array is not defined.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/type-log-minorgrid/
-                 *         Logarithmic with minor grid lines
-                 * @sample {highcharts} highcharts/yaxis/type-log-negative/
-                 *         Logarithmic with extension to emulate negative values
-                 * @sample {gantt} gantt/treegrid-axis/demo
-                 *         Treegrid axis
-                 *
-                 * @type      {Highcharts.AxisTypeValue}
-                 * @default   {highcharts} linear
-                 * @default   {gantt} treegrid
-                 * @product   highcharts gantt
-                 * @apioption yAxis.type
-                 */
-                /**
-                 * The height of the Y axis. If it's a number, it is interpreted as
-                 * pixels.
-                 *
-                 * Since Highcharts 2: If it's a percentage string, it is interpreted as
-                 * percentages of the total plot height.
-                 *
-                 * @see [yAxis.top](#yAxis.top)
-                 *
-                 * @sample {highstock} stock/demo/candlestick-and-volume/
-                 *         Percentage height panes
-                 *
-                 * @type      {number|string}
-                 * @product   highcharts highstock
-                 * @apioption yAxis.height
-                 */
-                /**
-                 * Solid gauge only. Unless [stops](#yAxis.stops) are set, the color
-                 * to represent the maximum value of the Y axis.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/mincolor-maxcolor/
-                 *         Min and max colors
-                 *
-                 * @type      {Highcharts.ColorType}
-                 * @default   #003399
-                 * @since     4.0
-                 * @product   highcharts
-                 * @apioption yAxis.maxColor
-                 */
-                /**
-                 * Solid gauge only. Unless [stops](#yAxis.stops) are set, the color
-                 * to represent the minimum value of the Y axis.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/mincolor-maxcolor/
-                 *         Min and max color
-                 *
-                 * @type      {Highcharts.ColorType}
-                 * @default   #e6ebf5
-                 * @since     4.0
-                 * @product   highcharts
-                 * @apioption yAxis.minColor
-                 */
-                /**
-                 * Whether to reverse the axis so that the highest number is closest
-                 * to the origin.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/reversed/
-                 *         Reversed Y axis
-                 * @sample {highstock} stock/xaxis/reversed/
-                 *         Reversed Y axis
-                 *
-                 * @type      {boolean}
-                 * @default   {highcharts} false
-                 * @default   {highstock} false
-                 * @default   {highmaps} true
-                 * @default   {gantt} true
-                 * @apioption yAxis.reversed
-                 */
-                /**
-                 * If `true`, the first series in a stack will be drawn on top in a
-                 * positive, non-reversed Y axis. If `false`, the first series is in
-                 * the base of the stack.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/reversedstacks-false/
-                 *         Non-reversed stacks
-                 * @sample {highstock} highcharts/yaxis/reversedstacks-false/
-                 *         Non-reversed stacks
-                 *
-                 * @type      {boolean}
-                 * @default   true
-                 * @since     3.0.10
-                 * @product   highcharts highstock
-                 * @apioption yAxis.reversedStacks
-                 */
-                /**
-                 * Solid gauge series only. Color stops for the solid gauge. Use this
-                 * in cases where a linear gradient between a `minColor` and `maxColor`
-                 * is not sufficient. The stops is an array of tuples, where the first
-                 * item is a float between 0 and 1 assigning the relative position in
-                 * the gradient, and the second item is the color.
-                 *
-                 * For solid gauges, the Y axis also inherits the concept of
-                 * [data classes](https://api.highcharts.com/highmaps#colorAxis.dataClasses)
-                 * from the Highmaps color axis.
-                 *
-                 * @see [minColor](#yAxis.minColor)
-                 * @see [maxColor](#yAxis.maxColor)
-                 *
-                 * @sample {highcharts} highcharts/demo/gauge-solid/
-                 *         True by default
-                 *
-                 * @type      {Array<Array<number,Highcharts.ColorType>>}
-                 * @since     4.0
-                 * @product   highcharts
-                 * @apioption yAxis.stops
-                 */
-                /**
-                 * The pixel width of the major tick marks.
-                 *
-                 * @sample {highcharts} highcharts/xaxis/tickwidth/ 10 px width
-                 * @sample {highstock} stock/xaxis/ticks/ Formatted ticks on X axis
-                 *
-                 * @type      {number}
-                 * @default   0
-                 * @product   highcharts highstock gantt
-                 * @apioption yAxis.tickWidth
-                 */
-                /**
-                 * Whether to force the axis to end on a tick. Use this option with
-                 * the `maxPadding` option to control the axis end.
-                 *
-                 * This option is always disabled, when panning type is
-                 * either `y` or `xy`.
-                 *
-                 * @see [type](#chart.panning.type)
-                 *
-                 *
-                 * @sample {highcharts} highcharts/chart/reflow-true/
-                 *         True by default
-                 * @sample {highcharts} highcharts/yaxis/endontick/
-                 *         False
-                 * @sample {highstock} stock/demo/basic-line/
-                 *         True by default
-                 * @sample {highstock} stock/xaxis/endontick/
-                 *         False for Y axis
-                 *
-                 * @since 1.2.0
-                 */
-                endOnTick: true,
-                /**
-                 * Padding of the max value relative to the length of the axis. A
-                 * padding of 0.05 will make a 100px axis 5px longer. This is useful
-                 * when you don't want the highest data value to appear on the edge
-                 * of the plot area. When the axis' `max` option is set or a max extreme
-                 * is set using `axis.setExtremes()`, the maxPadding will be ignored.
-                 *
-                 * Also the `softThreshold` option takes precedence over `maxPadding`,
-                 * so if the data is tangent to the threshold, `maxPadding` may not
-                 * apply unless `softThreshold` is set to false.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/maxpadding-02/
-                 *         Max padding of 0.2
-                 * @sample {highstock} stock/xaxis/minpadding-maxpadding/
-                 *         Greater min- and maxPadding
-                 *
-                 * @since   1.2.0
-                 * @product highcharts highstock gantt
-                 */
-                maxPadding: 0.05,
-                /**
-                 * Padding of the min value relative to the length of the axis. A
-                 * padding of 0.05 will make a 100px axis 5px longer. This is useful
-                 * when you don't want the lowest data value to appear on the edge
-                 * of the plot area. When the axis' `min` option is set or a max extreme
-                 * is set using `axis.setExtremes()`, the maxPadding will be ignored.
-                 *
-                 * Also the `softThreshold` option takes precedence over `minPadding`,
-                 * so if the data is tangent to the threshold, `minPadding` may not
-                 * apply unless `softThreshold` is set to false.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/minpadding/
-                 *         Min padding of 0.2
-                 * @sample {highstock} stock/xaxis/minpadding-maxpadding/
-                 *         Greater min- and maxPadding
-                 *
-                 * @since   1.2.0
-                 * @product highcharts highstock gantt
-                 */
-                minPadding: 0.05,
-                /**
-                 * @productdesc {highstock}
-                 * In Highstock 1.x, the Y axis was placed on the left side by default.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/opposite/
-                 *         Secondary Y axis opposite
-                 * @sample {highstock} stock/xaxis/opposite/
-                 *         Y axis on left side
-                 *
-                 * @type      {boolean}
-                 * @default   {highstock} true
-                 * @default   {highcharts} false
-                 * @product   highstock highcharts gantt
-                 * @apioption yAxis.opposite
-                 */
-                /**
-                 * @see [tickInterval](#xAxis.tickInterval)
-                 * @see [tickPositioner](#xAxis.tickPositioner)
-                 * @see [tickPositions](#xAxis.tickPositions)
-                 */
-                tickPixelInterval: 72,
-                showLastLabel: true,
-                /**
-                 * @extends xAxis.labels
-                 */
-                labels: {
-                    /**
-                     * Angular gauges and solid gauges only.
-                     * The label's pixel distance from the perimeter of the plot area.
-                     *
-                     * Since v7.1.2: If it's a percentage string, it is interpreted the
-                     * same as [series.radius](#plotOptions.gauge.radius), so label can be
-                     * aligned under the gauge's shape.
-                     *
-                     * @sample {highcharts} highcharts/yaxis/labels-distance/
-                     *         Labels centered under the arc
-                     *
-                     * @type      {number|string}
-                     * @default   -25
-                     * @product   highcharts
-                     * @apioption yAxis.labels.distance
-                     */
-                    /**
-                     * The y position offset of all labels relative to the tick
-                     * positions on the axis. For polar and radial axis consider the use
-                     * of the [distance](#yAxis.labels.distance) option.
-                     *
-                     * @sample {highcharts} highcharts/xaxis/labels-x/
-                     *         Y axis labels placed on grid lines
-                     *
-                     * @type      {number}
-                     * @default   {highcharts} 3
-                     * @default   {highstock} -2
-                     * @default   {highmaps} 3
-                     * @apioption yAxis.labels.y
-                     */
-                    /**
-                     * What part of the string the given position is anchored to. Can
-                     * be one of `"left"`, `"center"` or `"right"`. The exact position
-                     * also depends on the `labels.x` setting.
-                     *
-                     * Angular gauges and solid gauges defaults to `"center"`.
-                     * Solid gauges with two labels have additional option `"auto"`
-                     * for automatic horizontal and vertical alignment.
-                     *
-                     * @see [yAxis.labels.distance](#yAxis.labels.distance)
-                     *
-                     * @sample {highcharts} highcharts/yaxis/labels-align-left/
-                     *         Left
-                     * @sample {highcharts} highcharts/series-solidgauge/labels-auto-aligned/
-                     *         Solid gauge labels auto aligned
-                     *
-                     * @type       {Highcharts.AlignValue}
-                     * @default    {highcharts|highmaps} right
-                     * @default    {highstock} left
-                     * @apioption  yAxis.labels.align
-                     */
-                    /**
-                     * The x position offset of all labels relative to the tick
-                     * positions on the axis. Defaults to -15 for left axis, 15 for
-                     * right axis.
-                     *
-                     * @sample {highcharts} highcharts/xaxis/labels-x/
-                     *         Y axis labels placed on grid lines
-                     */
-                    x: -8
-                },
-                /**
-                 * @productdesc {highmaps}
-                 * In Highmaps, the axis line is hidden by default, because the axis is
-                 * not visible by default.
-                 *
-                 * @type      {Highcharts.ColorType}
-                 * @apioption yAxis.lineColor
-                 */
-                /**
-                 * @sample {highcharts} highcharts/yaxis/max-200/
-                 *         Y axis max of 200
-                 * @sample {highcharts} highcharts/yaxis/max-logarithmic/
-                 *         Y axis max on logarithmic axis
-                 * @sample {highstock} stock/yaxis/min-max/
-                 *         Fixed min and max on Y axis
-                 * @sample {highmaps} maps/axis/min-max/
-                 *         Pre-zoomed to a specific area
-                 *
-                 * @apioption yAxis.max
-                 */
-                /**
-                 * @sample {highcharts} highcharts/yaxis/min-startontick-false/
-                 *         -50 with startOnTick to false
-                 * @sample {highcharts} highcharts/yaxis/min-startontick-true/
-                 *         -50 with startOnTick true by default
-                 * @sample {highstock} stock/yaxis/min-max/
-                 *         Fixed min and max on Y axis
-                 * @sample {highmaps} maps/axis/min-max/
-                 *         Pre-zoomed to a specific area
-                 *
-                 * @apioption yAxis.min
-                 */
-                /**
-                 * An optional scrollbar to display on the Y axis in response to
-                 * limiting the minimum an maximum of the axis values.
-                 *
-                 * In styled mode, all the presentational options for the scrollbar
-                 * are replaced by the classes `.highcharts-scrollbar-thumb`,
-                 * `.highcharts-scrollbar-arrow`, `.highcharts-scrollbar-button`,
-                 * `.highcharts-scrollbar-rifles` and `.highcharts-scrollbar-track`.
-                 *
-                 * @sample {highstock} stock/yaxis/scrollbar/
-                 *         Scrollbar on the Y axis
-                 *
-                 * @extends   scrollbar
-                 * @since     4.2.6
-                 * @product   highstock
-                 * @excluding height
-                 * @apioption yAxis.scrollbar
-                 */
-                /**
-                 * Enable the scrollbar on the Y axis.
-                 *
-                 * @sample {highstock} stock/yaxis/scrollbar/
-                 *         Enabled on Y axis
-                 *
-                 * @type      {boolean}
-                 * @default   false
-                 * @since     4.2.6
-                 * @product   highstock
-                 * @apioption yAxis.scrollbar.enabled
-                 */
-                /**
-                 * Pixel margin between the scrollbar and the axis elements.
-                 *
-                 * @type      {number}
-                 * @default   10
-                 * @since     4.2.6
-                 * @product   highstock
-                 * @apioption yAxis.scrollbar.margin
-                 */
-                /**
-                 * Whether to show the scrollbar when it is fully zoomed out at max
-                 * range. Setting it to `false` on the Y axis makes the scrollbar stay
-                 * hidden until the user zooms in, like common in browsers.
-                 *
-                 * @type      {boolean}
-                 * @default   true
-                 * @since     4.2.6
-                 * @product   highstock
-                 * @apioption yAxis.scrollbar.showFull
-                 */
-                /**
-                 * The width of a vertical scrollbar or height of a horizontal
-                 * scrollbar. Defaults to 20 on touch devices.
-                 *
-                 * @type      {number}
-                 * @default   14
-                 * @since     4.2.6
-                 * @product   highstock
-                 * @apioption yAxis.scrollbar.size
-                 */
-                /**
-                 * Z index of the scrollbar elements.
-                 *
-                 * @type      {number}
-                 * @default   3
-                 * @since     4.2.6
-                 * @product   highstock
-                 * @apioption yAxis.scrollbar.zIndex
-                 */
-                /**
-                 * A soft maximum for the axis. If the series data maximum is less
-                 * than this, the axis will stay at this maximum, but if the series
-                 * data maximum is higher, the axis will flex to show all data.
-                 *
-                 * **Note**: The [series.softThreshold](
-                 * #plotOptions.series.softThreshold) option takes precedence over this
-                 * option.
-                 *
-                 * @sample highcharts/yaxis/softmin-softmax/
-                 *         Soft min and max
-                 *
-                 * @type      {number}
-                 * @since     5.0.1
-                 * @product   highcharts highstock gantt
-                 * @apioption yAxis.softMax
-                 */
-                /**
-                 * A soft minimum for the axis. If the series data minimum is greater
-                 * than this, the axis will stay at this minimum, but if the series
-                 * data minimum is lower, the axis will flex to show all data.
-                 *
-                 * **Note**: The [series.softThreshold](
-                 * #plotOptions.series.softThreshold) option takes precedence over this
-                 * option.
-                 *
-                 * @sample highcharts/yaxis/softmin-softmax/
-                 *         Soft min and max
-                 *
-                 * @type      {number}
-                 * @since     5.0.1
-                 * @product   highcharts highstock gantt
-                 * @apioption yAxis.softMin
-                 */
-                /**
-                 * Defines the horizontal alignment of the stack total label. Can be one
-                 * of `"left"`, `"center"` or `"right"`. The default value is calculated
-                 * at runtime and depends on orientation and whether the stack is
-                 * positive or negative.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/stacklabels-align-left/
-                 *         Aligned to the left
-                 * @sample {highcharts} highcharts/yaxis/stacklabels-align-center/
-                 *         Aligned in center
-                 * @sample {highcharts} highcharts/yaxis/stacklabels-align-right/
-                 *         Aligned to the right
-                 *
-                 * @type      {Highcharts.AlignValue}
-                 * @since     2.1.5
-                 * @product   highcharts
-                 * @apioption yAxis.stackLabels.align
-                 */
-                /**
-                 * A format string for the data label. Available variables are the same
-                 * as for `formatter`.
-                 *
-                 * @type      {string}
-                 * @default   {total}
-                 * @since     3.0.2
-                 * @product   highcharts highstock
-                 * @apioption yAxis.stackLabels.format
-                 */
-                /**
-                 * Rotation of the labels in degrees.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/stacklabels-rotation/
-                 *         Labels rotated 45°
-                 *
-                 * @type      {number}
-                 * @default   0
-                 * @since     2.1.5
-                 * @product   highcharts
-                 * @apioption yAxis.stackLabels.rotation
-                 */
-                /**
-                 * The text alignment for the label. While `align` determines where the
-                 * texts anchor point is placed with regards to the stack, `textAlign`
-                 * determines how the text is aligned against its anchor point. Possible
-                 * values are `"left"`, `"center"` and `"right"`. The default value is
-                 * calculated at runtime and depends on orientation and whether the
-                 * stack is positive or negative.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/stacklabels-textalign-left/
-                 *         Label in center position but text-aligned left
-                 *
-                 * @type      {Highcharts.AlignValue}
-                 * @since     2.1.5
-                 * @product   highcharts
-                 * @apioption yAxis.stackLabels.textAlign
-                 */
-                /**
-                 * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html)
-                 * to render the labels.
-                 *
-                 * @type      {boolean}
-                 * @default   false
-                 * @since     3.0
-                 * @product   highcharts highstock
-                 * @apioption yAxis.stackLabels.useHTML
-                 */
-                /**
-                 * Defines the vertical alignment of the stack total label. Can be one
-                 * of `"top"`, `"middle"` or `"bottom"`. The default value is calculated
-                 * at runtime and depends on orientation and whether the stack is
-                 * positive or negative.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/stacklabels-verticalalign-top/
-                 *         Vertically aligned top
-                 * @sample {highcharts} highcharts/yaxis/stacklabels-verticalalign-middle/
-                 *         Vertically aligned middle
-                 * @sample {highcharts} highcharts/yaxis/stacklabels-verticalalign-bottom/
-                 *         Vertically aligned bottom
-                 *
-                 * @type      {Highcharts.VerticalAlignValue}
-                 * @since     2.1.5
-                 * @product   highcharts
-                 * @apioption yAxis.stackLabels.verticalAlign
-                 */
-                /**
-                 * The x position offset of the label relative to the left of the
-                 * stacked bar. The default value is calculated at runtime and depends
-                 * on orientation and whether the stack is positive or negative.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/stacklabels-x/
-                 *         Stack total labels with x offset
-                 *
-                 * @type      {number}
-                 * @since     2.1.5
-                 * @product   highcharts
-                 * @apioption yAxis.stackLabels.x
-                 */
-                /**
-                 * The y position offset of the label relative to the tick position
-                 * on the axis. The default value is calculated at runtime and depends
-                 * on orientation and whether the stack is positive or negative.
-                 *
-                 * @sample {highcharts} highcharts/yaxis/stacklabels-y/
-                 *         Stack total labels with y offset
-                 *
-                 * @type      {number}
-                 * @since     2.1.5
-                 * @product   highcharts
-                 * @apioption yAxis.stackLabels.y
-                 */
-                /**
-                 * Whether to force the axis to start on a tick. Use this option with
-                 * the `maxPadding` option to control the axis start.
-                 *
-                 * This option is always disabled, when panning type is
-                 * either `y` or `xy`.
-                 *
-                 * @see [type](#chart.panning.type)
-                 *
-                 * @sample {highcharts} highcharts/xaxis/startontick-false/
-                 *         False by default
-                 * @sample {highcharts} highcharts/xaxis/startontick-true/
-                 *         True
-                 * @sample {highstock} stock/xaxis/endontick/
-                 *         False for Y axis
-                 *
-                 * @since   1.2.0
-                 * @product highcharts highstock gantt
-                 */
-                startOnTick: true,
-                title: {
-                    /**
-                     * The pixel distance between the axis labels and the title.
-                     * Positive values are outside the axis line, negative are inside.
-                     *
-                     * @sample {highcharts} highcharts/xaxis/title-margin/
-                     *         Y axis title margin of 60
-                     *
-                     * @type      {number}
-                     * @default   40
-                     * @apioption yAxis.title.margin
-                     */
-                    /**
-                     * The rotation of the text in degrees. 0 is horizontal, 270 is
-                     * vertical reading from bottom to top.
-                     *
-                     * @sample {highcharts} highcharts/yaxis/title-offset/
-                     *         Horizontal
-                     */
-                    rotation: 270,
-                    /**
-                     * The actual text of the axis title. Horizontal texts can contain
-                     * HTML, but rotated texts are painted using vector techniques and
-                     * must be clean text. The Y axis title is disabled by setting the
-                     * `text` option to `undefined`.
-                     *
-                     * @sample {highcharts} highcharts/xaxis/title-text/
-                     *         Custom HTML
-                     *
-                     * @type    {string|null}
-                     * @default {highcharts} Values
-                     * @default {highstock} undefined
-                     * @product highcharts highstock gantt
-                     */
-                    text: 'Values'
-                },
-                /**
-                 * The top position of the Y axis. If it's a number, it is interpreted
-                 * as pixel position relative to the chart.
-                 *
-                 * Since Highcharts 2: If it's a percentage string, it is interpreted as
-                 * percentages of the plot height, offset from plot area top.
-                 *
-                 * @see [yAxis.height](#yAxis.height)
-                 *
-                 * @sample {highstock} stock/demo/candlestick-and-volume/
-                 *         Percentage height panes
-                 *
-                 * @type      {number|string}
-                 * @product   highcharts highstock
-                 * @apioption yAxis.top
-                 */
-                /**
-                 * The stack labels show the total value for each bar in a stacked
-                 * column or bar chart. The label will be placed on top of positive
-                 * columns and below negative columns. In case of an inverted column
-                 * chart or a bar chart the label is placed to the right of positive
-                 * bars and to the left of negative bars.
-                 *
-                 * @product highcharts
-                 */
-                stackLabels: {
-                    /**
-                     * Enable or disable the initial animation when a series is
-                     * displayed for the `stackLabels`. The animation can also be set as
-                     * a configuration object. Please note that this option only
-                     * applies to the initial animation.
-                     * For other animations, see [chart.animation](#chart.animation)
-                     * and the animation parameter under the API methods.
-                     * The following properties are supported:
-                     *
-                     * - `defer`: The animation delay time in milliseconds.
-                     *
-                     * @sample {highcharts} highcharts/plotoptions/animation-defer/
-                     *          Animation defer settings
-                     * @type {boolean|Partial<Highcharts.AnimationOptionsObject>}
-                     * @since 8.2.0
-                     * @apioption yAxis.stackLabels.animation
-                     */
-                    animation: {},
-                    /**
-                     * The animation delay time in milliseconds.
-                     * Set to `0` renders stackLabel immediately.
-                     * As `undefined` inherits defer time from the [series.animation.defer](#plotOptions.series.animation.defer).
-                     *
-                     * @type      {number}
-                     * @since 8.2.0
-                     * @apioption yAxis.stackLabels.animation.defer
-                     */
-                    /**
-                     * Allow the stack labels to overlap.
-                     *
-                     * @sample {highcharts} highcharts/yaxis/stacklabels-allowoverlap-false/
-                     *         Default false
-                     *
-                     * @since   5.0.13
-                     * @product highcharts
-                     */
-                    allowOverlap: false,
-                    /**
-                     * The background color or gradient for the stack label.
-                     *
-                     * @sample {highcharts} highcharts/yaxis/stacklabels-box/
-                     *          Stack labels box options
-                     * @type      {Highcharts.ColorType}
-                     * @since 8.1.0
-                     * @apioption yAxis.stackLabels.backgroundColor
-                     */
-                    /**
-                     * The border color for the stack label. Defaults to `undefined`.
-                     *
-                     * @sample {highcharts} highcharts/yaxis/stacklabels-box/
-                     *          Stack labels box options
-                     * @type      {Highcharts.ColorType}
-                     * @since 8.1.0
-                     * @apioption yAxis.stackLabels.borderColor
-                     */
-                    /**
-                     * The border radius in pixels for the stack label.
-                     *
-                     * @sample {highcharts} highcharts/yaxis/stacklabels-box/
-                     *          Stack labels box options
-                     * @type      {number}
-                     * @default   0
-                     * @since 8.1.0
-                     * @apioption yAxis.stackLabels.borderRadius
-                     */
-                    /**
-                     * The border width in pixels for the stack label.
-                     *
-                     * @sample {highcharts} highcharts/yaxis/stacklabels-box/
-                     *          Stack labels box options
-                     * @type      {number}
-                     * @default   0
-                     * @since 8.1.0
-                     * @apioption yAxis.stackLabels.borderWidth
-                     */
-                    /**
-                     * Enable or disable the stack total labels.
-                     *
-                     * @sample {highcharts} highcharts/yaxis/stacklabels-enabled/
-                     *         Enabled stack total labels
-                     * @sample {highcharts} highcharts/yaxis/stacklabels-enabled-waterfall/
-                     *         Enabled stack labels in waterfall chart
-                     *
-                     * @since   2.1.5
-                     * @product highcharts
-                     */
-                    enabled: false,
-                    /**
-                     * Whether to hide stack labels that are outside the plot area.
-                     * By default, the stack label is moved
-                     * inside the plot area according to the
-                     * [overflow](/highcharts/#yAxis/stackLabels/overflow)
-                     * option.
-                     *
-                     * @type  {boolean}
-                     * @since 7.1.3
-                     */
-                    crop: true,
-                    /**
-                     * How to handle stack total labels that flow outside the plot area.
-                     * The default is set to `"justify"`,
-                     * which aligns them inside the plot area.
-                     * For columns and bars, this means it will be moved inside the bar.
-                     * To display stack labels outside the plot area,
-                     * set `crop` to `false` and `overflow` to `"allow"`.
-                     *
-                     * @sample highcharts/yaxis/stacklabels-overflow/
-                     *         Stack labels flows outside the plot area.
-                     *
-                     * @type  {Highcharts.DataLabelsOverflowValue}
-                     * @since 7.1.3
-                     */
-                    overflow: 'justify',
-                    /* eslint-disable valid-jsdoc */
-                    /**
-                     * Callback JavaScript function to format the label. The value is
-                     * given by `this.total`.
-                     *
-                     * @sample {highcharts} highcharts/yaxis/stacklabels-formatter/
-                     *         Added units to stack total value
-                     *
-                     * @type    {Highcharts.FormatterCallbackFunction<Highcharts.StackItemObject>}
-                     * @since   2.1.5
-                     * @product highcharts
-                     */
-                    formatter: function () {
-                        var numberFormatter = this.axis.chart.numberFormatter;
-                        /* eslint-enable valid-jsdoc */
-                        return numberFormatter(this.total, -1);
-                    },
-                    /**
-                     * CSS styles for the label.
-                     *
-                     * In styled mode, the styles are set in the
-                     * `.highcharts-stack-label` class.
-                     *
-                     * @sample {highcharts} highcharts/yaxis/stacklabels-style/
-                     *         Red stack total labels
-                     *
-                     * @type    {Highcharts.CSSObject}
-                     * @since   2.1.5
-                     * @product highcharts
-                     */
-                    style: {
-                        /** @internal */
-                        color: '#000000',
-                        /** @internal */
-                        fontSize: '11px',
-                        /** @internal */
-                        fontWeight: 'bold',
-                        /** @internal */
-                        textOutline: '1px contrast'
-                    }
-                },
-                gridLineWidth: 1,
-                lineWidth: 0
-                // tickWidth: 0
-            };
-            /**
-             * The Z axis or depth axis for 3D plots.
-             *
-             * See the [Axis class](/class-reference/Highcharts.Axis) for programmatic
-             * access to the axis.
-             *
-             * @sample {highcharts} highcharts/3d/scatter-zaxis-categories/
-             *         Z-Axis with Categories
-             * @sample {highcharts} highcharts/3d/scatter-zaxis-grid/
-             *         Z-Axis with styling
-             *
-             * @type      {*|Array<*>}
-             * @extends   xAxis
-             * @since     5.0.0
-             * @product   highcharts
-             * @excluding breaks, crosshair, height, left, lineColor, lineWidth,
-             *            nameToX, showEmpty, top, width
-             * @apioption zAxis
-             *
-             * @private
-             */
-            // This variable extends the defaultOptions for left axes.
-            Axis.defaultLeftAxisOptions = {
-                labels: {
-                    x: -15
-                },
-                title: {
-                    rotation: 270
-                }
-            };
-            // This variable extends the defaultOptions for right axes.
-            Axis.defaultRightAxisOptions = {
-                labels: {
-                    x: 15
-                },
-                title: {
-                    rotation: 90
-                }
-            };
-            // This variable extends the defaultOptions for bottom axes.
-            Axis.defaultBottomAxisOptions = {
-                labels: {
-                    autoRotation: [-45],
-                    x: 0
-                    // overflow: undefined,
-                    // staggerLines: null
-                },
-                margin: 15,
-                title: {
-                    rotation: 0
-                }
-            };
-            // This variable extends the defaultOptions for top axes.
-            Axis.defaultTopAxisOptions = {
-                labels: {
-                    autoRotation: [-45],
-                    x: 0
-                    // overflow: undefined
-                    // staggerLines: null
-                },
-                margin: 15,
-                title: {
-                    rotation: 0
-                }
-            };
-            // Properties to survive after destroy, needed for Axis.update (#4317,
-            // #5773, #5881).
-            Axis.keepProps = ['extKey', 'hcEvents', 'names', 'series', 'userMax', 'userMin'];
-            return Axis;
-        }());
-        H.Axis = Axis;
-
-        return H.Axis;
-    });
-    _registerModule(_modules, 'Core/Axis/DateTimeAxis.js', [_modules['Core/Axis/Axis.js'], _modules['Core/Utilities.js']], function (Axis, U) {
-        /* *
-         *
-         *  (c) 2010-2020 Torstein Honsi
-         *
-         *  License: www.highcharts.com/license
-         *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
-         *
-         * */
-        var addEvent = U.addEvent,
-            getMagnitude = U.getMagnitude,
-            normalizeTickInterval = U.normalizeTickInterval,
-            timeUnits = U.timeUnits;
-        /* eslint-disable valid-jsdoc */
-        var DateTimeAxisAdditions = /** @class */ (function () {
-                /* *
-                 *
-                 *  Constructors
-                 *
-                 * */
-                function DateTimeAxisAdditions(axis) {
-                    this.axis = axis;
-            }
-            /* *
-             *
-             *  Functions
-             *
-             * */
-            /**
-             * Get a normalized tick interval for dates. Returns a configuration object
-             * with unit range (interval), count and name. Used to prepare data for
-             * `getTimeTicks`. Previously this logic was part of getTimeTicks, but as
-             * `getTimeTicks` now runs of segments in stock charts, the normalizing
-             * logic was extracted in order to prevent it for running over again for
-             * each segment having the same interval. #662, #697.
-             * @private
-             */
-            /**
-             * Get a normalized tick interval for dates. Returns a configuration object
-             * with unit range (interval), count and name. Used to prepare data for
-             * `getTimeTicks`. Previously this logic was part of getTimeTicks, but as
-             * `getTimeTicks` now runs of segments in stock charts, the normalizing
-             * logic was extracted in order to prevent it for running over again for
-             * each segment having the same interval. #662, #697.
-             * @private
-             */
-            DateTimeAxisAdditions.prototype.normalizeTimeTickInterval = function (tickInterval, unitsOption) {
-                var units = unitsOption || [[
-                            'millisecond',
-                            [1, 2, 5, 10, 20, 25, 50, 100, 200, 500] // allowed multiples
-                        ],
-                    [
-                            'second',
-                            [1, 2, 5, 10, 15, 30]
-                        ],
-                    [
-                            'minute',
-                            [1, 2, 5, 10, 15, 30]
-                        ],
-                    [
-                            'hour',
-                            [1, 2, 3, 4, 6, 8, 12]
-                        ],
-                    [
-                            'day',
-                            [1, 2]
-                        ],
-                    [
-                            'week',
-                            [1, 2]
-                        ],
-                    [
-                            'month',
-                            [1, 2, 3, 4, 6]
-                        ],
-                    [
-                            'year',
-                            null
-                        ]],
-                    unit = units[units.length - 1], // default unit is years
-                    interval = timeUnits[unit[0]],
-                    multiples = unit[1],
-                    count,
-                    i;
-                // loop through the units to find the one that best fits the
-                // tickInterval
-                for (i = 0; i < units.length; i++) {
-                    unit = units[i];
-                    interval = timeUnits[unit[0]];
-                    multiples = unit[1];
-                    if (units[i + 1]) {
-                        // lessThan is in the middle between the highest multiple and
-                        // the next unit.
-                        var lessThan = (interval *
-                                multiples[multiples.length - 1] +
-                                timeUnits[units[i + 1][0]]) / 2;
-                        // break and keep the current unit
-                        if (tickInterval <= lessThan) {
-                            break;
-                        }
-                    }
-                }
-                // prevent 2.5 years intervals, though 25, 250 etc. are allowed
-                if (interval === timeUnits.year && tickInterval < 5 * interval) {
-                    multiples = [1, 2, 5];
-                }
-                // get the count
-                count = normalizeTickInterval(tickInterval / interval, multiples, unit[0] === 'year' ? // #1913, #2360
-                    Math.max(getMagnitude(tickInterval / interval), 1) :
-                    1);
-                return {
-                    unitRange: interval,
-                    count: count,
-                    unitName: unit[0]
-                };
-            };
-            return DateTimeAxisAdditions;
-        }());
-        /**
-         * Date and time support for axes.
-         *
-         * @private
-         * @class
-         */
-        var DateTimeAxis = /** @class */ (function () {
-                function DateTimeAxis() {
-                }
-                /* *
-                 *
-                 *  Static Functions
-                 *
-                 * */
-                /**
-                 * Extends axis class with date and time support.
-                 * @private
-                 */
-                DateTimeAxis.compose = function (AxisClass) {
-                    AxisClass.keepProps.push('dateTime');
-                var axisProto = AxisClass.prototype;
-                /**
-                 * Set the tick positions to a time unit that makes sense, for example
-                 * on the first of each month or on every Monday. Return an array with
-                 * the time positions. Used in datetime axes as well as for grouping
-                 * data on a datetime axis.
-                 *
-                 * @private
-                 * @function Highcharts.Axis#getTimeTicks
-                 *
-                 * @param {Highcharts.TimeNormalizeObject} normalizedInterval
-                 * The interval in axis values (ms) and thecount.
-                 *
-                 * @param {number} min
-                 * The minimum in axis values.
-                 *
-                 * @param {number} max
-                 * The maximum in axis values.
-                 *
-                 * @param {number} startOfWeek
-                 *
-                 * @return {Highcharts.AxisTickPositionsArray}
-                 */
-                axisProto.getTimeTicks = function () {
-                    return this.chart.time.getTimeTicks.apply(this.chart.time, arguments);
-                };
-                /* eslint-disable no-invalid-this */
-                addEvent(AxisClass, 'init', function (e) {
-                    var axis = this;
-                    var options = e.userOptions;
-                    if (options.type !== 'datetime') {
-                        axis.dateTime = void 0;
-                        return;
-                    }
-                    if (!axis.dateTime) {
-                        axis.dateTime = new DateTimeAxisAdditions(axis);
-                    }
-                });
-                /* eslint-enable no-invalid-this */
-            };
-            /* *
-             *
-             *  Static Properties
-             *
-             * */
-            DateTimeAxis.AdditionsClass = DateTimeAxisAdditions;
-            return DateTimeAxis;
-        }());
-        DateTimeAxis.compose(Axis);
-
-        return DateTimeAxis;
-    });
-    _registerModule(_modules, 'Core/Axis/LogarithmicAxis.js', [_modules['Core/Axis/Axis.js'], _modules['Core/Utilities.js']], function (Axis, U) {
-        /* *
-         *
-         *  (c) 2010-2020 Torstein Honsi
-         *
-         *  License: www.highcharts.com/license
-         *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
-         *
-         * */
-        var addEvent = U.addEvent,
-            getMagnitude = U.getMagnitude,
-            normalizeTickInterval = U.normalizeTickInterval,
-            pick = U.pick;
-        /* eslint-disable valid-jsdoc */
-        /**
-         * Provides logarithmic support for axes.
-         *
-         * @private
-         * @class
-         */
-        var LogarithmicAxisAdditions = /** @class */ (function () {
-                /* *
-                 *
-                 *  Constructors
-                 *
-                 * */
-                function LogarithmicAxisAdditions(axis) {
-                    this.axis = axis;
-            }
-            /* *
-             *
-             *  Functions
-             *
-             * */
-            /**
-             * Set the tick positions of a logarithmic axis.
-             */
-            LogarithmicAxisAdditions.prototype.getLogTickPositions = function (interval, min, max, minor) {
-                var log = this;
-                var axis = log.axis;
-                var axisLength = axis.len;
-                var options = axis.options;
-                // Since we use this method for both major and minor ticks,
-                // use a local variable and return the result
-                var positions = [];
-                // Reset
-                if (!minor) {
-                    log.minorAutoInterval = void 0;
-                }
-                // First case: All ticks fall on whole logarithms: 1, 10, 100 etc.
-                if (interval >= 0.5) {
-                    interval = Math.round(interval);
-                    positions = axis.getLinearTickPositions(interval, min, max);
-                    // Second case: We need intermediary ticks. For example
-                    // 1, 2, 4, 6, 8, 10, 20, 40 etc.
-                }
-                else if (interval >= 0.08) {
-                    var roundedMin = Math.floor(min),
-                        intermediate,
-                        i,
-                        j,
-                        len,
-                        pos,
-                        lastPos,
-                        break2;
-                    if (interval > 0.3) {
-                        intermediate = [1, 2, 4];
-                        // 0.2 equals five minor ticks per 1, 10, 100 etc
-                    }
-                    else if (interval > 0.15) {
-                        intermediate = [1, 2, 4, 6, 8];
-                    }
-                    else { // 0.1 equals ten minor ticks per 1, 10, 100 etc
-                        intermediate = [1, 2, 3, 4, 5, 6, 7, 8, 9];
-                    }
-                    for (i = roundedMin; i < max + 1 && !break2; i++) {
-                        len = intermediate.length;
-                        for (j = 0; j < len && !break2; j++) {
-                            pos = log.log2lin(log.lin2log(i) * intermediate[j]);
-                            // #1670, lastPos is #3113
-                            if (pos > min &&
-                                (!minor || lastPos <= max) &&
-                                typeof lastPos !== 'undefined') {
-                                positions.push(lastPos);
-                            }
-                            if (lastPos > max) {
-                                break2 = true;
-                            }
-                            lastPos = pos;
-                        }
-                    }
-                    // Third case: We are so deep in between whole logarithmic values that
-                    // we might as well handle the tick positions like a linear axis. For
-                    // example 1.01, 1.02, 1.03, 1.04.
-                }
-                else {
-                    var realMin = log.lin2log(min),
-                        realMax = log.lin2log(max),
-                        tickIntervalOption = minor ?
-                            axis.getMinorTickInterval() :
-                            options.tickInterval,
-                        filteredTickIntervalOption = tickIntervalOption === 'auto' ?
-                            null :
-                            tickIntervalOption,
-                        tickPixelIntervalOption = options.tickPixelInterval / (minor ? 5 : 1),
-                        totalPixelLength = minor ?
-                            axisLength / axis.tickPositions.length :
-                            axisLength;
-                    interval = pick(filteredTickIntervalOption, log.minorAutoInterval, (realMax - realMin) *
-                        tickPixelIntervalOption / (totalPixelLength || 1));
-                    interval = normalizeTickInterval(interval, void 0, getMagnitude(interval));
-                    positions = axis.getLinearTickPositions(interval, realMin, realMax).map(log.log2lin);
-                    if (!minor) {
-                        log.minorAutoInterval = interval / 5;
-                    }
-                }
-                // Set the axis-level tickInterval variable
-                if (!minor) {
-                    axis.tickInterval = interval;
-                }
-                return positions;
-            };
-            LogarithmicAxisAdditions.prototype.lin2log = function (num) {
-                return Math.pow(10, num);
-            };
-            LogarithmicAxisAdditions.prototype.log2lin = function (num) {
-                return Math.log(num) / Math.LN10;
-            };
-            return LogarithmicAxisAdditions;
-        }());
-        var LogarithmicAxis = /** @class */ (function () {
-                function LogarithmicAxis() {
-                }
-                /**
-                 * Provides logarithmic support for axes.
-                 *
-                 * @private
-                 */
-                LogarithmicAxis.compose = function (AxisClass) {
-                    AxisClass.keepProps.push('logarithmic');
-                // HC <= 8 backwards compatibility, allow wrapping
-                // Axis.prototype.lin2log and log2lin
-                // @todo Remove this in next major
-                var axisProto = AxisClass.prototype;
-                var logAxisProto = LogarithmicAxisAdditions.prototype;
-                axisProto.log2lin = logAxisProto.log2lin;
-                axisProto.lin2log = logAxisProto.lin2log;
-                /* eslint-disable no-invalid-this */
-                addEvent(AxisClass, 'init', function (e) {
-                    var axis = this;
-                    var options = e.userOptions;
-                    var logarithmic = axis.logarithmic;
-                    if (options.type !== 'logarithmic') {
-                        axis.logarithmic = void 0;
-                    }
-                    else {
-                        if (!logarithmic) {
-                            logarithmic = axis.logarithmic = new LogarithmicAxisAdditions(axis);
-                        }
-                        // HC <= 8 backwards compatibility, allow wrapping
-                        // Axis.prototype.lin2log and log2lin
-                        // @todo Remove this in next major
-                        if (axis.log2lin !== logarithmic.log2lin) {
-                            logarithmic.log2lin = axis.log2lin.bind(axis);
-                        }
-                        if (axis.lin2log !== logarithmic.lin2log) {
-                            logarithmic.lin2log = axis.lin2log.bind(axis);
-                        }
-                    }
-                });
-                addEvent(AxisClass, 'afterInit', function () {
-                    var axis = this;
-                    var log = axis.logarithmic;
-                    // extend logarithmic axis
-                    if (log) {
-                        axis.lin2val = function (num) {
-                            return log.lin2log(num);
-                        };
-                        axis.val2lin = function (num) {
-                            return log.log2lin(num);
-                        };
-                    }
-                });
-            };
-            return LogarithmicAxis;
-        }());
-        LogarithmicAxis.compose(Axis); // @todo move to factory functions
-
-        return LogarithmicAxis;
-    });
-    _registerModule(_modules, 'Core/Axis/PlotLineOrBand.js', [_modules['Core/Axis/Axis.js'], _modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (Axis, H, U) {
-        /* *
-         *
-         *  (c) 2010-2020 Torstein Honsi
-         *
-         *  License: www.highcharts.com/license
-         *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
-         *
-         * */
-        /**
-         * Options for plot bands on axes.
-         *
-         * @typedef {Highcharts.XAxisPlotBandsOptions|Highcharts.YAxisPlotBandsOptions|Highcharts.ZAxisPlotBandsOptions} Highcharts.AxisPlotBandsOptions
-         */
-        /**
-         * Options for plot band labels on axes.
-         *
-         * @typedef {Highcharts.XAxisPlotBandsLabelOptions|Highcharts.YAxisPlotBandsLabelOptions|Highcharts.ZAxisPlotBandsLabelOptions} Highcharts.AxisPlotBandsLabelOptions
-         */
-        /**
-         * Options for plot lines on axes.
-         *
-         * @typedef {Highcharts.XAxisPlotLinesOptions|Highcharts.YAxisPlotLinesOptions|Highcharts.ZAxisPlotLinesOptions} Highcharts.AxisPlotLinesOptions
-         */
-        /**
-         * Options for plot line labels on axes.
-         *
-         * @typedef {Highcharts.XAxisPlotLinesLabelOptions|Highcharts.YAxisPlotLinesLabelOptions|Highcharts.ZAxisPlotLinesLabelOptions} Highcharts.AxisPlotLinesLabelOptions
-         */
-        var arrayMax = U.arrayMax,
-            arrayMin = U.arrayMin,
-            defined = U.defined,
-            destroyObjectProperties = U.destroyObjectProperties,
-            erase = U.erase,
-            extend = U.extend,
-            merge = U.merge,
-            objectEach = U.objectEach,
-            pick = U.pick;
-        /* eslint-disable no-invalid-this, valid-jsdoc */
-        /**
-         * The object wrapper for plot lines and plot bands
-         *
-         * @class
-         * @name Highcharts.PlotLineOrBand
-         *
-         * @param {Highcharts.Axis} axis
-         *
-         * @param {Highcharts.AxisPlotLinesOptions|Highcharts.AxisPlotBandsOptions} [options]
-         */
-        var PlotLineOrBand = /** @class */ (function () {
-                function PlotLineOrBand(axis, options) {
-                    this.axis = axis;
-                if (options) {
-                    this.options = options;
-                    this.id = options.id;
-                }
-            }
-            /**
-             * Render the plot line or plot band. If it is already existing,
-             * move it.
-             *
-             * @private
-             * @function Highcharts.PlotLineOrBand#render
-             * @return {Highcharts.PlotLineOrBand|undefined}
-             */
-            PlotLineOrBand.prototype.render = function () {
-                H.fireEvent(this, 'render');
-                var plotLine = this,
-                    axis = plotLine.axis,
-                    horiz = axis.horiz,
-                    log = axis.logarithmic,
-                    options = plotLine.options,
-                    optionsLabel = options.label,
-                    label = plotLine.label,
-                    to = options.to,
-                    from = options.from,
-                    value = options.value,
-                    isBand = defined(from) && defined(to),
-                    isLine = defined(value),
-                    svgElem = plotLine.svgElem,
-                    isNew = !svgElem,
-                    path = [],
-                    color = options.color,
-                    zIndex = pick(options.zIndex, 0),
-                    events = options.events,
-                    attribs = {
-                        'class': 'highcharts-plot-' + (isBand ? 'band ' : 'line ') +
-                            (options.className || '')
-                    },
-                    groupAttribs = {},
-                    renderer = axis.chart.renderer,
-                    groupName = isBand ? 'bands' : 'lines',
-                    group;
-                // logarithmic conversion
-                if (log) {
-                    from = log.log2lin(from);
-                    to = log.log2lin(to);
-                    value = log.log2lin(value);
-                }
-                // Set the presentational attributes
-                if (!axis.chart.styledMode) {
-                    if (isLine) {
-                        attribs.stroke = color || '#999999';
-                        attribs['stroke-width'] = pick(options.width, 1);
-                        if (options.dashStyle) {
-                            attribs.dashstyle =
-                                options.dashStyle;
-                        }
-                    }
-                    else if (isBand) { // plot band
-                        attribs.fill = color || '#e6ebf5';
-                        if (options.borderWidth) {
-                            attribs.stroke = options.borderColor;
-                            attribs['stroke-width'] = options.borderWidth;
-                        }
-                    }
-                }
-                // Grouping and zIndex
-                groupAttribs.zIndex = zIndex;
-                groupName += '-' + zIndex;
-                group = axis.plotLinesAndBandsGroups[groupName];
-                if (!group) {
-                    axis.plotLinesAndBandsGroups[groupName] = group =
-                        renderer.g('plot-' + groupName)
-                            .attr(groupAttribs).add();
-                }
-                // Create the path
-                if (isNew) {
-                    /**
-                     * SVG element of the plot line or band.
-                     *
-                     * @name Highcharts.PlotLineOrBand#svgElement
-                     * @type {Highcharts.SVGElement}
-                     */
-                    plotLine.svgElem = svgElem = renderer
-                        .path()
-                        .attr(attribs)
-                        .add(group);
-                }
-                // Set the path or return
-                if (isLine) {
-                    path = axis.getPlotLinePath({
-                        value: value,
-                        lineWidth: svgElem.strokeWidth(),
-                        acrossPanes: options.acrossPanes
-                    });
-                }
-                else if (isBand) { // plot band
-                    path = axis.getPlotBandPath(from, to, options);
-                }
-                else {
-                    return;
-                }
-                // common for lines and bands
-                // Add events only if they were not added before.
-                if (!plotLine.eventsAdded && events) {
-                    objectEach(events, function (event, eventType) {
-                        svgElem.on(eventType, function (e) {
-                            events[eventType].apply(plotLine, [e]);
-                        });
-                    });
-                    plotLine.eventsAdded = true;
-                }
-                if ((isNew || !svgElem.d) && path && path.length) {
-                    svgElem.attr({ d: path });
-                }
-                else if (svgElem) {
-                    if (path) {
-                        svgElem.show(true);
-                        svgElem.animate({ d: path });
-                    }
-                    else if (svgElem.d) {
-                        svgElem.hide();
-                        if (label) {
-                            plotLine.label = label = label.destroy();
-                        }
-                    }
-                }
-                // the plot band/line label
-                if (optionsLabel &&
-                    (defined(optionsLabel.text) || defined(optionsLabel.formatter)) &&
-                    path &&
-                    path.length &&
-                    axis.width > 0 &&
-                    axis.height > 0 &&
-                    !path.isFlat) {
-                    // apply defaults
-                    optionsLabel = merge({
-                        align: horiz && isBand && 'center',
-                        x: horiz ? !isBand && 4 : 10,
-                        verticalAlign: !horiz && isBand && 'middle',
-                        y: horiz ? isBand ? 16 : 10 : isBand ? 6 : -4,
-                        rotation: horiz && !isBand && 90
-                    }, optionsLabel);
-                    this.renderLabel(optionsLabel, path, isBand, zIndex);
-                }
-                else if (label) { // move out of sight
-                    label.hide();
-                }
-                // chainable
-                return plotLine;
-            };
-            /**
-             * Render and align label for plot line or band.
-             *
-             * @private
-             * @function Highcharts.PlotLineOrBand#renderLabel
-             * @param {Highcharts.AxisPlotLinesLabelOptions|Highcharts.AxisPlotBandsLabelOptions} optionsLabel
-             * @param {Highcharts.SVGPathArray} path
-             * @param {boolean} [isBand]
-             * @param {number} [zIndex]
-             * @return {void}
-             */
-            PlotLineOrBand.prototype.renderLabel = function (optionsLabel, path, isBand, zIndex) {
-                var plotLine = this,
-                    label = plotLine.label,
-                    renderer = plotLine.axis.chart.renderer,
-                    attribs,
-                    xBounds,
-                    yBounds,
-                    x,
-                    y,
-                    labelText;
-                // add the SVG element
-                if (!label) {
-                    attribs = {
-                        align: optionsLabel.textAlign || optionsLabel.align,
-                        rotation: optionsLabel.rotation,
-                        'class': 'highcharts-plot-' + (isBand ? 'band' : 'line') +
-                            '-label ' + (optionsLabel.className || '')
-                    };
-                    attribs.zIndex = zIndex;
-                    labelText = this.getLabelText(optionsLabel);
-                    /**
-                     * SVG element of the label.
-                     *
-                     * @name Highcharts.PlotLineOrBand#label
-                     * @type {Highcharts.SVGElement}
-                     */
-                    plotLine.label = label = renderer
-                        .text(labelText, 0, 0, optionsLabel.useHTML)
-                        .attr(attribs)
-                        .add();
-                    if (!this.axis.chart.styledMode) {
-                        label.css(optionsLabel.style);
-                    }
-                }
-                // get the bounding box and align the label
-                // #3000 changed to better handle choice between plotband or plotline
-                xBounds = path.xBounds ||
-                    [path[0][1], path[1][1], (isBand ? path[2][1] : path[0][1])];
-                yBounds = path.yBounds ||
-                    [path[0][2], path[1][2], (isBand ? path[2][2] : path[0][2])];
-                x = arrayMin(xBounds);
-                y = arrayMin(yBounds);
-                label.align(optionsLabel, false, {
-                    x: x,
-                    y: y,
-                    width: arrayMax(xBounds) - x,
-                    height: arrayMax(yBounds) - y
-                });
-                label.show(true);
-            };
-            /**
-             * Get label's text content.
-             *
-             * @private
-             * @function Highcharts.PlotLineOrBand#getLabelText
-             * @param {Highcharts.AxisPlotLinesLabelOptions|Highcharts.AxisPlotBandsLabelOptions} optionsLabel
-             * @return {string}
-             */
-            PlotLineOrBand.prototype.getLabelText = function (optionsLabel) {
-                return defined(optionsLabel.formatter) ?
-                    optionsLabel.formatter
-                        .call(this) :
-                    optionsLabel.text;
-            };
-            /**
-             * Remove the plot line or band.
-             *
-             * @function Highcharts.PlotLineOrBand#destroy
-             * @return {void}
-             */
-            PlotLineOrBand.prototype.destroy = function () {
-                // remove it from the lookup
-                erase(this.axis.plotLinesAndBands, this);
-                delete this.axis;
-                destroyObjectProperties(this);
-            };
-            return PlotLineOrBand;
-        }());
-        /* eslint-enable no-invalid-this, valid-jsdoc */
-        // Object with members for extending the Axis prototype
-        extend(Axis.prototype, /** @lends Highcharts.Axis.prototype */ {
-            /**
-             * An array of colored bands stretching across the plot area marking an
-             * interval on the axis.
-             *
-             * In styled mode, the plot bands are styled by the `.highcharts-plot-band`
-             * class in addition to the `className` option.
-             *
-             * @productdesc {highcharts}
-             * In a gauge, a plot band on the Y axis (value axis) will stretch along the
-             * perimeter of the gauge.
-             *
-             * @type      {Array<*>}
-             * @product   highcharts highstock gantt
-             * @apioption xAxis.plotBands
-             */
-            /**
-             * Flag to decide if plotBand should be rendered across all panes.
-             *
-             * @since     7.1.2
-             * @product   highstock
-             * @type      {boolean}
-             * @default   true
-             * @apioption xAxis.plotBands.acrossPanes
-             */
-            /**
-             * Border color for the plot band. Also requires `borderWidth` to be set.
-             *
-             * @type      {Highcharts.ColorString}
-             * @apioption xAxis.plotBands.borderColor
-             */
-            /**
-             * Border width for the plot band. Also requires `borderColor` to be set.
-             *
-             * @type      {number}
-             * @default   0
-             * @apioption xAxis.plotBands.borderWidth
-             */
-            /**
-             * A custom class name, in addition to the default `highcharts-plot-band`,
-             * to apply to each individual band.
-             *
-             * @type      {string}
-             * @since     5.0.0
-             * @apioption xAxis.plotBands.className
-             */
-            /**
-             * The color of the plot band.
-             *
-             * @sample {highcharts} highcharts/xaxis/plotbands-color/
-             *         Color band
-             * @sample {highstock} stock/xaxis/plotbands/
-             *         Plot band on Y axis
-             *
-             * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-             * @default   #e6ebf5
-             * @apioption xAxis.plotBands.color
-             */
-            /**
-             * An object defining mouse events for the plot band. Supported properties
-             * are `click`, `mouseover`, `mouseout`, `mousemove`.
-             *
-             * @sample {highcharts} highcharts/xaxis/plotbands-events/
-             *         Mouse events demonstrated
-             *
-             * @since     1.2
-             * @apioption xAxis.plotBands.events
-             */
-            /**
-             * Click event on a plot band.
-             *
-             * @type      {Highcharts.EventCallbackFunction<Highcharts.PlotLineOrBand>}
-             * @apioption xAxis.plotBands.events.click
-             */
-            /**
-             * Mouse move event on a plot band.
-             *
-             * @type      {Highcharts.EventCallbackFunction<Highcharts.PlotLineOrBand>}
-             * @apioption xAxis.plotBands.events.mousemove
-             */
-            /**
-             * Mouse out event on the corner of a plot band.
-             *
-             * @type      {Highcharts.EventCallbackFunction<Highcharts.PlotLineOrBand>}
-             * @apioption xAxis.plotBands.events.mouseout
-             */
-            /**
-             * Mouse over event on a plot band.
-             *
-             * @type      {Highcharts.EventCallbackFunction<Highcharts.PlotLineOrBand>}
-             * @apioption xAxis.plotBands.events.mouseover
-             */
-            /**
-             * The start position of the plot band in axis units.
-             *
-             * @sample {highcharts} highcharts/xaxis/plotbands-color/
-             *         Datetime axis
-             * @sample {highcharts} highcharts/xaxis/plotbands-from/
-             *         Categorized axis
-             * @sample {highstock} stock/xaxis/plotbands/
-             *         Plot band on Y axis
-             *
-             * @type      {number}
-             * @apioption xAxis.plotBands.from
-             */
-            /**
-             * An id used for identifying the plot band in Axis.removePlotBand.
-             *
-             * @sample {highcharts} highcharts/xaxis/plotbands-id/
-             *         Remove plot band by id
-             * @sample {highstock} highcharts/xaxis/plotbands-id/
-             *         Remove plot band by id
-             *
-             * @type      {string}
-             * @apioption xAxis.plotBands.id
-             */
-            /**
-             * The end position of the plot band in axis units.
-             *
-             * @sample {highcharts} highcharts/xaxis/plotbands-color/
-             *         Datetime axis
-             * @sample {highcharts} highcharts/xaxis/plotbands-from/
-             *         Categorized axis
-             * @sample {highstock} stock/xaxis/plotbands/
-             *         Plot band on Y axis
-             *
-             * @type      {number}
-             * @apioption xAxis.plotBands.to
-             */
-            /**
-             * The z index of the plot band within the chart, relative to other
-             * elements. Using the same z index as another element may give
-             * unpredictable results, as the last rendered element will be on top.
-             * Values from 0 to 20 make sense.
-             *
-             * @sample {highcharts} highcharts/xaxis/plotbands-color/
-             *         Behind plot lines by default
-             * @sample {highcharts} highcharts/xaxis/plotbands-zindex/
-             *         Above plot lines
-             * @sample {highcharts} highcharts/xaxis/plotbands-zindex-above-series/
-             *         Above plot lines and series
-             *
-             * @type      {number}
-             * @since     1.2
-             * @apioption xAxis.plotBands.zIndex
-             */
-            /**
-             * Text labels for the plot bands
-             *
-             * @product   highcharts highstock gantt
-             * @apioption xAxis.plotBands.label
-             */
-            /**
-             * Horizontal alignment of the label. Can be one of "left", "center" or
-             * "right".
-             *
-             * @sample {highcharts} highcharts/xaxis/plotbands-label-align/
-             *         Aligned to the right
-             * @sample {highstock} stock/xaxis/plotbands-label/
-             *         Plot band with labels
-             *
-             * @type      {Highcharts.AlignValue}
-             * @default   center
-             * @since     2.1
-             * @apioption xAxis.plotBands.label.align
-             */
-            /**
-             * Rotation of the text label in degrees .
-             *
-             * @sample {highcharts} highcharts/xaxis/plotbands-label-rotation/
-             *         Vertical text
-             *
-             * @type      {number}
-             * @default   0
-             * @since     2.1
-             * @apioption xAxis.plotBands.label.rotation
-             */
-            /**
-             * CSS styles for the text label.
-             *
-             * In styled mode, the labels are styled by the
-             * `.highcharts-plot-band-label` class.
-             *
-             * @sample {highcharts} highcharts/xaxis/plotbands-label-style/
-             *         Blue and bold label
-             *
-             * @type      {Highcharts.CSSObject}
-             * @since     2.1
-             * @apioption xAxis.plotBands.label.style
-             */
-            /**
-             * The string text itself. A subset of HTML is supported.
-             *
-             * @type      {string}
-             * @since     2.1
-             * @apioption xAxis.plotBands.label.text
-             */
-            /**
-             * The text alignment for the label. While `align` determines where the
-             * texts anchor point is placed within the plot band, `textAlign` determines
-             * how the text is aligned against its anchor point. Possible values are
-             * "left", "center" and "right". Defaults to the same as the `align` option.
-             *
-             * @sample {highcharts} highcharts/xaxis/plotbands-label-rotation/
-             *         Vertical text in center position but text-aligned left
-             *
-             * @type       {Highcharts.AlignValue}
-             * @since      2.1
-             * @apioption  xAxis.plotBands.label.textAlign
-             */
-            /**
-             * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html)
-             * to render the labels.
-             *
-             * @type      {boolean}
-             * @default   false
-             * @since     3.0.3
-             * @apioption xAxis.plotBands.label.useHTML
-             */
-            /**
-             * Vertical alignment of the label relative to the plot band. Can be one of
-             * "top", "middle" or "bottom".
-             *
-             * @sample {highcharts} highcharts/xaxis/plotbands-label-verticalalign/
-             *         Vertically centered label
-             * @sample {highstock} stock/xaxis/plotbands-label/
-             *         Plot band with labels
-             *
-             * @type       {Highcharts.VerticalAlignValue}
-             * @default    top
-             * @since      2.1
-             * @apioption  xAxis.plotBands.label.verticalAlign
-             */
-            /**
-             * Horizontal position relative the alignment. Default varies by
-             * orientation.
-             *
-             * @sample {highcharts} highcharts/xaxis/plotbands-label-align/
-             *         Aligned 10px from the right edge
-             * @sample {highstock} stock/xaxis/plotbands-label/
-             *         Plot band with labels
-             *
-             * @type      {number}
-             * @since     2.1
-             * @apioption xAxis.plotBands.label.x
-             */
-            /**
-             * Vertical position of the text baseline relative to the alignment. Default
-             * varies by orientation.
-             *
-             * @sample {highcharts} highcharts/xaxis/plotbands-label-y/
-             *         Label on x axis
-             * @sample {highstock} stock/xaxis/plotbands-label/
-             *         Plot band with labels
-             *
-             * @type      {number}
-             * @since     2.1
-             * @apioption xAxis.plotBands.label.y
-             */
-            /**
-             * An array of lines stretching across the plot area, marking a specific
-             * value on one of the axes.
-             *
-             * In styled mode, the plot lines are styled by the
-             * `.highcharts-plot-line` class in addition to the `className` option.
-             *
-             * @type      {Array<*>}
-             * @product   highcharts highstock gantt
-             * @sample {highcharts} highcharts/xaxis/plotlines-color/
-             *         Basic plot line
-             * @sample {highcharts} highcharts/series-solidgauge/labels-auto-aligned/
-             *         Solid gauge plot line
-             * @apioption xAxis.plotLines
-             */
-            /**
-             * Flag to decide if plotLine should be rendered across all panes.
-             *
-             * @sample {highstock} stock/xaxis/plotlines-acrosspanes/
-             *         Plot lines on different panes
-             *
-             * @since     7.1.2
-             * @product   highstock
-             * @type      {boolean}
-             * @default   true
-             * @apioption xAxis.plotLines.acrossPanes
-             */
-            /**
-             * A custom class name, in addition to the default `highcharts-plot-line`,
-             * to apply to each individual line.
-             *
-             * @type      {string}
-             * @since     5.0.0
-             * @apioption xAxis.plotLines.className
-             */
-            /**
-             * The color of the line.
-             *
-             * @sample {highcharts} highcharts/xaxis/plotlines-color/
-             *         A red line from X axis
-             * @sample {highstock} stock/xaxis/plotlines/
-             *         Plot line on Y axis
-             *
-             * @type      {Highcharts.ColorString}
-             * @default   #999999
-             * @apioption xAxis.plotLines.color
-             */
-            /**
-             * The dashing or dot style for the plot line. For possible values see
-             * [this overview](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/series-dashstyle-all/).
-             *
-             * @sample {highcharts} highcharts/xaxis/plotlines-dashstyle/
-             *         Dash and dot pattern
-             * @sample {highstock} stock/xaxis/plotlines/
-             *         Plot line on Y axis
-             *
-             * @type      {Highcharts.DashStyleValue}
-             * @default   Solid
-             * @since     1.2
-             * @apioption xAxis.plotLines.dashStyle
-             */
-            /**
-             * An object defining mouse events for the plot line. Supported
-             * properties are `click`, `mouseover`, `mouseout`, `mousemove`.
-             *
-             * @sample {highcharts} highcharts/xaxis/plotlines-events/
-             *         Mouse events demonstrated
-             *
-             * @since     1.2
-             * @apioption xAxis.plotLines.events
-             */
-            /**
-             * Click event on a plot band.
-             *
-             * @type      {Highcharts.EventCallbackFunction<Highcharts.PlotLineOrBand>}
-             * @apioption xAxis.plotLines.events.click
-             */
-            /**
-             * Mouse move event on a plot band.
-             *
-             * @type      {Highcharts.EventCallbackFunction<Highcharts.PlotLineOrBand>}
-             * @apioption xAxis.plotLines.events.mousemove
-             */
-            /**
-             * Mouse out event on the corner of a plot band.
-             *
-             * @type      {Highcharts.EventCallbackFunction<Highcharts.PlotLineOrBand>}
-             * @apioption xAxis.plotLines.events.mouseout
-             */
-            /**
-             * Mouse over event on a plot band.
-             *
-             * @type      {Highcharts.EventCallbackFunction<Highcharts.PlotLineOrBand>}
-             * @apioption xAxis.plotLines.events.mouseover
-             */
-            /**
-             * An id used for identifying the plot line in Axis.removePlotLine.
-             *
-             * @sample {highcharts} highcharts/xaxis/plotlines-id/
-             *         Remove plot line by id
-             *
-             * @type      {string}
-             * @apioption xAxis.plotLines.id
-             */
-            /**
-             * The position of the line in axis units.
-             *
-             * @sample {highcharts} highcharts/xaxis/plotlines-color/
-             *         Between two categories on X axis
-             * @sample {highstock} stock/xaxis/plotlines/
-             *         Plot line on Y axis
-             *
-             * @type      {number}
-             * @apioption xAxis.plotLines.value
-             */
-            /**
-             * The width or thickness of the plot line.
-             *
-             * @sample {highcharts} highcharts/xaxis/plotlines-color/
-             *         2px wide line from X axis
-             * @sample {highstock} stock/xaxis/plotlines/
-             *         Plot line on Y axis
-             *
-             * @type      {number}
-             * @default   2
-             * @apioption xAxis.plotLines.width
-             */
-            /**
-             * The z index of the plot line within the chart.
-             *
-             * @sample {highcharts} highcharts/xaxis/plotlines-zindex-behind/
-             *         Behind plot lines by default
-             * @sample {highcharts} highcharts/xaxis/plotlines-zindex-above/
-             *         Above plot lines
-             * @sample {highcharts} highcharts/xaxis/plotlines-zindex-above-all/
-             *         Above plot lines and series
-             *
-             * @type      {number}
-             * @since     1.2
-             * @apioption xAxis.plotLines.zIndex
-             */
-            /**
-             * Text labels for the plot bands
-             *
-             * @apioption xAxis.plotLines.label
-             */
-            /**
-             * Horizontal alignment of the label. Can be one of "left", "center" or
-             * "right".
-             *
-             * @sample {highcharts} highcharts/xaxis/plotlines-label-align-right/
-             *         Aligned to the right
-             * @sample {highstock} stock/xaxis/plotlines/
-             *         Plot line on Y axis
-             *
-             * @type       {Highcharts.AlignValue}
-             * @default    left
-             * @since      2.1
-             * @apioption  xAxis.plotLines.label.align
-             */
-            /**
-             * Callback JavaScript function to format the label. Useful properties like
-             * the value of plot line or the range of plot band (`from` & `to`
-             * properties) can be found in `this.options` object.
-             *
-             * @sample {highcharts} highcharts/xaxis/plotlines-plotbands-label-formatter
-             *         Label formatters for plot line and plot band.
-             * @type      {Highcharts.FormatterCallbackFunction<Highcharts.PlotLineOrBand>}
-             * @apioption xAxis.plotLines.label.formatter
-             */
-            /**
-             * Rotation of the text label in degrees. Defaults to 0 for horizontal plot
-             * lines and 90 for vertical lines.
-             *
-             * @sample {highcharts} highcharts/xaxis/plotlines-label-verticalalign-middle/
-             *         Slanted text
-             *
-             * @type      {number}
-             * @since     2.1
-             * @apioption xAxis.plotLines.label.rotation
-             */
-            /**
-             * CSS styles for the text label.
-             *
-             * In styled mode, the labels are styled by the
-             * `.highcharts-plot-line-label` class.
-             *
-             * @sample {highcharts} highcharts/xaxis/plotlines-label-style/
-             *         Blue and bold label
-             *
-             * @type      {Highcharts.CSSObject}
-             * @since     2.1
-             * @apioption xAxis.plotLines.label.style
-             */
-            /**
-             * The text itself. A subset of HTML is supported.
-             *
-             * @type      {string}
-             * @since     2.1
-             * @apioption xAxis.plotLines.label.text
-             */
-            /**
-             * The text alignment for the label. While `align` determines where the
-             * texts anchor point is placed within the plot band, `textAlign` determines
-             * how the text is aligned against its anchor point. Possible values are
-             * "left", "center" and "right". Defaults to the same as the `align` option.
-             *
-             * @sample {highcharts} highcharts/xaxis/plotlines-label-textalign/
-             *         Text label in bottom position
-             *
-             * @type      {Highcharts.AlignValue}
-             * @since     2.1
-             * @apioption xAxis.plotLines.label.textAlign
-             */
-            /**
-             * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html)
-             * to render the labels.
-             *
-             * @type      {boolean}
-             * @default   false
-             * @since     3.0.3
-             * @apioption xAxis.plotLines.label.useHTML
-             */
-            /**
-             * Vertical alignment of the label relative to the plot line. Can be
-             * one of "top", "middle" or "bottom".
-             *
-             * @sample {highcharts} highcharts/xaxis/plotlines-label-verticalalign-middle/
-             *         Vertically centered label
-             *
-             * @type       {Highcharts.VerticalAlignValue}
-             * @default    {highcharts} top
-             * @default    {highstock} top
-             * @since      2.1
-             * @apioption  xAxis.plotLines.label.verticalAlign
-             */
-            /**
-             * Horizontal position relative the alignment. Default varies by
-             * orientation.
-             *
-             * @sample {highcharts} highcharts/xaxis/plotlines-label-align-right/
-             *         Aligned 10px from the right edge
-             * @sample {highstock} stock/xaxis/plotlines/
-             *         Plot line on Y axis
-             *
-             * @type      {number}
-             * @since     2.1
-             * @apioption xAxis.plotLines.label.x
-             */
-            /**
-             * Vertical position of the text baseline relative to the alignment. Default
-             * varies by orientation.
-             *
-             * @sample {highcharts} highcharts/xaxis/plotlines-label-y/
-             *         Label below the plot line
-             * @sample {highstock} stock/xaxis/plotlines/
-             *         Plot line on Y axis
-             *
-             * @type      {number}
-             * @since     2.1
-             * @apioption xAxis.plotLines.label.y
-             */
-            /**
-             *
-             * @type      {Array<*>}
-             * @extends   xAxis.plotBands
-             * @apioption yAxis.plotBands
-             */
-            /**
-             * In a gauge chart, this option determines the inner radius of the
-             * plot band that stretches along the perimeter. It can be given as
-             * a percentage string, like `"100%"`, or as a pixel number, like `100`.
-             * By default, the inner radius is controlled by the [thickness](
-             * #yAxis.plotBands.thickness) option.
-             *
-             * @sample {highcharts} highcharts/xaxis/plotbands-gauge
-             *         Gauge plot band
-             *
-             * @type      {number|string}
-             * @since     2.3
-             * @product   highcharts
-             * @apioption yAxis.plotBands.innerRadius
-             */
-            /**
-             * In a gauge chart, this option determines the outer radius of the
-             * plot band that stretches along the perimeter. It can be given as
-             * a percentage string, like `"100%"`, or as a pixel number, like `100`.
-             *
-             * @sample {highcharts} highcharts/xaxis/plotbands-gauge
-             *         Gauge plot band
-             *
-             * @type      {number|string}
-             * @default   100%
-             * @since     2.3
-             * @product   highcharts
-             * @apioption yAxis.plotBands.outerRadius
-             */
-            /**
-             * In a gauge chart, this option sets the width of the plot band
-             * stretching along the perimeter. It can be given as a percentage
-             * string, like `"10%"`, or as a pixel number, like `10`. The default
-             * value 10 is the same as the default [tickLength](#yAxis.tickLength),
-             * thus making the plot band act as a background for the tick markers.
-             *
-             * @sample {highcharts} highcharts/xaxis/plotbands-gauge
-             *         Gauge plot band
-             *
-             * @type      {number|string}
-             * @default   10
-             * @since     2.3
-             * @product   highcharts
-             * @apioption yAxis.plotBands.thickness
-             */
-            /**
-             * @type      {Array<*>}
-             * @extends   xAxis.plotLines
-             * @apioption yAxis.plotLines
-             */
-            /* eslint-disable no-invalid-this, valid-jsdoc */
-            /**
-             * Internal function to create the SVG path definition for a plot band.
-             *
-             * @function Highcharts.Axis#getPlotBandPath
-             *
-             * @param {number} from
-             *        The axis value to start from.
-             *
-             * @param {number} to
-             *        The axis value to end on.
-             *
-             * @param {Highcharts.AxisPlotBandsOptions|Highcharts.AxisPlotLinesOptions} options
-             *        The plotBand or plotLine configuration object.
-             *
-             * @return {Highcharts.SVGPathArray}
-             *         The SVG path definition in array form.
-             */
-            getPlotBandPath: function (from, to, options) {
-                if (options === void 0) { options = this.options; }
-                var toPath = this.getPlotLinePath({
-                        value: to,
-                        force: true,
-                        acrossPanes: options.acrossPanes
-                    }),
-                    path = this.getPlotLinePath({
-                        value: from,
-                        force: true,
-                        acrossPanes: options.acrossPanes
-                    }),
-                    result = [],
-                    i, 
-                    // #4964 check if chart is inverted or plotband is on yAxis
-                    horiz = this.horiz,
-                    plus = 1,
-                    isFlat,
-                    outside = (from < this.min && to < this.min) ||
-                        (from > this.max && to > this.max);
-                if (path && toPath) {
-                    // Flat paths don't need labels (#3836)
-                    if (outside) {
-                        isFlat = path.toString() === toPath.toString();
-                        plus = 0;
-                    }
-                    // Go over each subpath - for panes in Highstock
-                    for (i = 0; i < path.length; i += 2) {
-                        var pathStart = path[i],
-                            pathEnd = path[i + 1],
-                            toPathStart = toPath[i],
-                            toPathEnd = toPath[i + 1];
-                        // Type checking all affected path segments. Consider something
-                        // smarter.
-                        if ((pathStart[0] === 'M' || pathStart[0] === 'L') &&
-                            (pathEnd[0] === 'M' || pathEnd[0] === 'L') &&
-                            (toPathStart[0] === 'M' || toPathStart[0] === 'L') &&
-                            (toPathEnd[0] === 'M' || toPathEnd[0] === 'L')) {
-                            // Add 1 pixel when coordinates are the same
-                            if (horiz && toPathStart[1] === pathStart[1]) {
-                                toPathStart[1] += plus;
-                                toPathEnd[1] += plus;
-                            }
-                            else if (!horiz && toPathStart[2] === pathStart[2]) {
-                                toPathStart[2] += plus;
-                                toPathEnd[2] += plus;
-                            }
-                            result.push(['M', pathStart[1], pathStart[2]], ['L', pathEnd[1], pathEnd[2]], ['L', toPathEnd[1], toPathEnd[2]], ['L', toPathStart[1], toPathStart[2]], ['Z']);
-                        }
-                        result.isFlat = isFlat;
-                    }
-                }
-                else { // outside the axis area
-                    path = null;
-                }
-                return result;
-            },
-            /**
-             * Add a plot band after render time.
-             *
-             * @sample highcharts/members/axis-addplotband/
-             *         Toggle the plot band from a button
-             *
-             * @function Highcharts.Axis#addPlotBand
-             *
-             * @param {Highcharts.AxisPlotBandsOptions} options
-             *        A configuration object for the plot band, as defined in
-             *        [xAxis.plotBands](https://api.highcharts.com/highcharts/xAxis.plotBands).
-             *
-             * @return {Highcharts.PlotLineOrBand|undefined}
-             *         The added plot band.
-             */
-            addPlotBand: function (options) {
-                return this.addPlotBandOrLine(options, 'plotBands');
-            },
-            /**
-             * Add a plot line after render time.
-             *
-             * @sample highcharts/members/axis-addplotline/
-             *         Toggle the plot line from a button
-             *
-             * @function Highcharts.Axis#addPlotLine
-             *
-             * @param {Highcharts.AxisPlotLinesOptions} options
-             *        A configuration object for the plot line, as defined in
-             *        [xAxis.plotLines](https://api.highcharts.com/highcharts/xAxis.plotLines).
-             *
-             * @return {Highcharts.PlotLineOrBand|undefined}
-             *         The added plot line.
-             */
-            addPlotLine: function (options) {
-                return this.addPlotBandOrLine(options, 'plotLines');
-            },
-            /**
-             * Add a plot band or plot line after render time. Called from addPlotBand
-             * and addPlotLine internally.
-             *
-             * @private
-             * @function Highcharts.Axis#addPlotBandOrLine
-             *
-             * @param {Highcharts.AxisPlotBandsOptions|Highcharts.AxisPlotLinesOptions} options
-             *        The plotBand or plotLine configuration object.
-             *
-             * @param {"plotBands"|"plotLines"} [coll]
-             *
-             * @return {Highcharts.PlotLineOrBand|undefined}
-             */
-            addPlotBandOrLine: function (options, coll) {
-                var obj = new H.PlotLineOrBand(this,
-                    options),
-                    userOptions = this.userOptions;
-                if (this.visible) {
-                    obj = obj.render();
-                }
-                if (obj) { // #2189
-                    // Add it to the user options for exporting and Axis.update
-                    if (coll) {
-                        // Workaround Microsoft/TypeScript issue #32693
-                        var updatedOptions = (userOptions[coll] || []);
-                        updatedOptions.push(options);
-                        userOptions[coll] = updatedOptions;
-                    }
-                    this.plotLinesAndBands.push(obj);
-                    this._addedPlotLB = true;
-                }
-                return obj;
-            },
-            /**
-             * Remove a plot band or plot line from the chart by id. Called internally
-             * from `removePlotBand` and `removePlotLine`.
-             *
-             * @private
-             * @function Highcharts.Axis#removePlotBandOrLine
-             * @param {string} id
-             * @return {void}
-             */
-            removePlotBandOrLine: function (id) {
-                var plotLinesAndBands = this.plotLinesAndBands,
-                    options = this.options,
-                    userOptions = this.userOptions,
-                    i = plotLinesAndBands.length;
-                while (i--) {
-                    if (plotLinesAndBands[i].id === id) {
-                        plotLinesAndBands[i].destroy();
-                    }
-                }
-                ([
-                    options.plotLines || [],
-                    userOptions.plotLines || [],
-                    options.plotBands || [],
-                    userOptions.plotBands || []
-                ]).forEach(function (arr) {
-                    i = arr.length;
-                    while (i--) {
-                        if ((arr[i] || {}).id === id) {
-                            erase(arr, arr[i]);
-                        }
-                    }
-                });
-            },
-            /**
-             * Remove a plot band by its id.
-             *
-             * @sample highcharts/members/axis-removeplotband/
-             *         Remove plot band by id
-             * @sample highcharts/members/axis-addplotband/
-             *         Toggle the plot band from a button
-             *
-             * @function Highcharts.Axis#removePlotBand
-             *
-             * @param {string} id
-             *        The plot band's `id` as given in the original configuration
-             *        object or in the `addPlotBand` option.
-             *
-             * @return {void}
-             */
-            removePlotBand: function (id) {
-                this.removePlotBandOrLine(id);
-            },
-            /**
-             * Remove a plot line by its id.
-             *
-             * @sample highcharts/xaxis/plotlines-id/
-             *         Remove plot line by id
-             * @sample highcharts/members/axis-addplotline/
-             *         Toggle the plot line from a button
-             *
-             * @function Highcharts.Axis#removePlotLine
-             *
-             * @param {string} id
-             *        The plot line's `id` as given in the original configuration
-             *        object or in the `addPlotLine` option.
-             */
-            removePlotLine: function (id) {
-                this.removePlotBandOrLine(id);
-            }
-        });
-        H.PlotLineOrBand = PlotLineOrBand;
-
-        return H.PlotLineOrBand;
-    });
-    _registerModule(_modules, 'Core/Tooltip.js', [_modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (H, U) {
-        /* *
-         *
-         *  (c) 2010-2020 Torstein Honsi
-         *
-         *  License: www.highcharts.com/license
-         *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
-         *
-         * */
-        var doc = H.doc;
-        var clamp = U.clamp,
-            css = U.css,
-            defined = U.defined,
-            discardElement = U.discardElement,
-            extend = U.extend,
-            fireEvent = U.fireEvent,
-            format = U.format,
-            isNumber = U.isNumber,
-            isString = U.isString,
-            merge = U.merge,
-            pick = U.pick,
-            splat = U.splat,
-            syncTimeout = U.syncTimeout,
-            timeUnits = U.timeUnits;
-        /**
-         * Callback function to format the text of the tooltip from scratch.
-         *
-         * In case of single or shared tooltips, a string should be be returned. In case
-         * of splitted tooltips, it should return an array where the first item is the
-         * header, and subsequent items are mapped to the points. Return `false` to
-         * disable tooltip for a specific point on series.
-         *
-         * @callback Highcharts.TooltipFormatterCallbackFunction
-         *
-         * @param {Highcharts.TooltipFormatterContextObject} this
-         *        Context to format
-         *
-         * @param {Highcharts.Tooltip} tooltip
-         *        The tooltip instance
-         *
-         * @return {false|string|Array<(string|null|undefined)>|null|undefined}
-         *         Formatted text or false
-         */
-        /**
-         * @interface Highcharts.TooltipFormatterContextObject
-         */ /**
-        * @name Highcharts.TooltipFormatterContextObject#color
-        * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-        */ /**
-        * @name Highcharts.TooltipFormatterContextObject#colorIndex
-        * @type {number|undefined}
-        */ /**
-        * @name Highcharts.TooltipFormatterContextObject#key
-        * @type {number}
-        */ /**
-        * @name Highcharts.TooltipFormatterContextObject#percentage
-        * @type {number|undefined}
-        */ /**
-        * @name Highcharts.TooltipFormatterContextObject#point
-        * @type {Highcharts.Point}
-        */ /**
-        * @name Highcharts.TooltipFormatterContextObject#points
-        * @type {Array<Highcharts.TooltipFormatterContextObject>|undefined}
-        */ /**
-        * @name Highcharts.TooltipFormatterContextObject#series
-        * @type {Highcharts.Series}
-        */ /**
-        * @name Highcharts.TooltipFormatterContextObject#total
-        * @type {number|undefined}
-        */ /**
-        * @name Highcharts.TooltipFormatterContextObject#x
-        * @type {number}
-        */ /**
-        * @name Highcharts.TooltipFormatterContextObject#y
-        * @type {number}
-        */
-        /**
-         * A callback function to place the tooltip in a specific position.
-         *
-         * @callback Highcharts.TooltipPositionerCallbackFunction
-         *
-         * @param {Highcharts.Tooltip} this
-         * Tooltip context of the callback.
-         *
-         * @param {number} labelWidth
-         * Width of the tooltip.
-         *
-         * @param {number} labelHeight
-         * Height of the tooltip.
-         *
-         * @param {Highcharts.TooltipPositionerPointObject} point
-         * Point information for positioning a tooltip.
-         *
-         * @return {Highcharts.PositionObject}
-         * New position for the tooltip.
-         */
-        /**
-         * Point information for positioning a tooltip.
-         *
-         * @interface Highcharts.TooltipPositionerPointObject
-         * @extends Highcharts.Point
-         */ /**
-        * If `tooltip.split` option is enabled and positioner is called for each of the
-        * boxes separately, this property indicates the call on the xAxis header, which
-        * is not a point itself.
-        * @name Highcharts.TooltipPositionerPointObject#isHeader
-        * @type {boolean}
-        */ /**
-        * The reference point relative to the plot area. Add chart.plotLeft to get the
-        * full coordinates.
-        * @name Highcharts.TooltipPositionerPointObject#plotX
-        * @type {number}
-        */ /**
-        * The reference point relative to the plot area. Add chart.plotTop to get the
-        * full coordinates.
-        * @name Highcharts.TooltipPositionerPointObject#plotY
-        * @type {number}
-        */
-        /**
-         * @typedef {"callout"|"circle"|"square"} Highcharts.TooltipShapeValue
-         */
-        ''; // separates doclets above from variables below
-        /* eslint-disable no-invalid-this, valid-jsdoc */
-        /**
-         * Tooltip of a chart.
-         *
-         * @class
-         * @name Highcharts.Tooltip
-         *
-         * @param {Highcharts.Chart} chart
-         * The chart instance.
-         *
-         * @param {Highcharts.TooltipOptions} options
-         * Tooltip options.
-         */
-        var Tooltip = /** @class */ (function () {
-                /* *
-                 *
-                 *  Constructors
-                 *
-                 * */
-                function Tooltip(chart, options) {
-                    this.container = void 0;
-                this.crosshairs = [];
-                this.distance = 0;
-                this.isHidden = true;
-                this.isSticky = false;
-                this.now = {};
-                this.options = {};
-                this.outside = false;
-                this.chart = chart;
-                this.init(chart, options);
-            }
-            /* *
-             *
-             *  Functions
-             *
-             * */
-            /**
-             * In styled mode, apply the default filter for the tooltip drop-shadow. It
-             * needs to have an id specific to the chart, otherwise there will be issues
-             * when one tooltip adopts the filter of a different chart, specifically one
-             * where the container is hidden.
-             *
-             * @private
-             * @function Highcharts.Tooltip#applyFilter
-             */
-            Tooltip.prototype.applyFilter = function () {
-                var chart = this.chart;
-                chart.renderer.definition({
-                    tagName: 'filter',
-                    id: 'drop-shadow-' + chart.index,
-                    opacity: 0.5,
-                    children: [{
-                            tagName: 'feGaussianBlur',
-                            'in': 'SourceAlpha',
-                            stdDeviation: 1
-                        }, {
-                            tagName: 'feOffset',
-                            dx: 1,
-                            dy: 1
-                        }, {
-                            tagName: 'feComponentTransfer',
-                            children: [{
-                                    tagName: 'feFuncA',
-                                    type: 'linear',
-                                    slope: 0.3
-                                }]
-                        }, {
-                            tagName: 'feMerge',
-                            children: [{
-                                    tagName: 'feMergeNode'
-                                }, {
-                                    tagName: 'feMergeNode',
-                                    'in': 'SourceGraphic'
-                                }]
-                        }]
-                });
-                chart.renderer.definition({
-                    tagName: 'style',
-                    textContent: '.highcharts-tooltip-' + chart.index + '{' +
-                        'filter:url(#drop-shadow-' + chart.index + ')' +
-                        '}'
-                });
-            };
-            /**
-             * Build the body (lines) of the tooltip by iterating over the items and
-             * returning one entry for each item, abstracting this functionality allows
-             * to easily overwrite and extend it.
-             *
-             * @private
-             * @function Highcharts.Tooltip#bodyFormatter
-             * @param {Array<(Highcharts.Point|Highcharts.Series)>} items
-             * @return {Array<string>}
-             */
-            Tooltip.prototype.bodyFormatter = function (items) {
-                return items.map(function (item) {
-                    var tooltipOptions = item.series.tooltipOptions;
-                    return (tooltipOptions[(item.point.formatPrefix || 'point') + 'Formatter'] ||
-                        item.point.tooltipFormatter).call(item.point, tooltipOptions[(item.point.formatPrefix || 'point') + 'Format'] || '');
-                });
-            };
-            /**
-             * Destroy the single tooltips in a split tooltip.
-             * If the tooltip is active then it is not destroyed, unless forced to.
-             *
-             * @private
-             * @function Highcharts.Tooltip#cleanSplit
-             *
-             * @param {boolean} [force]
-             *        Force destroy all tooltips.
-             */
-            Tooltip.prototype.cleanSplit = function (force) {
-                this.chart.series.forEach(function (series) {
-                    var tt = series && series.tt;
-                    if (tt) {
-                        if (!tt.isActive || force) {
-                            series.tt = tt.destroy();
-                        }
-                        else {
-                            tt.isActive = false;
-                        }
-                    }
-                });
-            };
-            /**
-             * In case no user defined formatter is given, this will be used. Note that
-             * the context here is an object holding point, series, x, y etc.
-             *
-             * @function Highcharts.Tooltip#defaultFormatter
-             *
-             * @param {Highcharts.Tooltip} tooltip
-             *
-             * @return {Array<string>}
-             */
-            Tooltip.prototype.defaultFormatter = function (tooltip) {
-                var items = this.points || splat(this),
-                    s;
-                // Build the header
-                s = [tooltip.tooltipFooterHeaderFormatter(items[0])];
-                // build the values
-                s = s.concat(tooltip.bodyFormatter(items));
-                // footer
-                s.push(tooltip.tooltipFooterHeaderFormatter(items[0], true));
-                return s;
-            };
-            /**
-             * Removes and destroys the tooltip and its elements.
-             *
-             * @function Highcharts.Tooltip#destroy
-             */
-            Tooltip.prototype.destroy = function () {
-                // Destroy and clear local variables
-                if (this.label) {
-                    this.label = this.label.destroy();
-                }
-                if (this.split && this.tt) {
-                    this.cleanSplit(this.chart, true);
-                    this.tt = this.tt.destroy();
-                }
-                if (this.renderer) {
-                    this.renderer = this.renderer.destroy();
-                    discardElement(this.container);
-                }
-                U.clearTimeout(this.hideTimer);
-                U.clearTimeout(this.tooltipTimeout);
-            };
-            /**
-             * Extendable method to get the anchor position of the tooltip
-             * from a point or set of points
-             *
-             * @private
-             * @function Highcharts.Tooltip#getAnchor
-             *
-             * @param {Highcharts.Point|Array<Highcharts.Point>} points
-             *
-             * @param {Highcharts.PointerEventObject} [mouseEvent]
-             *
-             * @return {Array<number>}
-             */
-            Tooltip.prototype.getAnchor = function (points, mouseEvent) {
-                var ret,
-                    chart = this.chart,
-                    pointer = chart.pointer,
-                    inverted = chart.inverted,
-                    plotTop = chart.plotTop,
-                    plotLeft = chart.plotLeft,
-                    plotX = 0,
-                    plotY = 0,
-                    yAxis,
-                    xAxis;
-                points = splat(points);
-                // When tooltip follows mouse, relate the position to the mouse
-                if (this.followPointer && mouseEvent) {
-                    if (typeof mouseEvent.chartX === 'undefined') {
-                        mouseEvent = pointer.normalize(mouseEvent);
-                    }
-                    ret = [
-                        mouseEvent.chartX - plotLeft,
-                        mouseEvent.chartY - plotTop
-                    ];
-                    // Some series types use a specificly calculated tooltip position for
-                    // each point
-                }
-                else if (points[0].tooltipPos) {
-                    ret = points[0].tooltipPos;
-                    // When shared, use the average position
-                }
-                else {
-                    points.forEach(function (point) {
-                        yAxis = point.series.yAxis;
-                        xAxis = point.series.xAxis;
-                        plotX += point.plotX +
-                            (!inverted && xAxis ? xAxis.left - plotLeft : 0);
-                        plotY += (point.plotLow ?
-                            (point.plotLow + point.plotHigh) / 2 :
-                            point.plotY) + (!inverted && yAxis ? yAxis.top - plotTop : 0); // #1151
-                    });
-                    plotX /= points.length;
-                    plotY /= points.length;
-                    ret = [
-                        inverted ? chart.plotWidth - plotY : plotX,
-                        this.shared && !inverted && points.length > 1 && mouseEvent ?
-                            // place shared tooltip next to the mouse (#424)
-                            mouseEvent.chartY - plotTop :
-                            inverted ? chart.plotHeight - plotX : plotY
-                    ];
-                }
-                return ret.map(Math.round);
-            };
-            /**
-             * Get the optimal date format for a point, based on a range.
-             *
-             * @private
-             * @function Highcharts.Tooltip#getDateFormat
-             *
-             * @param {number} range
-             *        The time range
-             *
-             * @param {number} date
-             *        The date of the point in question
-             *
-             * @param {number} startOfWeek
-             *        An integer representing the first day of the week, where 0 is
-             *        Sunday.
-             *
-             * @param {Highcharts.Dictionary<string>} dateTimeLabelFormats
-             *        A map of time units to formats.
-             *
-             * @return {string}
-             *         The optimal date format for a point.
-             */
-            Tooltip.prototype.getDateFormat = function (range, date, startOfWeek, dateTimeLabelFormats) {
-                var time = this.chart.time, dateStr = time.dateFormat('%m-%d %H:%M:%S.%L', date), format, n, blank = '01-01 00:00:00.000', strpos = {
-                        millisecond: 15,
-                        second: 12,
-                        minute: 9,
-                        hour: 6,
-                        day: 3
-                    }, lastN = 'millisecond'; // for sub-millisecond data, #4223
-                    for (n in timeUnits) { // eslint-disable-line guard-for-in
-                        // If the range is exactly one week and we're looking at a
-                        // Sunday/Monday, go for the week format
-                        if (range === timeUnits.week &&
-                            +time.dateFormat('%w', date) === startOfWeek &&
-                            dateStr.substr(6) === blank.substr(6)) {
-                            n = 'week';
-                        break;
-                    }
-                    // The first format that is too great for the range
-                    if (timeUnits[n] > range) {
-                        n = lastN;
-                        break;
-                    }
-                    // If the point is placed every day at 23:59, we need to show
-                    // the minutes as well. #2637.
-                    if (strpos[n] &&
-                        dateStr.substr(strpos[n]) !== blank.substr(strpos[n])) {
-                        break;
-                    }
-                    // Weeks are outside the hierarchy, only apply them on
-                    // Mondays/Sundays like in the first condition
-                    if (n !== 'week') {
-                        lastN = n;
-                    }
-                }
-                if (n) {
-                    format = time.resolveDTLFormat(dateTimeLabelFormats[n]).main;
-                }
-                return format;
-            };
-            /**
-             * Creates the Tooltip label element if it does not exist, then returns it.
-             *
-             * @function Highcharts.Tooltip#getLabel
-             * @return {Highcharts.SVGElement}
-             */
-            Tooltip.prototype.getLabel = function () {
-                var _a,
-                    _b;
-                var tooltip = this,
-                    renderer = this.chart.renderer,
-                    styledMode = this.chart.styledMode,
-                    options = this.options,
-                    className = ('tooltip' + (defined(options.className) ?
-                        ' ' + options.className :
-                        '')),
-                    pointerEvents = (((_a = options.style) === null || _a === void 0 ? void 0 : _a.pointerEvents) ||
-                        (!this.followPointer && options.stickOnContact ? 'auto' : 'none')),
-                    container,
-                    set,
-                    onMouseEnter = function () {
-                        tooltip.inContact = true;
-                }, onMouseLeave = function () {
-                    var series = tooltip.chart.hoverSeries;
-                    tooltip.inContact = false;
-                    if (series &&
-                        series.onMouseOut) {
-                        series.onMouseOut();
-                    }
-                };
-                if (!this.label) {
-                    if (this.outside) {
-                        /**
-                         * Reference to the tooltip's container, when
-                         * [Highcharts.Tooltip#outside] is set to true, otherwise
-                         * it's undefined.
-                         *
-                         * @name Highcharts.Tooltip#container
-                         * @type {Highcharts.HTMLDOMElement|undefined}
-                         */
-                        this.container = container = H.doc.createElement('div');
-                        container.className = 'highcharts-tooltip-container';
-                        css(container, {
-                            position: 'absolute',
-                            top: '1px',
-                            pointerEvents: pointerEvents,
-                            zIndex: 3
-                        });
-                        H.doc.body.appendChild(container);
-                        /**
-                         * Reference to the tooltip's renderer, when
-                         * [Highcharts.Tooltip#outside] is set to true, otherwise
-                         * it's undefined.
-                         *
-                         * @name Highcharts.Tooltip#renderer
-                         * @type {Highcharts.SVGRenderer|undefined}
-                         */
-                        this.renderer = renderer = new H.Renderer(container, 0, 0, (_b = this.chart.options.chart) === null || _b === void 0 ? void 0 : _b.style, void 0, void 0, renderer.styledMode);
-                    }
-                    // Create the label
-                    if (this.split) {
-                        this.label = renderer.g(className);
-                    }
-                    else {
-                        this.label = renderer
-                            .label('', 0, 0, options.shape || 'callout', null, null, options.useHTML, null, className)
-                            .attr({
-                            padding: options.padding,
-                            r: options.borderRadius
-                        });
-                        if (!styledMode) {
-                            this.label
-                                .attr({
-                                fill: options.backgroundColor,
-                                'stroke-width': options.borderWidth
-                            })
-                                // #2301, #2657
-                                .css(options.style)
-                                .css({ pointerEvents: pointerEvents })
-                                .shadow(options.shadow);
-                        }
-                    }
-                    if (styledMode) {
-                        // Apply the drop-shadow filter
-                        this.applyFilter();
-                        this.label.addClass('highcharts-tooltip-' + this.chart.index);
-                    }
-                    // Split tooltip use updateTooltipContainer to position the tooltip
-                    // container.
-                    if (tooltip.outside && !tooltip.split) {
-                        var label_1 = this.label;
-                        var xSetter_1 = label_1.xSetter,
-                            ySetter_1 = label_1.ySetter;
-                        label_1.xSetter = function (value) {
-                            xSetter_1.call(label_1, tooltip.distance);
-                            container.style.left = value + 'px';
-                        };
-                        label_1.ySetter = function (value) {
-                            ySetter_1.call(label_1, tooltip.distance);
-                            container.style.top = value + 'px';
-                        };
-                    }
-                    this.label
-                        .on('mouseenter', onMouseEnter)
-                        .on('mouseleave', onMouseLeave)
-                        .attr({ zIndex: 8 })
-                        .add();
-                }
-                return this.label;
-            };
-            /**
-             * Place the tooltip in a chart without spilling over
-             * and not covering the point it self.
-             *
-             * @private
-             * @function Highcharts.Tooltip#getPosition
-             *
-             * @param {number} boxWidth
-             *
-             * @param {number} boxHeight
-             *
-             * @param {Highcharts.Point} point
-             *
-             * @return {Highcharts.PositionObject}
-             */
-            Tooltip.prototype.getPosition = function (boxWidth, boxHeight, point) {
-                var chart = this.chart,
-                    distance = this.distance,
-                    ret = {}, 
-                    // Don't use h if chart isn't inverted (#7242) ???
-                    h = (chart.inverted && point.h) || 0, // #4117 ???
-                    swapped,
-                    outside = this.outside,
-                    outerWidth = outside ?
-                        // substract distance to prevent scrollbars
-                        doc.documentElement.clientWidth - 2 * distance :
-                        chart.chartWidth,
-                    outerHeight = outside ?
-                        Math.max(doc.body.scrollHeight,
-                    doc.documentElement.scrollHeight,
-                    doc.body.offsetHeight,
-                    doc.documentElement.offsetHeight,
-                    doc.documentElement.clientHeight) :
-                        chart.chartHeight,
-                    chartPosition = chart.pointer.getChartPosition(),
-                    containerScaling = chart.containerScaling,
-                    scaleX = function (val) { return ( // eslint-disable-line no-confusing-arrow
-                    containerScaling ? val * containerScaling.scaleX : val); },
-                    scaleY = function (val) { return ( // eslint-disable-line no-confusing-arrow
-                    containerScaling ? val * containerScaling.scaleY : val); }, 
-                    // Build parameter arrays for firstDimension()/secondDimension()
-                    buildDimensionArray = function (dim) {
-                        var isX = dim === 'x';
-                    return [
-                        dim,
-                        isX ? outerWidth : outerHeight,
-                        isX ? boxWidth : boxHeight
-                    ].concat(outside ? [
-                        // If we are using tooltip.outside, we need to scale the
-                        // position to match scaling of the container in case there
-                        // is a transform/zoom on the container. #11329
-                        isX ? scaleX(boxWidth) : scaleY(boxHeight),
-                        isX ? chartPosition.left - distance +
-                            scaleX(point.plotX + chart.plotLeft) :
-                            chartPosition.top - distance +
-                                scaleY(point.plotY + chart.plotTop),
-                        0,
-                        isX ? outerWidth : outerHeight
-                    ] : [
-                        // Not outside, no scaling is needed
-                        isX ? boxWidth : boxHeight,
-                        isX ? point.plotX + chart.plotLeft :
-                            point.plotY + chart.plotTop,
-                        isX ? chart.plotLeft : chart.plotTop,
-                        isX ? chart.plotLeft + chart.plotWidth :
-                            chart.plotTop + chart.plotHeight
-                    ]);
-                }, first = buildDimensionArray('y'), second = buildDimensionArray('x'), 
-                // The far side is right or bottom
-                preferFarSide = !this.followPointer && pick(point.ttBelow, !chart.inverted === !!point.negative), // #4984
-                /*
-                 * Handle the preferred dimension. When the preferred dimension is
-                 * tooltip on top or bottom of the point, it will look for space
-                 * there.
-                 *
-                 * @private
-                 */
-                firstDimension = function (dim, outerSize, innerSize, scaledInnerSize, // #11329
-                point, min, max) {
-                    var scaledDist = dim === 'y' ?
-                            scaleY(distance) : scaleX(distance),
-                        scaleDiff = (innerSize - scaledInnerSize) / 2,
-                        roomLeft = scaledInnerSize < point - distance,
-                        roomRight = point + distance + scaledInnerSize < outerSize,
-                        alignedLeft = point - scaledDist - innerSize + scaleDiff,
-                        alignedRight = point + scaledDist - scaleDiff;
-                    if (preferFarSide && roomRight) {
-                        ret[dim] = alignedRight;
-                    }
-                    else if (!preferFarSide && roomLeft) {
-                        ret[dim] = alignedLeft;
-                    }
-                    else if (roomLeft) {
-                        ret[dim] = Math.min(max - scaledInnerSize, alignedLeft - h < 0 ? alignedLeft : alignedLeft - h);
-                    }
-                    else if (roomRight) {
-                        ret[dim] = Math.max(min, alignedRight + h + innerSize > outerSize ?
-                            alignedRight :
-                            alignedRight + h);
-                    }
-                    else {
-                        return false;
-                    }
-                }, 
-                /*
-                 * Handle the secondary dimension. If the preferred dimension is
-                 * tooltip on top or bottom of the point, the second dimension is to
-                 * align the tooltip above the point, trying to align center but
-                 * allowing left or right align within the chart box.
-                 *
-                 * @private
-                 */
-                secondDimension = function (dim, outerSize, innerSize, scaledInnerSize, // #11329
-                point) {
-                    var retVal;
-                    // Too close to the edge, return false and swap dimensions
-                    if (point < distance || point > outerSize - distance) {
-                        retVal = false;
-                        // Align left/top
-                    }
-                    else if (point < innerSize / 2) {
-                        ret[dim] = 1;
-                        // Align right/bottom
-                    }
-                    else if (point > outerSize - scaledInnerSize / 2) {
-                        ret[dim] = outerSize - scaledInnerSize - 2;
-                        // Align center
-                    }
-                    else {
-                        ret[dim] = point - innerSize / 2;
-                    }
-                    return retVal;
-                }, 
-                /*
-                 * Swap the dimensions
-                 */
-                swap = function (count) {
-                    var temp = first;
-                    first = second;
-                    second = temp;
-                    swapped = count;
-                }, run = function () {
-                    if (firstDimension.apply(0, first) !== false) {
-                        if (secondDimension.apply(0, second) === false &&
-                            !swapped) {
-                            swap(true);
-                            run();
-                        }
-                    }
-                    else if (!swapped) {
-                        swap(true);
-                        run();
-                    }
-                    else {
-                        ret.x = ret.y = 0;
-                    }
-                };
-                // Under these conditions, prefer the tooltip on the side of the point
-                if (chart.inverted || this.len > 1) {
-                    swap();
-                }
-                run();
-                return ret;
-            };
-            /**
-             * Get the best X date format based on the closest point range on the axis.
-             *
-             * @private
-             * @function Highcharts.Tooltip#getXDateFormat
-             *
-             * @param {Highcharts.Point} point
-             *
-             * @param {Highcharts.TooltipOptions} options
-             *
-             * @param {Highcharts.Axis} xAxis
-             *
-             * @return {string}
-             */
-            Tooltip.prototype.getXDateFormat = function (point, options, xAxis) {
-                var xDateFormat,
-                    dateTimeLabelFormats = options.dateTimeLabelFormats,
-                    closestPointRange = xAxis && xAxis.closestPointRange;
-                if (closestPointRange) {
-                    xDateFormat = this.getDateFormat(closestPointRange, point.x, xAxis.options.startOfWeek, dateTimeLabelFormats);
-                }
-                else {
-                    xDateFormat = dateTimeLabelFormats.day;
-                }
-                return xDateFormat || dateTimeLabelFormats.year; // #2546, 2581
-            };
-            /**
-             * Hides the tooltip with a fade out animation.
-             *
-             * @function Highcharts.Tooltip#hide
-             *
-             * @param {number} [delay]
-             *        The fade out in milliseconds. If no value is provided the value
-             *        of the tooltip.hideDelay option is used. A value of 0 disables
-             *        the fade out animation.
-             */
-            Tooltip.prototype.hide = function (delay) {
-                var tooltip = this;
-                // disallow duplicate timers (#1728, #1766)
-                U.clearTimeout(this.hideTimer);
-                delay = pick(delay, this.options.hideDelay, 500);
-                if (!this.isHidden) {
-                    this.hideTimer = syncTimeout(function () {
-                        // If there is a delay, do fadeOut with the default duration. If
-                        // the hideDelay is 0, we assume no animation is wanted, so we
-                        // pass 0 duration. #12994.
-                        tooltip.getLabel().fadeOut(delay ? void 0 : delay);
-                        tooltip.isHidden = true;
-                    }, delay);
-                }
-            };
-            /**
-             * @private
-             * @function Highcharts.Tooltip#init
-             *
-             * @param {Highcharts.Chart} chart
-             *        The chart instance.
-             *
-             * @param {Highcharts.TooltipOptions} options
-             *        Tooltip options.
-             */
-            Tooltip.prototype.init = function (chart, options) {
-                /**
-                 * Chart of the tooltip.
-                 *
-                 * @readonly
-                 * @name Highcharts.Tooltip#chart
-                 * @type {Highcharts.Chart}
-                 */
-                this.chart = chart;
-                /**
-                 * Used tooltip options.
-                 *
-                 * @readonly
-                 * @name Highcharts.Tooltip#options
-                 * @type {Highcharts.TooltipOptions}
-                 */
-                this.options = options;
-                /**
-                 * List of crosshairs.
-                 *
-                 * @private
-                 * @readonly
-                 * @name Highcharts.Tooltip#crosshairs
-                 * @type {Array<null>}
-                 */
-                this.crosshairs = [];
-                /**
-                 * Current values of x and y when animating.
-                 *
-                 * @private
-                 * @readonly
-                 * @name Highcharts.Tooltip#now
-                 * @type {Highcharts.PositionObject}
-                 */
-                this.now = { x: 0, y: 0 };
-                /**
-                 * Tooltips are initially hidden.
-                 *
-                 * @private
-                 * @readonly
-                 * @name Highcharts.Tooltip#isHidden
-                 * @type {boolean}
-                 */
-                this.isHidden = true;
-                /**
-                 * True, if the tooltip is split into one label per series, with the
-                 * header close to the axis.
-                 *
-                 * @readonly
-                 * @name Highcharts.Tooltip#split
-                 * @type {boolean|undefined}
-                 */
-                this.split = options.split && !chart.inverted && !chart.polar;
-                /**
-                 * When the tooltip is shared, the entire plot area will capture mouse
-                 * movement or touch events.
-                 *
-                 * @readonly
-                 * @name Highcharts.Tooltip#shared
-                 * @type {boolean|undefined}
-                 */
-                this.shared = options.shared || this.split;
-                /**
-                 * Whether to allow the tooltip to render outside the chart's SVG
-                 * element box. By default (false), the tooltip is rendered within the
-                 * chart's SVG element, which results in the tooltip being aligned
-                 * inside the chart area.
-                 *
-                 * @readonly
-                 * @name Highcharts.Tooltip#outside
-                 * @type {boolean}
-                 *
-                 * @todo
-                 * Split tooltip does not support outside in the first iteration. Should
-                 * not be too complicated to implement.
-                 */
-                this.outside = pick(options.outside, Boolean(chart.scrollablePixelsX || chart.scrollablePixelsY));
-            };
-            /**
-             * Returns true, if the pointer is in contact with the tooltip tracker.
-             */
-            Tooltip.prototype.isStickyOnContact = function () {
-                return !!(!this.followPointer &&
-                    this.options.stickOnContact &&
-                    this.inContact);
-            };
-            /**
-             * Moves the tooltip with a soft animation to a new position.
-             *
-             * @private
-             * @function Highcharts.Tooltip#move
-             *
-             * @param {number} x
-             *
-             * @param {number} y
-             *
-             * @param {number} anchorX
-             *
-             * @param {number} anchorY
-             */
-            Tooltip.prototype.move = function (x, y, anchorX, anchorY) {
-                var tooltip = this,
-                    now = tooltip.now,
-                    animate = tooltip.options.animation !== false &&
-                        !tooltip.isHidden &&
-                        // When we get close to the target position, abort animation and
-                        // land on the right place (#3056)
-                        (Math.abs(x - now.x) > 1 || Math.abs(y - now.y) > 1),
-                    skipAnchor = tooltip.followPointer || tooltip.len > 1;
-                // Get intermediate values for animation
-                extend(now, {
-                    x: animate ? (2 * now.x + x) / 3 : x,
-                    y: animate ? (now.y + y) / 2 : y,
-                    anchorX: skipAnchor ?
-                        void 0 :
-                        animate ? (2 * now.anchorX + anchorX) / 3 : anchorX,
-                    anchorY: skipAnchor ?
-                        void 0 :
-                        animate ? (now.anchorY + anchorY) / 2 : anchorY
-                });
-                // Move to the intermediate value
-                tooltip.getLabel().attr(now);
-                tooltip.drawTracker();
-                // Run on next tick of the mouse tracker
-                if (animate) {
-                    // Never allow two timeouts
-                    U.clearTimeout(this.tooltipTimeout);
-                    // Set the fixed interval ticking for the smooth tooltip
-                    this.tooltipTimeout = setTimeout(function () {
-                        // The interval function may still be running during destroy,
-                        // so check that the chart is really there before calling.
-                        if (tooltip) {
-                            tooltip.move(x, y, anchorX, anchorY);
-                        }
-                    }, 32);
-                }
-            };
-            /**
-             * Refresh the tooltip's text and position.
-             *
-             * @function Highcharts.Tooltip#refresh
-             *
-             * @param {Highcharts.Point|Array<Highcharts.Point>} pointOrPoints
-             *        Either a point or an array of points.
-             *
-             * @param {Highcharts.PointerEventObject} [mouseEvent]
-             *        Mouse event, that is responsible for the refresh and should be
-             *        used for the tooltip update.
-             */
-            Tooltip.prototype.refresh = function (pointOrPoints, mouseEvent) {
-                var tooltip = this,
-                    chart = this.chart,
-                    options = tooltip.options,
-                    x,
-                    y,
-                    point = pointOrPoints,
-                    anchor,
-                    textConfig = {},
-                    text,
-                    pointConfig = [],
-                    formatter = options.formatter || tooltip.defaultFormatter,
-                    shared = tooltip.shared,
-                    currentSeries,
-                    styledMode = chart.styledMode;
-                if (!options.enabled) {
-                    return;
-                }
-                U.clearTimeout(this.hideTimer);
-                // get the reference point coordinates (pie charts use tooltipPos)
-                tooltip.followPointer = splat(point)[0].series.tooltipOptions
-                    .followPointer;
-                anchor = tooltip.getAnchor(point, mouseEvent);
-                x = anchor[0];
-                y = anchor[1];
-                // shared tooltip, array is sent over
-                if (shared &&
-                    !(point.series &&
-                        point.series.noSharedTooltip)) {
-                    chart.pointer.applyInactiveState(point);
-                    // Now set hover state for the choosen ones:
-                    point.forEach(function (item) {
-                        item.setState('hover');
-                        pointConfig.push(item.getLabelConfig());
-                    });
-                    textConfig = {
-                        x: point[0].category,
-                        y: point[0].y
-                    };
-                    textConfig.points = pointConfig;
-                    point = point[0];
-                    // single point tooltip
-                }
-                else {
-                    textConfig = point.getLabelConfig();
-                }
-                this.len = pointConfig.length; // #6128
-                text = formatter.call(textConfig, tooltip);
-                // register the current series
-                currentSeries = point.series;
-                this.distance = pick(currentSeries.tooltipOptions.distance, 16);
-                // update the inner HTML
-                if (text === false) {
-                    this.hide();
-                }
-                else {
-                    // update text
-                    if (tooltip.split) {
-                        this.renderSplit(text, splat(pointOrPoints));
-                    }
-                    else {
-                        var label = tooltip.getLabel();
-                        // Prevent the tooltip from flowing over the chart box (#6659)
-                        if (!options.style.width || styledMode) {
-                            label.css({
-                                width: this.chart.spacingBox.width + 'px'
-                            });
-                        }
-                        label.attr({
-                            text: text && text.join ?
-                                text.join('') :
-                                text
-                        });
-                        // Set the stroke color of the box to reflect the point
-                        label.removeClass(/highcharts-color-[\d]+/g)
-                            .addClass('highcharts-color-' +
-                            pick(point.colorIndex, currentSeries.colorIndex));
-                        if (!styledMode) {
-                            label.attr({
-                                stroke: (options.borderColor ||
-                                    point.color ||
-                                    currentSeries.color ||
-                                    '#666666')
-                            });
-                        }
-                        tooltip.updatePosition({
-                            plotX: x,
-                            plotY: y,
-                            negative: point.negative,
-                            ttBelow: point.ttBelow,
-                            h: anchor[2] || 0
-                        });
-                    }
-                    // show it
-                    if (tooltip.isHidden && tooltip.label) {
-                        tooltip.label.attr({
-                            opacity: 1
-                        }).show();
-                    }
-                    tooltip.isHidden = false;
-                }
-                fireEvent(this, 'refresh');
-            };
-            /**
-             * Render the split tooltip. Loops over each point's text and adds
-             * a label next to the point, then uses the distribute function to
-             * find best non-overlapping positions.
-             *
-             * @private
-             * @function Highcharts.Tooltip#renderSplit
-             *
-             * @param {string|Array<(boolean|string)>} labels
-             *
-             * @param {Array<Highcharts.Point>} points
-             */
-            Tooltip.prototype.renderSplit = function (labels, points) {
-                var tooltip = this;
-                var chart = tooltip.chart,
-                    _a = tooltip.chart,
-                    chartWidth = _a.chartWidth,
-                    chartHeight = _a.chartHeight,
-                    plotHeight = _a.plotHeight,
-                    plotLeft = _a.plotLeft,
-                    plotTop = _a.plotTop,
-                    pointer = _a.pointer,
-                    ren = _a.renderer,
-                    _b = _a.scrollablePixelsY,
-                    scrollablePixelsY = _b === void 0 ? 0 : _b,
-                    _c = _a.scrollingContainer,
-                    _d = _c === void 0 ? { scrollLeft: 0,
-                    scrollTop: 0 } : _c,
-                    scrollLeft = _d.scrollLeft,
-                    scrollTop = _d.scrollTop,
-                    styledMode = _a.styledMode,
-                    distance = tooltip.distance,
-                    options = tooltip.options,
-                    positioner = tooltip.options.positioner;
-                // The area which the tooltip should be limited to. Limit to scrollable
-                // plot area if enabled, otherwise limit to the chart container.
-                var bounds = {
-                        left: scrollLeft,
-                        right: scrollLeft + chartWidth,
-                        top: scrollTop,
-                        bottom: scrollTop + chartHeight
-                    };
-                var tooltipLabel = tooltip.getLabel();
-                var headerTop = Boolean(chart.xAxis[0] && chart.xAxis[0].opposite);
-                var distributionBoxTop = plotTop + scrollTop;
-                var headerHeight = 0;
-                var adjustedPlotHeight = plotHeight - scrollablePixelsY;
-                /**
-                 * Calculates the anchor position for the partial tooltip
-                 *
-                 * @private
-                 * @param {Highcharts.Point} point The point related to the tooltip
-                 * @return {object} Returns an object with anchorX and anchorY
-                 */
-                function getAnchor(point) {
-                    var isHeader = point.isHeader,
-                        _a = point.plotX,
-                        plotX = _a === void 0 ? 0 : _a,
-                        _b = point.plotY,
-                        plotY = _b === void 0 ? 0 : _b,
-                        series = point.series;
-                    var anchorX;
-                    var anchorY;
-                    if (isHeader) {
-                        // Set anchorX to plotX
-                        anchorX = plotLeft + plotX;
-                        // Set anchorY to center of visible plot area.
-                        anchorY = plotTop + plotHeight / 2;
-                    }
-                    else {
-                        var xAxis = series.xAxis,
-                            yAxis = series.yAxis;
-                        // Set anchorX to plotX. Limit to within xAxis.
-                        anchorX = xAxis.pos + clamp(plotX, -distance, xAxis.len + distance);
-                        // Set anchorY, limit to the scrollable plot area
-                        if (yAxis.pos + plotY >= scrollTop + plotTop &&
-                            yAxis.pos + plotY <= scrollTop + plotTop + plotHeight - scrollablePixelsY) {
-                            anchorY = yAxis.pos + plotY;
-                        }
-                    }
-                    // Limit values to plot area
-                    anchorX = clamp(anchorX, bounds.left - distance, bounds.right + distance);
-                    return { anchorX: anchorX, anchorY: anchorY };
-                }
-                /**
-                 * Calculates the position of the partial tooltip
-                 *
-                 * @private
-                 * @param {number} anchorX The partial tooltip anchor x position
-                 * @param {number} anchorY The partial tooltip anchor y position
-                 * @param {boolean} isHeader Whether the partial tooltip is a header
-                 * @param {number} boxWidth Width of the partial tooltip
-                 * @return {Highcharts.PositionObject} Returns the partial tooltip x and
-                 * y position
-                 */
-                function defaultPositioner(anchorX, anchorY, isHeader, boxWidth, alignedLeft) {
-                    if (alignedLeft === void 0) { alignedLeft = true; }
-                    var y;
-                    var x;
-                    if (isHeader) {
-                        y = headerTop ? 0 : adjustedPlotHeight;
-                        x = clamp(anchorX - (boxWidth / 2), bounds.left, bounds.right - boxWidth);
-                    }
-                    else {
-                        y = anchorY - distributionBoxTop;
-                        x = alignedLeft ?
-                            anchorX - boxWidth - distance :
-                            anchorX + distance;
-                        x = clamp(x, alignedLeft ? x : bounds.left, bounds.right);
-                    }
-                    // NOTE: y is relative to distributionBoxTop
-                    return { x: x, y: y };
-                }
-                /**
-                 * Updates the attributes and styling of the partial tooltip. Creates a
-                 * new partial tooltip if it does not exists.
-                 *
-                 * @private
-                 * @param {Highcharts.SVGElement|undefined} partialTooltip
-                 *  The partial tooltip to update
-                 * @param {Highcharts.Point} point
-                 *  The point related to the partial tooltip
-                 * @param {boolean|string} str The text for the partial tooltip
-                 * @return {Highcharts.SVGElement} Returns the updated partial tooltip
-                 */
-                function updatePartialTooltip(partialTooltip, point, str) {
-                    var tt = partialTooltip;
-                    var isHeader = point.isHeader,
-                        series = point.series;
-                    var colorClass = 'highcharts-color-' + pick(point.colorIndex, series.colorIndex, 'none');
-                    if (!tt) {
-                        var attribs = {
-                                padding: options.padding,
-                                r: options.borderRadius
-                            };
-                        if (!styledMode) {
-                            attribs.fill = options.backgroundColor;
-                            attribs['stroke-width'] = options.borderWidth;
-                        }
-                        tt = ren
-                            .label('', 0, 0, (options[isHeader ? 'headerShape' : 'shape']) ||
-                            'callout', void 0, void 0, options.useHTML)
-                            .addClass((isHeader ? 'highcharts-tooltip-header ' : '') +
-                            'highcharts-tooltip-box ' +
-                            colorClass)
-                            .attr(attribs)
-                            .add(tooltipLabel);
-                    }
-                    tt.isActive = true;
-                    tt.attr({
-                        text: str
-                    });
-                    if (!styledMode) {
-                        tt.css(options.style)
-                            .shadow(options.shadow)
-                            .attr({
-                            stroke: (options.borderColor ||
-                                point.color ||
-                                series.color ||
-                                '#333333')
-                        });
-                    }
-                    return tt;
-                }
-                // Graceful degradation for legacy formatters
-                if (isString(labels)) {
-                    labels = [false, labels];
-                }
-                // Create the individual labels for header and points, ignore footer
-                var boxes = labels.slice(0,
-                    points.length + 1).reduce(function (boxes,
-                    str,
-                    i) {
-                        if (str !== false && str !== '') {
-                            var point = (points[i - 1] ||
-                                {
-                                    // Item 0 is the header. Instead of this, we could also
-                                    // use the crosshair label
-                                    isHeader: true,
-                                    plotX: points[0].plotX,
-                                    plotY: plotHeight,
-                                    series: {}
-                                });
-                        var isHeader = point.isHeader;
-                        // Store the tooltip label referance on the series
-                        var owner = isHeader ? tooltip : point.series;
-                        var tt = owner.tt = updatePartialTooltip(owner.tt,
-                            point,
-                            str);
-                        // Get X position now, so we can move all to the other side in
-                        // case of overflow
-                        var bBox = tt.getBBox();
-                        var boxWidth = bBox.width + tt.strokeWidth();
-                        if (isHeader) {
-                            headerHeight = bBox.height;
-                            adjustedPlotHeight += headerHeight;
-                            if (headerTop) {
-                                distributionBoxTop -= headerHeight;
-                            }
-                        }
-                        var _a = getAnchor(point),
-                            anchorX = _a.anchorX,
-                            anchorY = _a.anchorY;
-                        if (typeof anchorY === 'number') {
-                            var size = bBox.height + 1;
-                            var boxPosition = (positioner ?
-                                    positioner.call(tooltip,
-                                boxWidth,
-                                size,
-                                point) :
-                                    defaultPositioner(anchorX,
-                                anchorY,
-                                isHeader,
-                                boxWidth));
-                            boxes.push({
-                                // 0-align to the top, 1-align to the bottom
-                                align: positioner ? 0 : void 0,
-                                anchorX: anchorX,
-                                anchorY: anchorY,
-                                boxWidth: boxWidth,
-                                point: point,
-                                rank: pick(boxPosition.rank, isHeader ? 1 : 0),
-                                size: size,
-                                target: boxPosition.y,
-                                tt: tt,
-                                x: boxPosition.x
-                            });
-                        }
-                        else {
-                            // Hide tooltips which anchorY is outside the visible plot
-                            // area
-                            tt.isActive = false;
-                        }
-                    }
-                    return boxes;
-                }, []);
-                // If overflow left then align all labels to the right
-                if (!positioner && boxes.some(function (box) { return box.x < bounds.left; })) {
-                    boxes = boxes.map(function (box) {
-                        var _a = defaultPositioner(box.anchorX,
-                            box.anchorY,
-                            box.point.isHeader,
-                            box.boxWidth,
-                            false),
-                            x = _a.x,
-                            y = _a.y;
-                        return extend(box, {
-                            target: y,
-                            x: x
-                        });
-                    });
-                }
-                // Clean previous run (for missing points)
-                tooltip.cleanSplit();
-                // Distribute and put in place
-                H.distribute(boxes, adjustedPlotHeight);
-                boxes.forEach(function (box) {
-                    var anchorX = box.anchorX,
-                        anchorY = box.anchorY,
-                        pos = box.pos,
-                        x = box.x;
-                    // Put the label in place
-                    box.tt.attr({
-                        visibility: typeof pos === 'undefined' ? 'hidden' : 'inherit',
-                        x: x,
-                        /* NOTE: y should equal pos to be consistent with !split
-                         * tooltip, but is currently relative to plotTop. Is left as is
-                         * to avoid breaking change. Remove distributionBoxTop to make
-                         * it consistent.
-                         */
-                        y: pos + distributionBoxTop,
-                        anchorX: anchorX,
-                        anchorY: anchorY
-                    });
-                });
-                /* If we have a seperate tooltip container, then update the necessary
-                 * container properties.
-                 * Test that tooltip has its own container and renderer before executing
-                 * the operation.
-                 */
-                var container = tooltip.container,
-                    outside = tooltip.outside,
-                    renderer = tooltip.renderer;
-                if (outside && container && renderer) {
-                    // Set container size to fit the tooltip
-                    var _e = tooltipLabel.getBBox(),
-                        width = _e.width,
-                        height = _e.height,
-                        x = _e.x,
-                        y = _e.y;
-                    renderer.setSize(width + x, height + y, false);
-                    // Position the tooltip container to the chart container
-                    var chartPosition = pointer.getChartPosition();
-                    container.style.left = chartPosition.left + 'px';
-                    container.style.top = chartPosition.top + 'px';
-                }
-            };
-            /**
-             * If the `stickOnContact` option is active, this will add a tracker shape.
-             *
-             * @private
-             * @function Highcharts.Tooltip#drawTracker
-             */
-            Tooltip.prototype.drawTracker = function () {
-                var tooltip = this;
-                if (tooltip.followPointer ||
-                    !tooltip.options.stickOnContact) {
-                    if (tooltip.tracker) {
-                        tooltip.tracker.destroy();
-                    }
-                    return;
-                }
-                var chart = tooltip.chart;
-                var label = tooltip.label;
-                var point = chart.hoverPoint;
-                if (!label || !point) {
-                    return;
-                }
-                var box = {
-                        x: 0,
-                        y: 0,
-                        width: 0,
-                        height: 0
-                    };
-                // Combine anchor and tooltip
-                var anchorPos = this.getAnchor(point);
-                var labelBBox = label.getBBox();
-                anchorPos[0] += chart.plotLeft - label.translateX;
-                anchorPos[1] += chart.plotTop - label.translateY;
-                // When the mouse pointer is between the anchor point and the label,
-                // the label should stick.
-                box.x = Math.min(0, anchorPos[0]);
-                box.y = Math.min(0, anchorPos[1]);
-                box.width = (anchorPos[0] < 0 ?
-                    Math.max(Math.abs(anchorPos[0]), (labelBBox.width - anchorPos[0])) :
-                    Math.max(Math.abs(anchorPos[0]), labelBBox.width));
-                box.height = (anchorPos[1] < 0 ?
-                    Math.max(Math.abs(anchorPos[1]), (labelBBox.height - Math.abs(anchorPos[1]))) :
-                    Math.max(Math.abs(anchorPos[1]), labelBBox.height));
-                if (tooltip.tracker) {
-                    tooltip.tracker.attr(box);
-                }
-                else {
-                    tooltip.tracker = label.renderer
-                        .rect(box)
-                        .addClass('highcharts-tracker')
-                        .add(label);
-                    if (!chart.styledMode) {
-                        tooltip.tracker.attr({
-                            fill: 'rgba(0,0,0,0)'
-                        });
-                    }
-                }
-            };
-            /**
-             * @private
-             */
-            Tooltip.prototype.styledModeFormat = function (formatString) {
-                return formatString
-                    .replace('style="font-size: 10px"', 'class="highcharts-header"')
-                    .replace(/style="color:{(point|series)\.color}"/g, 'class="highcharts-color-{$1.colorIndex}"');
-            };
-            /**
-             * Format the footer/header of the tooltip
-             * #3397: abstraction to enable formatting of footer and header
-             *
-             * @private
-             * @function Highcharts.Tooltip#tooltipFooterHeaderFormatter
-             * @param {Highcharts.PointLabelObject} labelConfig
-             * @param {boolean} [isFooter]
-             * @return {string}
-             */
-            Tooltip.prototype.tooltipFooterHeaderFormatter = function (labelConfig, isFooter) {
-                var footOrHead = isFooter ? 'footer' : 'header',
-                    series = labelConfig.series,
-                    tooltipOptions = series.tooltipOptions,
-                    xDateFormat = tooltipOptions.xDateFormat,
-                    xAxis = series.xAxis,
-                    isDateTime = (xAxis &&
-                        xAxis.options.type === 'datetime' &&
-                        isNumber(labelConfig.key)),
-                    formatString = tooltipOptions[footOrHead + 'Format'],
-                    e = {
-                        isFooter: isFooter,
-                        labelConfig: labelConfig
-                    };
-                fireEvent(this, 'headerFormatter', e, function (e) {
-                    // Guess the best date format based on the closest point distance
-                    // (#568, #3418)
-                    if (isDateTime && !xDateFormat) {
-                        xDateFormat = this.getXDateFormat(labelConfig, tooltipOptions, xAxis);
-                    }
-                    // Insert the footer date format if any
-                    if (isDateTime && xDateFormat) {
-                        ((labelConfig.point && labelConfig.point.tooltipDateKeys) ||
-                            ['key']).forEach(function (key) {
-                            formatString = formatString.replace('{point.' + key + '}', '{point.' + key + ':' + xDateFormat + '}');
-                        });
-                    }
-                    // Replace default header style with class name
-                    if (series.chart.styledMode) {
-                        formatString = this.styledModeFormat(formatString);
-                    }
-                    e.text = format(formatString, {
-                        point: labelConfig,
-                        series: series
-                    }, this.chart);
-                });
-                return e.text;
-            };
-            /**
-             * Updates the tooltip with the provided tooltip options.
-             *
-             * @function Highcharts.Tooltip#update
-             *
-             * @param {Highcharts.TooltipOptions} options
-             *        The tooltip options to update.
-             */
-            Tooltip.prototype.update = function (options) {
-                this.destroy();
-                // Update user options (#6218)
-                merge(true, this.chart.options.tooltip.userOptions, options);
-                this.init(this.chart, merge(true, this.options, options));
-            };
-            /**
-             * Find the new position and perform the move
-             *
-             * @private
-             * @function Highcharts.Tooltip#updatePosition
-             *
-             * @param {Highcharts.Point} point
-             */
-            Tooltip.prototype.updatePosition = function (point) {
-                var chart = this.chart,
-                    pointer = chart.pointer,
-                    label = this.getLabel(),
-                    pos,
-                    anchorX = point.plotX + chart.plotLeft,
-                    anchorY = point.plotY + chart.plotTop,
-                    pad;
-                // Needed for outside: true (#11688)
-                var chartPosition = pointer.getChartPosition();
-                pos = (this.options.positioner || this.getPosition).call(this, label.width, label.height, point);
-                // Set the renderer size dynamically to prevent document size to change
-                if (this.outside) {
-                    pad = (this.options.borderWidth || 0) + 2 * this.distance;
-                    this.renderer.setSize(label.width + pad, label.height + pad, false);
-                    // Anchor and tooltip container need scaling if chart container has
-                    // scale transform/css zoom. #11329.
-                    var containerScaling = chart.containerScaling;
-                    if (containerScaling) {
-                        css(this.container, {
-                            transform: "scale(" + containerScaling.scaleX + ", " + containerScaling.scaleY + ")"
-                        });
-                        anchorX *= containerScaling.scaleX;
-                        anchorY *= containerScaling.scaleY;
-                    }
-                    anchorX += chartPosition.left - pos.x;
-                    anchorY += chartPosition.top - pos.y;
-                }
-                // do the move
-                this.move(Math.round(pos.x), Math.round(pos.y || 0), // can be undefined (#3977)
-                anchorX, anchorY);
-            };
-            return Tooltip;
-        }());
-        H.Tooltip = Tooltip;
-
-        return H.Tooltip;
-    });
-    _registerModule(_modules, 'Core/Pointer.js', [_modules['Core/Color/Color.js'], _modules['Core/Globals.js'], _modules['Core/Tooltip.js'], _modules['Core/Utilities.js']], function (Color, H, Tooltip, U) {
-        /* *
-         *
-         *  (c) 2010-2020 Torstein Honsi
-         *
-         *  License: www.highcharts.com/license
-         *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
-         *
-         * */
-        var color = Color.parse;
-        var charts = H.charts,
-            noop = H.noop;
-        var addEvent = U.addEvent,
-            attr = U.attr,
-            css = U.css,
-            defined = U.defined,
-            extend = U.extend,
-            find = U.find,
-            fireEvent = U.fireEvent,
-            isNumber = U.isNumber,
-            isObject = U.isObject,
-            objectEach = U.objectEach,
-            offset = U.offset,
-            pick = U.pick,
-            splat = U.splat;
-        /**
-         * One position in relation to an axis.
-         *
-         * @interface Highcharts.PointerAxisCoordinateObject
-         */ /**
-        * Related axis.
-        *
-        * @name Highcharts.PointerAxisCoordinateObject#axis
-        * @type {Highcharts.Axis}
-        */ /**
-        * Axis value.
-        *
-        * @name Highcharts.PointerAxisCoordinateObject#value
-        * @type {number}
-        */
-        /**
-         * Positions in terms of axis values.
-         *
-         * @interface Highcharts.PointerAxisCoordinatesObject
-         */ /**
-        * Positions on the x-axis.
-        * @name Highcharts.PointerAxisCoordinatesObject#xAxis
-        * @type {Array<Highcharts.PointerAxisCoordinateObject>}
-        */ /**
-        * Positions on the y-axis.
-        * @name Highcharts.PointerAxisCoordinatesObject#yAxis
-        * @type {Array<Highcharts.PointerAxisCoordinateObject>}
-        */
-        /**
-         * Pointer coordinates.
-         *
-         * @interface Highcharts.PointerCoordinatesObject
-         */ /**
-        * @name Highcharts.PointerCoordinatesObject#chartX
-        * @type {number}
-        */ /**
-        * @name Highcharts.PointerCoordinatesObject#chartY
-        * @type {number}
-        */
-        /**
-         * A native browser mouse or touch event, extended with position information
-         * relative to the {@link Chart.container}.
-         *
-         * @interface Highcharts.PointerEventObject
-         * @extends global.PointerEvent
-         */ /**
-        * The X coordinate of the pointer interaction relative to the chart.
-        *
-        * @name Highcharts.PointerEventObject#chartX
-        * @type {number}
-        */ /**
-        * The Y coordinate of the pointer interaction relative to the chart.
-        *
-        * @name Highcharts.PointerEventObject#chartY
-        * @type {number}
-        */
-        /**
-         * Axis-specific data of a selection.
-         *
-         * @interface Highcharts.SelectDataObject
-         */ /**
-        * @name Highcharts.SelectDataObject#axis
-        * @type {Highcharts.Axis}
-        */ /**
-        * @name Highcharts.SelectDataObject#max
-        * @type {number}
-        */ /**
-        * @name Highcharts.SelectDataObject#min
-        * @type {number}
-        */
-        /**
-         * Object for select events.
-         *
-         * @interface Highcharts.SelectEventObject
-         */ /**
-        * @name Highcharts.SelectEventObject#originalEvent
-        * @type {global.Event}
-        */ /**
-        * @name Highcharts.SelectEventObject#xAxis
-        * @type {Array<Highcharts.SelectDataObject>}
-        */ /**
-        * @name Highcharts.SelectEventObject#yAxis
-        * @type {Array<Highcharts.SelectDataObject>}
-        */
-        ''; // detach doclets above
-        /* eslint-disable no-invalid-this, valid-jsdoc */
-        /**
-         * The mouse and touch tracker object. Each {@link Chart} item has one
-         * assosiated Pointer item that can be accessed from the  {@link Chart.pointer}
-         * property.
-         *
-         * @class
-         * @name Highcharts.Pointer
-         *
-         * @param {Highcharts.Chart} chart
-         * The chart instance.
-         *
-         * @param {Highcharts.Options} options
-         * The root options object. The pointer uses options from the chart and
-         * tooltip structures.
-         */
-        var Pointer = /** @class */ (function () {
-                /* *
-                 *
-                 *  Constructors
-                 *
-                 * */
-                function Pointer(chart, options) {
-                    this.lastValidTouch = {};
-                this.pinchDown = [];
-                this.runChartClick = false;
-                this.chart = chart;
-                this.hasDragged = false;
-                this.options = options;
-                this.unbindContainerMouseLeave = function () { };
-                this.unbindContainerMouseEnter = function () { };
-                this.init(chart, options);
-            }
-            /* *
-             *
-             *  Functions
-             *
-             * */
-            /**
-             * Set inactive state to all series that are not currently hovered,
-             * or, if `inactiveOtherPoints` is set to true, set inactive state to
-             * all points within that series.
-             *
-             * @private
-             * @function Highcharts.Pointer#applyInactiveState
-             * @param {Array<Highcharts.Point>} points
-             * Currently hovered points
-             */
-            Pointer.prototype.applyInactiveState = function (points) {
-                var activeSeries = [],
-                    series;
-                // Get all active series from the hovered points
-                (points || []).forEach(function (item) {
-                    series = item.series;
-                    // Include itself
-                    activeSeries.push(series);
-                    // Include parent series
-                    if (series.linkedParent) {
-                        activeSeries.push(series.linkedParent);
-                    }
-                    // Include all child series
-                    if (series.linkedSeries) {
-                        activeSeries = activeSeries.concat(series.linkedSeries);
-                    }
-                    // Include navigator series
-                    if (series.navigatorSeries) {
-                        activeSeries.push(series.navigatorSeries);
-                    }
-                });
-                // Now loop over all series, filtering out active series
-                this.chart.series.forEach(function (inactiveSeries) {
-                    if (activeSeries.indexOf(inactiveSeries) === -1) {
-                        // Inactive series
-                        inactiveSeries.setState('inactive', true);
-                    }
-                    else if (inactiveSeries.options.inactiveOtherPoints) {
-                        // Active series, but other points should be inactivated
-                        inactiveSeries.setAllPointsToState('inactive');
-                    }
-                });
-            };
-            /**
-             * Destroys the Pointer object and disconnects DOM events.
-             *
-             * @function Highcharts.Pointer#destroy
-             */
-            Pointer.prototype.destroy = function () {
-                var pointer = this;
-                if (typeof pointer.unDocMouseMove !== 'undefined') {
-                    pointer.unDocMouseMove();
-                }
-                this.unbindContainerMouseLeave();
-                if (!H.chartCount) {
-                    if (H.unbindDocumentMouseUp) {
-                        H.unbindDocumentMouseUp = H.unbindDocumentMouseUp();
-                    }
-                    if (H.unbindDocumentTouchEnd) {
-                        H.unbindDocumentTouchEnd = H.unbindDocumentTouchEnd();
-                    }
-                }
-                // memory and CPU leak
-                clearInterval(pointer.tooltipTimeout);
-                objectEach(pointer, function (_val, prop) {
-                    pointer[prop] = void 0;
-                });
-            };
-            /**
-             * Perform a drag operation in response to a mousemove event while the mouse
-             * is down.
-             *
-             * @private
-             * @function Highcharts.Pointer#drag
-             *
-             * @param {Highcharts.PointerEventObject} e
-             *
-             * @return {void}
-             */
-            Pointer.prototype.drag = function (e) {
-                var chart = this.chart,
-                    chartOptions = chart.options.chart,
-                    chartX = e.chartX,
-                    chartY = e.chartY,
-                    zoomHor = this.zoomHor,
-                    zoomVert = this.zoomVert,
-                    plotLeft = chart.plotLeft,
-                    plotTop = chart.plotTop,
-                    plotWidth = chart.plotWidth,
-                    plotHeight = chart.plotHeight,
-                    clickedInside,
-                    size,
-                    selectionMarker = this.selectionMarker,
-                    mouseDownX = (this.mouseDownX || 0),
-                    mouseDownY = (this.mouseDownY || 0),
-                    panningEnabled = isObject(chartOptions.panning) ?
-                        chartOptions.panning && chartOptions.panning.enabled :
-                        chartOptions.panning,
-                    panKey = (chartOptions.panKey && e[chartOptions.panKey + 'Key']);
-                // If the device supports both touch and mouse (like IE11), and we are
-                // touch-dragging inside the plot area, don't handle the mouse event.
-                // #4339.
-                if (selectionMarker && selectionMarker.touch) {
-                    return;
-                }
-                // If the mouse is outside the plot area, adjust to cooordinates
-                // inside to prevent the selection marker from going outside
-                if (chartX < plotLeft) {
-                    chartX = plotLeft;
-                }
-                else if (chartX > plotLeft + plotWidth) {
-                    chartX = plotLeft + plotWidth;
-                }
-                if (chartY < plotTop) {
-                    chartY = plotTop;
-                }
-                else if (chartY > plotTop + plotHeight) {
-                    chartY = plotTop + plotHeight;
-                }
-                // determine if the mouse has moved more than 10px
-                this.hasDragged = Math.sqrt(Math.pow(mouseDownX - chartX, 2) +
-                    Math.pow(mouseDownY - chartY, 2));
-                if (this.hasDragged > 10) {
-                    clickedInside = chart.isInsidePlot(mouseDownX - plotLeft, mouseDownY - plotTop);
-                    // make a selection
-                    if (chart.hasCartesianSeries &&
-                        (this.zoomX || this.zoomY) &&
-                        clickedInside &&
-                        !panKey) {
-                        if (!selectionMarker) {
-                            this.selectionMarker = selectionMarker =
-                                chart.renderer.rect(plotLeft, plotTop, zoomHor ? 1 : plotWidth, zoomVert ? 1 : plotHeight, 0)
-                                    .attr({
-                                    'class': 'highcharts-selection-marker',
-                                    zIndex: 7
-                                })
-                                    .add();
-                            if (!chart.styledMode) {
-                                selectionMarker.attr({
-                                    fill: (chartOptions.selectionMarkerFill ||
-                                        color('#335cad')
-                                            .setOpacity(0.25).get())
-                                });
-                            }
-                        }
-                    }
-                    // adjust the width of the selection marker
-                    if (selectionMarker && zoomHor) {
-                        size = chartX - mouseDownX;
-                        selectionMarker.attr({
-                            width: Math.abs(size),
-                            x: (size > 0 ? 0 : size) + mouseDownX
-                        });
-                    }
-                    // adjust the height of the selection marker
-                    if (selectionMarker && zoomVert) {
-                        size = chartY - mouseDownY;
-                        selectionMarker.attr({
-                            height: Math.abs(size),
-                            y: (size > 0 ? 0 : size) + mouseDownY
-                        });
-                    }
-                    // panning
-                    if (clickedInside &&
-                        !selectionMarker &&
-                        panningEnabled) {
-                        chart.pan(e, chartOptions.panning);
-                    }
-                }
-            };
-            /**
-             * Start a drag operation.
-             *
-             * @private
-             * @function Highcharts.Pointer#dragStart
-             *
-             * @param {Highcharts.PointerEventObject} e
-             *
-             * @return {void}
-             */
-            Pointer.prototype.dragStart = function (e) {
-                var chart = this.chart;
-                // Record the start position
-                chart.mouseIsDown = e.type;
-                chart.cancelClick = false;
-                chart.mouseDownX = this.mouseDownX = e.chartX;
-                chart.mouseDownY = this.mouseDownY = e.chartY;
-            };
-            /**
-             * On mouse up or touch end across the entire document, drop the selection.
-             *
-             * @private
-             * @function Highcharts.Pointer#drop
-             *
-             * @param {global.Event} e
-             */
-            Pointer.prototype.drop = function (e) {
-                var pointer = this,
-                    chart = this.chart,
-                    hasPinched = this.hasPinched;
-                if (this.selectionMarker) {
-                    var selectionData = {
-                            originalEvent: e,
-                            xAxis: [],
-                            yAxis: []
-                        },
-                        selectionBox = this.selectionMarker,
-                        selectionLeft = selectionBox.attr ?
-                            selectionBox.attr('x') :
-                            selectionBox.x,
-                        selectionTop = selectionBox.attr ?
-                            selectionBox.attr('y') :
-                            selectionBox.y,
-                        selectionWidth = selectionBox.attr ?
-                            selectionBox.attr('width') :
-                            selectionBox.width,
-                        selectionHeight = selectionBox.attr ?
-                            selectionBox.attr('height') :
-                            selectionBox.height,
-                        runZoom;
-                    // a selection has been made
-                    if (this.hasDragged || hasPinched) {
-                        // record each axis' min and max
-                        chart.axes.forEach(function (axis) {
-                            if (axis.zoomEnabled &&
-                                defined(axis.min) &&
-                                (hasPinched ||
-                                    pointer[{
-                                        xAxis: 'zoomX',
-                                        yAxis: 'zoomY'
-                                    }[axis.coll]]) &&
-                                isNumber(selectionLeft) &&
-                                isNumber(selectionTop)) { // #859, #3569
-                                var horiz = axis.horiz,
-                                    minPixelPadding = e.type === 'touchend' ?
-                                        axis.minPixelPadding :
-                                        0, // #1207, #3075
-                                    selectionMin = axis.toValue((horiz ? selectionLeft : selectionTop) +
-                                        minPixelPadding),
-                                    selectionMax = axis.toValue((horiz ?
-                                        selectionLeft + selectionWidth :
-                                        selectionTop + selectionHeight) - minPixelPadding);
-                                selectionData[axis.coll].push({
-                                    axis: axis,
-                                    // Min/max for reversed axes
-                                    min: Math.min(selectionMin, selectionMax),
-                                    max: Math.max(selectionMin, selectionMax)
-                                });
-                                runZoom = true;
-                            }
-                        });
-                        if (runZoom) {
-                            fireEvent(chart, 'selection', selectionData, function (args) {
-                                chart.zoom(extend(args, hasPinched ?
-                                    { animation: false } :
-                                    null));
-                            });
-                        }
-                    }
-                    if (isNumber(chart.index)) {
-                        this.selectionMarker = this.selectionMarker.destroy();
-                    }
-                    // Reset scaling preview
-                    if (hasPinched) {
-                        this.scaleGroups();
-                    }
-                }
-                // Reset all. Check isNumber because it may be destroyed on mouse up
-                // (#877)
-                if (chart && isNumber(chart.index)) {
-                    css(chart.container, { cursor: chart._cursor });
-                    chart.cancelClick = this.hasDragged > 10; // #370
-                    chart.mouseIsDown = this.hasDragged = this.hasPinched = false;
-                    this.pinchDown = [];
-                }
-            };
-            /**
-             * Finds the closest point to a set of coordinates, using the k-d-tree
-             * algorithm.
-             *
-             * @function Highcharts.Pointer#findNearestKDPoint
-             *
-             * @param {Array<Highcharts.Series>} series
-             *        All the series to search in.
-             *
-             * @param {boolean|undefined} shared
-             *        Whether it is a shared tooltip or not.
-             *
-             * @param {Highcharts.PointerEventObject} e
-             *        The pointer event object, containing chart coordinates of the
-             *        pointer.
-             *
-             * @return {Highcharts.Point|undefined}
-             *         The point closest to given coordinates.
-             */
-            Pointer.prototype.findNearestKDPoint = function (series, shared, e) {
-                var chart = this.chart;
-                var hoverPoint = chart.hoverPoint;
-                var tooltip = chart.tooltip;
-                if (hoverPoint &&
-                    tooltip &&
-                    tooltip.isStickyOnContact()) {
-                    return hoverPoint;
-                }
-                var closest;
-                /** @private */
-                function sort(p1, p2) {
-                    var isCloserX = p1.distX - p2.distX,
-                        isCloser = p1.dist - p2.dist,
-                        isAbove = (p2.series.group && p2.series.group.zIndex) -
-                            (p1.series.group && p1.series.group.zIndex),
-                        result;
-                    // We have two points which are not in the same place on xAxis
-                    // and shared tooltip:
-                    if (isCloserX !== 0 && shared) { // #5721
-                        result = isCloserX;
-                        // Points are not exactly in the same place on x/yAxis:
-                    }
-                    else if (isCloser !== 0) {
-                        result = isCloser;
-                        // The same xAxis and yAxis position, sort by z-index:
-                    }
-                    else if (isAbove !== 0) {
-                        result = isAbove;
-                        // The same zIndex, sort by array index:
-                    }
-                    else {
-                        result =
-                            p1.series.index > p2.series.index ?
-                                -1 :
-                                1;
-                    }
-                    return result;
-                }
-                series.forEach(function (s) {
-                    var noSharedTooltip = s.noSharedTooltip && shared,
-                        compareX = (!noSharedTooltip &&
-                            s.options.findNearestPointBy.indexOf('y') < 0),
-                        point = s.searchPoint(e,
-                        compareX);
-                    if ( // Check that we actually found a point on the series.
-                    isObject(point, true) &&
-                        // Use the new point if it is closer.
-                        (!isObject(closest, true) ||
-                            (sort(closest, point) > 0))) {
-                        closest = point;
-                    }
-                });
-                return closest;
-            };
-            /**
-             * @private
-             * @function Highcharts.Pointer#getChartCoordinatesFromPoint
-             * @param {Highcharts.Point} point
-             * @param {boolean} [inverted]
-             * @return {Highcharts.PointerCoordinatesObject|undefined}
-             */
-            Pointer.prototype.getChartCoordinatesFromPoint = function (point, inverted) {
-                var series = point.series,
-                    xAxis = series.xAxis,
-                    yAxis = series.yAxis,
-                    plotX = pick(point.clientX,
-                    point.plotX),
-                    shapeArgs = point.shapeArgs;
-                if (xAxis && yAxis) {
-                    return inverted ? {
-                        chartX: xAxis.len + xAxis.pos - plotX,
-                        chartY: yAxis.len + yAxis.pos - point.plotY
-                    } : {
-                        chartX: plotX + xAxis.pos,
-                        chartY: point.plotY + yAxis.pos
-                    };
-                }
-                if (shapeArgs && shapeArgs.x && shapeArgs.y) {
-                    // E.g. pies do not have axes
-                    return {
-                        chartX: shapeArgs.x,
-                        chartY: shapeArgs.y
-                    };
-                }
-            };
-            /**
-             * Return the cached chartPosition if it is available on the Pointer,
-             * otherwise find it. Running offset is quite expensive, so it should be
-             * avoided when we know the chart hasn't moved.
-             *
-             * @function Highcharts.Pointer#getChartPosition
-             *
-             * @return {Highcharts.OffsetObject}
-             *         The offset of the chart container within the page
-             */
-            Pointer.prototype.getChartPosition = function () {
-                return (this.chartPosition ||
-                    (this.chartPosition = offset(this.chart.container)));
-            };
-            /**
-             * Get the click position in terms of axis values.
-             *
-             * @function Highcharts.Pointer#getCoordinates
-             *
-             * @param {Highcharts.PointerEventObject} e
-             *        Pointer event, extended with `chartX` and `chartY` properties.
-             *
-             * @return {Highcharts.PointerAxisCoordinatesObject}
-             */
-            Pointer.prototype.getCoordinates = function (e) {
-                var coordinates = {
-                        xAxis: [],
-                        yAxis: []
-                    };
-                this.chart.axes.forEach(function (axis) {
-                    coordinates[axis.isXAxis ? 'xAxis' : 'yAxis'].push({
-                        axis: axis,
-                        value: axis.toValue(e[axis.horiz ? 'chartX' : 'chartY'])
-                    });
-                });
-                return coordinates;
-            };
-            /**
-             * Calculates what is the current hovered point/points and series.
-             *
-             * @private
-             * @function Highcharts.Pointer#getHoverData
-             *
-             * @param {Highcharts.Point|undefined} existingHoverPoint
-             *        The point currrently beeing hovered.
-             *
-             * @param {Highcharts.Series|undefined} existingHoverSeries
-             *        The series currently beeing hovered.
-             *
-             * @param {Array<Highcharts.Series>} series
-             *        All the series in the chart.
-             *
-             * @param {boolean} isDirectTouch
-             *        Is the pointer directly hovering the point.
-             *
-             * @param {boolean|undefined} shared
-             *        Whether it is a shared tooltip or not.
-             *
-             * @param {Highcharts.PointerEventObject} [e]
-             *        The triggering event, containing chart coordinates of the pointer.
-             *
-             * @return {object}
-             *         Object containing resulting hover data: hoverPoint, hoverSeries,
-             *         and hoverPoints.
-             */
-            Pointer.prototype.getHoverData = function (existingHoverPoint, existingHoverSeries, series, isDirectTouch, shared, e) {
-                var hoverPoint,
-                    hoverPoints = [],
-                    hoverSeries = existingHoverSeries,
-                    useExisting = !!(isDirectTouch && existingHoverPoint),
-                    notSticky = hoverSeries && !hoverSeries.stickyTracking, 
-                    // Which series to look in for the hover point
-                    searchSeries, 
-                    // Parameters needed for beforeGetHoverData event.
-                    eventArgs = {
-                        chartX: e ? e.chartX : void 0,
-                        chartY: e ? e.chartY : void 0,
-                        shared: shared
-                    },
-                    filter = function (s) {
-                        return (s.visible &&
-                            !(!shared && s.directTouch) && // #3821
-                            pick(s.options.enableMouseTracking,
-                    true));
-                };
-                // Find chart.hoverPane and update filter method in polar.
-                fireEvent(this, 'beforeGetHoverData', eventArgs);
-                searchSeries = notSticky ?
-                    // Only search on hovered series if it has stickyTracking false
-                    [hoverSeries] :
-                    // Filter what series to look in.
-                    series.filter(function (s) {
-                        return eventArgs.filter ? eventArgs.filter(s) : filter(s) &&
-                            s.stickyTracking;
-                    });
-                // Use existing hovered point or find the one closest to coordinates.
-                hoverPoint = useExisting || !e ?
-                    existingHoverPoint :
-                    this.findNearestKDPoint(searchSeries, shared, e);
-                // Assign hover series
-                hoverSeries = hoverPoint && hoverPoint.series;
-                // If we have a hoverPoint, assign hoverPoints.
-                if (hoverPoint) {
-                    // When tooltip is shared, it displays more than one point
-                    if (shared && !hoverSeries.noSharedTooltip) {
-                        searchSeries = series.filter(function (s) {
-                            return eventArgs.filter ?
-                                eventArgs.filter(s) : filter(s) && !s.noSharedTooltip;
-                        });
-                        // Get all points with the same x value as the hoverPoint
-                        searchSeries.forEach(function (s) {
-                            var point = find(s.points,
-                                function (p) {
-                                    return p.x === hoverPoint.x && !p.isNull;
-                            });
-                            if (isObject(point)) {
-                                /*
-                                * Boost returns a minimal point. Convert it to a usable
-                                * point for tooltip and states.
-                                */
-                                if (s.chart.isBoosting) {
-                                    point = s.getPoint(point);
-                                }
-                                hoverPoints.push(point);
-                            }
-                        });
-                    }
-                    else {
-                        hoverPoints.push(hoverPoint);
-                    }
-                }
-                // Check whether the hoverPoint is inside pane we are hovering over.
-                eventArgs = { hoverPoint: hoverPoint };
-                fireEvent(this, 'afterGetHoverData', eventArgs);
-                return {
-                    hoverPoint: eventArgs.hoverPoint,
-                    hoverSeries: hoverSeries,
-                    hoverPoints: hoverPoints
-                };
-            };
-            /**
-             * @private
-             * @function Highcharts.Pointer#getPointFromEvent
-             *
-             * @param {global.Event} e
-             *
-             * @return {Highcharts.Point|undefined}
-             */
-            Pointer.prototype.getPointFromEvent = function (e) {
-                var target = e.target,
-                    point;
-                while (target && !point) {
-                    point = target.point;
-                    target = target.parentNode;
-                }
-                return point;
-            };
-            /**
-             * @private
-             * @function Highcharts.Pointer#onTrackerMouseOut
-             *
-             * @param {Highcharts.PointerEventObject} e
-             *
-             * @return {void}
-             */
-            Pointer.prototype.onTrackerMouseOut = function (e) {
-                var chart = this.chart;
-                var relatedTarget = e.relatedTarget || e.toElement;
-                var series = chart.hoverSeries;
-                this.isDirectTouch = false;
-                if (series &&
-                    relatedTarget &&
-                    !series.stickyTracking &&
-                    !this.inClass(relatedTarget, 'highcharts-tooltip') &&
-                    (!this.inClass(relatedTarget, 'highcharts-series-' + series.index) || // #2499, #4465, #5553
-                        !this.inClass(relatedTarget, 'highcharts-tracker'))) {
-                    series.onMouseOut();
-                }
-            };
-            /**
-             * Utility to detect whether an element has, or has a parent with, a
-             * specificclass name. Used on detection of tracker objects and on deciding
-             * whether hovering the tooltip should cause the active series to mouse out.
-             *
-             * @function Highcharts.Pointer#inClass
-             *
-             * @param {Highcharts.SVGDOMElement|Highcharts.HTMLDOMElement} element
-             *        The element to investigate.
-             *
-             * @param {string} className
-             *        The class name to look for.
-             *
-             * @return {boolean|undefined}
-             *         True if either the element or one of its parents has the given
-             *         class name.
-             */
-            Pointer.prototype.inClass = function (element, className) {
-                var elemClassName;
-                while (element) {
-                    elemClassName = attr(element, 'class');
-                    if (elemClassName) {
-                        if (elemClassName.indexOf(className) !== -1) {
-                            return true;
-                        }
-                        if (elemClassName.indexOf('highcharts-container') !== -1) {
-                            return false;
-                        }
-                    }
-                    element = element.parentNode;
-                }
-            };
-            /**
-             * Initialize the Pointer.
-             *
-             * @private
-             * @function Highcharts.Pointer#init
-             *
-             * @param {Highcharts.Chart} chart
-             *        The Chart instance.
-             *
-             * @param {Highcharts.Options} options
-             *        The root options object. The pointer uses options from the chart
-             *        and tooltip structures.
-             *
-             * @return {void}
-             */
-            Pointer.prototype.init = function (chart, options) {
-                // Store references
-                this.options = options;
-                this.chart = chart;
-                // Do we need to handle click on a touch device?
-                this.runChartClick =
-                    options.chart.events &&
-                        !!options.chart.events.click;
-                this.pinchDown = [];
-                this.lastValidTouch = {};
-                if (Tooltip) {
-                    /**
-                     * Tooltip object for points of series.
-                     *
-                     * @name Highcharts.Chart#tooltip
-                     * @type {Highcharts.Tooltip}
-                     */
-                    chart.tooltip = new Tooltip(chart, options.tooltip);
-                    this.followTouchMove = pick(options.tooltip.followTouchMove, true);
-                }
-                this.setDOMEvents();
-            };
-            /**
-             * Takes a browser event object and extends it with custom Highcharts
-             * properties `chartX` and `chartY` in order to work on the internal
-             * coordinate system.
-             *
-             * @function Highcharts.Pointer#normalize
-             *
-             * @param {global.MouseEvent|global.PointerEvent|global.TouchEvent} e
-             *        Event object in standard browsers.
-             *
-             * @param {Highcharts.OffsetObject} [chartPosition]
-             *        Additional chart offset.
-             *
-             * @return {Highcharts.PointerEventObject}
-             *         A browser event with extended properties `chartX` and `chartY`.
-             */
-            Pointer.prototype.normalize = function (e, chartPosition) {
-                var touches = e.touches;
-                // iOS (#2757)
-                var ePos = (touches ?
-                        touches.length ?
-                            touches.item(0) :
-                            (pick(// #13534
-                            touches.changedTouches,
-                    e.changedTouches))[0] :
-                        e);
-                // Get mouse position
-                if (!chartPosition) {
-                    chartPosition = this.getChartPosition();
-                }
-                var chartX = ePos.pageX - chartPosition.left,
-                    chartY = ePos.pageY - chartPosition.top;
-                // #11329 - when there is scaling on a parent element, we need to take
-                // this into account
-                var containerScaling = this.chart.containerScaling;
-                if (containerScaling) {
-                    chartX /= containerScaling.scaleX;
-                    chartY /= containerScaling.scaleY;
-                }
-                return extend(e, {
-                    chartX: Math.round(chartX),
-                    chartY: Math.round(chartY)
-                });
-            };
-            /**
-             * @private
-             * @function Highcharts.Pointer#onContainerClick
-             */
-            Pointer.prototype.onContainerClick = function (e) {
-                var chart = this.chart;
-                var hoverPoint = chart.hoverPoint;
-                var pEvt = this.normalize(e);
-                var plotLeft = chart.plotLeft;
-                var plotTop = chart.plotTop;
-                if (!chart.cancelClick) {
-                    // On tracker click, fire the series and point events. #783, #1583
-                    if (hoverPoint &&
-                        this.inClass(pEvt.target, 'highcharts-tracker')) {
-                        // the series click event
-                        fireEvent(hoverPoint.series, 'click', extend(pEvt, {
-                            point: hoverPoint
-                        }));
-                        // the point click event
-                        if (chart.hoverPoint) { // it may be destroyed (#1844)
-                            hoverPoint.firePointEvent('click', pEvt);
-                        }
-                        // When clicking outside a tracker, fire a chart event
-                    }
-                    else {
-                        extend(pEvt, this.getCoordinates(pEvt));
-                        // fire a click event in the chart
-                        if (chart.isInsidePlot((pEvt.chartX - plotLeft), (pEvt.chartY - plotTop))) {
-                            fireEvent(chart, 'click', pEvt);
-                        }
-                    }
-                }
-            };
-            /**
-             * @private
-             * @function Highcharts.Pointer#onContainerMouseDown
-             *
-             * @param {global.MouseEvent} e
-             */
-            Pointer.prototype.onContainerMouseDown = function (e) {
-                var isPrimaryButton = ((e.buttons || e.button) & 1) === 1;
-                // Normalize before the 'if' for the legacy IE (#7850)
-                e = this.normalize(e);
-                // #11635, Firefox does not reliable fire move event after click scroll
-                if (H.isFirefox &&
-                    e.button !== 0) {
-                    this.onContainerMouseMove(e);
-                }
-                // #11635, limiting to primary button (incl. IE 8 support)
-                if (typeof e.button === 'undefined' ||
-                    isPrimaryButton) {
-                    this.zoomOption(e);
-                    // #295, #13737 solve conflict between container drag and chart zoom
-                    if (isPrimaryButton &&
-                        e.preventDefault) {
-                        e.preventDefault();
-                    }
-                    this.dragStart(e);
-                }
-            };
-            /**
-             * When mouse leaves the container, hide the tooltip.
-             *
-             * @private
-             * @function Highcharts.Pointer#onContainerMouseLeave
-             *
-             * @param {global.MouseEvent} e
-             *
-             * @return {void}
-             */
-            Pointer.prototype.onContainerMouseLeave = function (e) {
-                var chart = charts[pick(H.hoverChartIndex, -1)];
-                var tooltip = this.chart.tooltip;
-                e = this.normalize(e);
-                // #4886, MS Touch end fires mouseleave but with no related target
-                if (chart &&
-                    (e.relatedTarget || e.toElement)) {
-                    chart.pointer.reset();
-                    // Also reset the chart position, used in #149 fix
-                    chart.pointer.chartPosition = void 0;
-                }
-                if ( // #11635, Firefox wheel scroll does not fire out events consistently
-                tooltip &&
-                    !tooltip.isHidden) {
-                    this.reset();
-                }
-            };
-            /**
-             * When mouse enters the container, delete pointer's chartPosition.
-             *
-             * @private
-             * @function Highcharts.Pointer#onContainerMouseEnter
-             *
-             * @param {global.MouseEvent} e
-             *
-             * @return {void}
-             */
-            Pointer.prototype.onContainerMouseEnter = function (e) {
-                delete this.chartPosition;
-            };
-            /**
-             * The mousemove, touchmove and touchstart event handler
-             *
-             * @private
-             * @function Highcharts.Pointer#onContainerMouseMove
-             *
-             * @param {global.MouseEvent} e
-             *
-             * @return {void}
-             */
-            Pointer.prototype.onContainerMouseMove = function (e) {
-                var chart = this.chart;
-                var pEvt = this.normalize(e);
-                this.setHoverChartIndex();
-                // In IE8 we apparently need this returnValue set to false in order to
-                // avoid text being selected. But in Chrome, e.returnValue is prevented,
-                // plus we don't need to run e.preventDefault to prevent selected text
-                // in modern browsers. So we set it conditionally. Remove it when IE8 is
-                // no longer needed. #2251, #3224.
-                if (!pEvt.preventDefault) {
-                    pEvt.returnValue = false;
-                }
-                if (chart.mouseIsDown === 'mousedown') {
-                    this.drag(pEvt);
-                }
-                // Show the tooltip and run mouse over events (#977)
-                if (!chart.openMenu &&
-                    (this.inClass(pEvt.target, 'highcharts-tracker') ||
-                        chart.isInsidePlot((pEvt.chartX - chart.plotLeft), (pEvt.chartY - chart.plotTop)))) {
-                    this.runPointActions(pEvt);
-                }
-            };
-            /**
-             * @private
-             * @function Highcharts.Pointer#onDocumentTouchEnd
-             *
-             * @param {Highcharts.PointerEventObject} e
-             *
-             * @return {void}
-             */
-            Pointer.prototype.onDocumentTouchEnd = function (e) {
-                if (charts[H.hoverChartIndex]) {
-                    charts[H.hoverChartIndex].pointer.drop(e);
-                }
-            };
-            /**
-             * @private
-             * @function Highcharts.Pointer#onContainerTouchMove
-             *
-             * @param {Highcharts.PointerEventObject} e
-             *
-             * @return {void}
-             */
-            Pointer.prototype.onContainerTouchMove = function (e) {
-                this.touch(e);
-            };
-            /**
-             * @private
-             * @function Highcharts.Pointer#onContainerTouchStart
-             *
-             * @param {Highcharts.PointerEventObject} e
-             *
-             * @return {void}
-             */
-            Pointer.prototype.onContainerTouchStart = function (e) {
-                this.zoomOption(e);
-                this.touch(e, true);
-            };
-            /**
-             * Special handler for mouse move that will hide the tooltip when the mouse
-             * leaves the plotarea. Issue #149 workaround. The mouseleave event does not
-             * always fire.
-             *
-             * @private
-             * @function Highcharts.Pointer#onDocumentMouseMove
-             *
-             * @param {global.MouseEvent} e
-             *
-             * @return {void}
-             */
-            Pointer.prototype.onDocumentMouseMove = function (e) {
-                var chart = this.chart;
-                var chartPosition = this.chartPosition;
-                var pEvt = this.normalize(e,
-                    chartPosition);
-                var tooltip = chart.tooltip;
-                // If we're outside, hide the tooltip
-                if (chartPosition &&
-                    (!tooltip ||
-                        !tooltip.isStickyOnContact()) &&
-                    !chart.isInsidePlot(pEvt.chartX - chart.plotLeft, pEvt.chartY - chart.plotTop) &&
-                    !this.inClass(pEvt.target, 'highcharts-tracker')) {
-                    this.reset();
-                }
-            };
-            /**
-             * @private
-             * @function Highcharts.Pointer#onDocumentMouseUp
-             *
-             * @param {global.MouseEvent} e
-             *
-             * @return {void}
-             */
-            Pointer.prototype.onDocumentMouseUp = function (e) {
-                var chart = charts[pick(H.hoverChartIndex, -1)];
-                if (chart) {
-                    chart.pointer.drop(e);
-                }
-            };
-            /**
-             * Handle touch events with two touches
-             *
-             * @private
-             * @function Highcharts.Pointer#pinch
-             *
-             * @param {Highcharts.PointerEventObject} e
-             *
-             * @return {void}
-             */
-            Pointer.prototype.pinch = function (e) {
-                var self = this,
-                    chart = self.chart,
-                    pinchDown = self.pinchDown,
-                    touches = (e.touches || []),
-                    touchesLength = touches.length,
-                    lastValidTouch = self.lastValidTouch,
-                    hasZoom = self.hasZoom,
-                    selectionMarker = self.selectionMarker,
-                    transform = {},
-                    fireClickEvent = touchesLength === 1 && ((self.inClass(e.target, 'highcharts-tracker') &&
-                        chart.runTrackerClick) ||
-                        self.runChartClick),
-                    clip = {};
-                // Don't initiate panning until the user has pinched. This prevents us
-                // from blocking page scrolling as users scroll down a long page
-                // (#4210).
-                if (touchesLength > 1) {
-                    self.initiated = true;
-                }
-                // On touch devices, only proceed to trigger click if a handler is
-                // defined
-                if (hasZoom && self.initiated && !fireClickEvent && e.cancelable !== false) {
-                    e.preventDefault();
-                }
-                // Normalize each touch
-                [].map.call(touches, function (e) {
-                    return self.normalize(e);
-                });
-                // Register the touch start position
-                if (e.type === 'touchstart') {
-                    [].forEach.call(touches, function (e, i) {
-                        pinchDown[i] = { chartX: e.chartX, chartY: e.chartY };
-                    });
-                    lastValidTouch.x = [pinchDown[0].chartX, pinchDown[1] &&
-                            pinchDown[1].chartX];
-                    lastValidTouch.y = [pinchDown[0].chartY, pinchDown[1] &&
-                            pinchDown[1].chartY];
-                    // Identify the data bounds in pixels
-                    chart.axes.forEach(function (axis) {
-                        if (axis.zoomEnabled) {
-                            var bounds = chart.bounds[axis.horiz ? 'h' : 'v'],
-                                minPixelPadding = axis.minPixelPadding,
-                                min = axis.toPixels(Math.min(pick(axis.options.min,
-                                axis.dataMin),
-                                axis.dataMin)),
-                                max = axis.toPixels(Math.max(pick(axis.options.max,
-                                axis.dataMax),
-                                axis.dataMax)),
-                                absMin = Math.min(min,
-                                max),
-                                absMax = Math.max(min,
-                                max);
-                            // Store the bounds for use in the touchmove handler
-                            bounds.min = Math.min(axis.pos, absMin - minPixelPadding);
-                            bounds.max = Math.max(axis.pos + axis.len, absMax + minPixelPadding);
-                        }
-                    });
-                    self.res = true; // reset on next move
-                    // Optionally move the tooltip on touchmove
-                }
-                else if (self.followTouchMove && touchesLength === 1) {
-                    this.runPointActions(self.normalize(e));
-                    // Event type is touchmove, handle panning and pinching
-                }
-                else if (pinchDown.length) { // can be 0 when releasing, if touchend
-                    // fires first
-                    // Set the marker
-                    if (!selectionMarker) {
-                        self.selectionMarker = selectionMarker = extend({
-                            destroy: noop,
-                            touch: true
-                        }, chart.plotBox);
-                    }
-                    self.pinchTranslate(pinchDown, touches, transform, selectionMarker, clip, lastValidTouch);
-                    self.hasPinched = hasZoom;
-                    // Scale and translate the groups to provide visual feedback during
-                    // pinching
-                    self.scaleGroups(transform, clip);
-                    if (self.res) {
-                        self.res = false;
-                        this.reset(false, 0);
-                    }
-                }
-            };
-            /**
-             * Run translation operations
-             *
-             * @private
-             * @function Highcharts.Pointer#pinchTranslate
-             *
-             * @param {Array<*>} pinchDown
-             *
-             * @param {Array<Highcharts.PointerEventObject>} touches
-             *
-             * @param {*} transform
-             *
-             * @param {*} selectionMarker
-             *
-             * @param {*} clip
-             *
-             * @param {*} lastValidTouch
-             *
-             * @return {void}
-             */
-            Pointer.prototype.pinchTranslate = function (pinchDown, touches, transform, selectionMarker, clip, lastValidTouch) {
-                if (this.zoomHor) {
-                    this.pinchTranslateDirection(true, pinchDown, touches, transform, selectionMarker, clip, lastValidTouch);
-                }
-                if (this.zoomVert) {
-                    this.pinchTranslateDirection(false, pinchDown, touches, transform, selectionMarker, clip, lastValidTouch);
-                }
-            };
-            /**
-             * Run translation operations for each direction (horizontal and vertical)
-             * independently.
-             *
-             * @private
-             * @function Highcharts.Pointer#pinchTranslateDirection
-             *
-             * @param {boolean} horiz
-             *
-             * @param {Array<*>} pinchDown
-             *
-             * @param {Array<Highcharts.PointerEventObject>} touches
-             *
-             * @param {*} transform
-             *
-             * @param {*} selectionMarker
-             *
-             * @param {*} clip
-             *
-             * @param {*} lastValidTouch
-             *
-             * @param {number|undefined} [forcedScale=1]
-             *
-             * @return {void}
-             */
-            Pointer.prototype.pinchTranslateDirection = function (horiz, pinchDown, touches, transform, selectionMarker, clip, lastValidTouch, forcedScale) {
-                var chart = this.chart, xy = horiz ? 'x' : 'y', XY = horiz ? 'X' : 'Y', sChartXY = ('chart' + XY), wh = horiz ? 'width' : 'height', plotLeftTop = chart['plot' + (horiz ? 'Left' : 'Top')], selectionWH, selectionXY, clipXY, scale = forcedScale || 1, inverted = chart.inverted, bounds = chart.bounds[horiz ? 'h' : 'v'], singleTouch = pinchDown.length === 1, touch0Start = pinchDown[0][sChartXY], touch0Now = touches[0][sChartXY], touch1Start = !singleTouch && pinchDown[1][sChartXY], touch1Now = !singleTouch && touches[1][sChartXY], outOfBounds, transformScale, scaleKey, setScale = function () {
-                        // Don't zoom if fingers are too close on this axis
-                        if (typeof touch1Now === 'number' &&
-                            Math.abs(touch0Start - touch1Start) > 20) {
-                            scale = forcedScale ||
-                                Math.abs(touch0Now - touch1Now) /
-                                    Math.abs(touch0Start - touch1Start);
-                    }
-                    clipXY = ((plotLeftTop - touch0Now) / scale) + touch0Start;
-                    selectionWH = chart['plot' + (horiz ? 'Width' : 'Height')] / scale;
-                };
-                // Set the scale, first pass
-                setScale();
-                // The clip position (x or y) is altered if out of bounds, the selection
-                // position is not
-                selectionXY = clipXY;
-                // Out of bounds
-                if (selectionXY < bounds.min) {
-                    selectionXY = bounds.min;
-                    outOfBounds = true;
-                }
-                else if (selectionXY + selectionWH > bounds.max) {
-                    selectionXY = bounds.max - selectionWH;
-                    outOfBounds = true;
-                }
-                // Is the chart dragged off its bounds, determined by dataMin and
-                // dataMax?
-                if (outOfBounds) {
-                    // Modify the touchNow position in order to create an elastic drag
-                    // movement. This indicates to the user that the chart is responsive
-                    // but can't be dragged further.
-                    touch0Now -= 0.8 * (touch0Now - lastValidTouch[xy][0]);
-                    if (typeof touch1Now === 'number') {
-                        touch1Now -= 0.8 * (touch1Now - lastValidTouch[xy][1]);
-                    }
-                    // Set the scale, second pass to adapt to the modified touchNow
-                    // positions
-                    setScale();
-                }
-                else {
-                    lastValidTouch[xy] = [touch0Now, touch1Now];
-                }
-                // Set geometry for clipping, selection and transformation
-                if (!inverted) {
-                    clip[xy] = clipXY - plotLeftTop;
-                    clip[wh] = selectionWH;
-                }
-                scaleKey = inverted ? (horiz ? 'scaleY' : 'scaleX') : 'scale' + XY;
-                transformScale = inverted ? 1 / scale : scale;
-                selectionMarker[wh] = selectionWH;
-                selectionMarker[xy] = selectionXY;
-                transform[scaleKey] = scale;
-                transform['translate' + XY] = (transformScale * plotLeftTop) +
-                    (touch0Now - (transformScale * touch0Start));
-            };
-            /**
-             * Reset the tracking by hiding the tooltip, the hover series state and the
-             * hover point
-             *
-             * @function Highcharts.Pointer#reset
-             *
-             * @param {boolean} [allowMove]
-             *        Instead of destroying the tooltip altogether, allow moving it if
-             *        possible.
-             *
-             * @param {number} [delay]
-             *
-             * @return {void}
-             */
-            Pointer.prototype.reset = function (allowMove, delay) {
-                var pointer = this,
-                    chart = pointer.chart,
-                    hoverSeries = chart.hoverSeries,
-                    hoverPoint = chart.hoverPoint,
-                    hoverPoints = chart.hoverPoints,
-                    tooltip = chart.tooltip,
-                    tooltipPoints = tooltip && tooltip.shared ?
-                        hoverPoints :
-                        hoverPoint;
-                // Check if the points have moved outside the plot area (#1003, #4736,
-                // #5101)
-                if (allowMove && tooltipPoints) {
-                    splat(tooltipPoints).forEach(function (point) {
-                        if (point.series.isCartesian &&
-                            typeof point.plotX === 'undefined') {
-                            allowMove = false;
-                        }
-                    });
-                }
-                // Just move the tooltip, #349
-                if (allowMove) {
-                    if (tooltip && tooltipPoints && splat(tooltipPoints).length) {
-                        tooltip.refresh(tooltipPoints);
-                        if (tooltip.shared && hoverPoints) { // #8284
-                            hoverPoints.forEach(function (point) {
-                                point.setState(point.state, true);
-                                if (point.series.isCartesian) {
-                                    if (point.series.xAxis.crosshair) {
-                                        point.series.xAxis
-                                            .drawCrosshair(null, point);
-                                    }
-                                    if (point.series.yAxis.crosshair) {
-                                        point.series.yAxis
-                                            .drawCrosshair(null, point);
-                                    }
-                                }
-                            });
-                        }
-                        else if (hoverPoint) { // #2500
-                            hoverPoint.setState(hoverPoint.state, true);
-                            chart.axes.forEach(function (axis) {
-                                if (axis.crosshair &&
-                                    hoverPoint.series[axis.coll] === axis) {
-                                    axis.drawCrosshair(null, hoverPoint);
-                                }
-                            });
-                        }
-                    }
-                    // Full reset
-                }
-                else {
-                    if (hoverPoint) {
-                        hoverPoint.onMouseOut();
-                    }
-                    if (hoverPoints) {
-                        hoverPoints.forEach(function (point) {
-                            point.setState();
-                        });
-                    }
-                    if (hoverSeries) {
-                        hoverSeries.onMouseOut();
-                    }
-                    if (tooltip) {
-                        tooltip.hide(delay);
-                    }
-                    if (pointer.unDocMouseMove) {
-                        pointer.unDocMouseMove = pointer.unDocMouseMove();
-                    }
-                    // Remove crosshairs
-                    chart.axes.forEach(function (axis) {
-                        axis.hideCrosshair();
-                    });
-                    pointer.hoverX = chart.hoverPoints = chart.hoverPoint = null;
-                }
-            };
-            /**
-             * With line type charts with a single tracker, get the point closest to the
-             * mouse. Run Point.onMouseOver and display tooltip for the point or points.
-             *
-             * @private
-             * @function Highcharts.Pointer#runPointActions
-             *
-             * @param {global.Event} e
-             *
-             * @param {Highcharts.PointerEventObject} [p]
-             *
-             * @return {void}
-             *
-             * @fires Highcharts.Point#event:mouseOut
-             * @fires Highcharts.Point#event:mouseOver
-             */
-            Pointer.prototype.runPointActions = function (e, p) {
-                var pointer = this,
-                    chart = pointer.chart,
-                    series = chart.series,
-                    tooltip = (chart.tooltip && chart.tooltip.options.enabled ?
-                        chart.tooltip :
-                        void 0),
-                    shared = (tooltip ?
-                        tooltip.shared :
-                        false),
-                    hoverPoint = p || chart.hoverPoint,
-                    hoverSeries = hoverPoint && hoverPoint.series || chart.hoverSeries, 
-                    // onMouseOver or already hovering a series with directTouch
-                    isDirectTouch = (!e || e.type !== 'touchmove') && (!!p || ((hoverSeries && hoverSeries.directTouch) &&
-                        pointer.isDirectTouch)),
-                    hoverData = this.getHoverData(hoverPoint,
-                    hoverSeries,
-                    series,
-                    isDirectTouch,
-                    shared,
-                    e),
-                    useSharedTooltip,
-                    followPointer,
-                    anchor,
-                    points;
-                // Update variables from hoverData.
-                hoverPoint = hoverData.hoverPoint;
-                points = hoverData.hoverPoints;
-                hoverSeries = hoverData.hoverSeries;
-                followPointer = hoverSeries && hoverSeries.tooltipOptions.followPointer;
-                useSharedTooltip = (shared &&
-                    hoverSeries &&
-                    !hoverSeries.noSharedTooltip);
-                // Refresh tooltip for kdpoint if new hover point or tooltip was hidden
-                // #3926, #4200
-                if (hoverPoint &&
-                    // !(hoverSeries && hoverSeries.directTouch) &&
-                    (hoverPoint !== chart.hoverPoint || (tooltip && tooltip.isHidden))) {
-                    (chart.hoverPoints || []).forEach(function (p) {
-                        if (points.indexOf(p) === -1) {
-                            p.setState();
-                        }
-                    });
-                    // Set normal state to previous series
-                    if (chart.hoverSeries !== hoverSeries) {
-                        hoverSeries.onMouseOver();
-                    }
-                    pointer.applyInactiveState(points);
-                    // Do mouseover on all points (#3919, #3985, #4410, #5622)
-                    (points || []).forEach(function (p) {
-                        p.setState('hover');
-                    });
-                    // If tracking is on series in stead of on each point,
-                    // fire mouseOver on hover point. // #4448
-                    if (chart.hoverPoint) {
-                        chart.hoverPoint.firePointEvent('mouseOut');
-                    }
-                    // Hover point may have been destroyed in the event handlers (#7127)
-                    if (!hoverPoint.series) {
-                        return;
-                    }
-                    /**
-                     * Contains all hovered points.
-                     *
-                     * @name Highcharts.Chart#hoverPoints
-                     * @type {Array<Highcharts.Point>|null}
-                     */
-                    chart.hoverPoints = points;
-                    /**
-                     * Contains the original hovered point.
-                     *
-                     * @name Highcharts.Chart#hoverPoint
-                     * @type {Highcharts.Point|null}
-                     */
-                    chart.hoverPoint = hoverPoint;
-                    /**
-                     * Hover state should not be lost when axis is updated (#12569)
-                     * Axis.update runs pointer.reset which uses chart.hoverPoint.state
-                     * to apply state which does not exist in hoverPoint yet.
-                     * The mouseOver event should be triggered when hoverPoint
-                     * is correct.
-                     */
-                    hoverPoint.firePointEvent('mouseOver');
-                    // Draw tooltip if necessary
-                    if (tooltip) {
-                        tooltip.refresh(useSharedTooltip ? points : hoverPoint, e);
-                    }
-                    // Update positions (regardless of kdpoint or hoverPoint)
-                }
-                else if (followPointer && tooltip && !tooltip.isHidden) {
-                    anchor = tooltip.getAnchor([{}], e);
-                    tooltip.updatePosition({ plotX: anchor[0], plotY: anchor[1] });
-                }
-                // Start the event listener to pick up the tooltip and crosshairs
-                if (!pointer.unDocMouseMove) {
-                    pointer.unDocMouseMove = addEvent(chart.container.ownerDocument, 'mousemove', function (e) {
-                        var chart = charts[H.hoverChartIndex];
-                        if (chart) {
-                            chart.pointer.onDocumentMouseMove(e);
-                        }
-                    });
-                }
-                // Issues related to crosshair #4927, #5269 #5066, #5658
-                chart.axes.forEach(function drawAxisCrosshair(axis) {
-                    var snap = pick((axis.crosshair || {}).snap,
-                        true);
-                    var point;
-                    if (snap) {
-                        point = chart.hoverPoint; // #13002
-                        if (!point || point.series[axis.coll] !== axis) {
-                            point = find(points, function (p) {
-                                return p.series[axis.coll] === axis;
-                            });
-                        }
-                    }
-                    // Axis has snapping crosshairs, and one of the hover points belongs
-                    // to axis. Always call drawCrosshair when it is not snap.
-                    if (point || !snap) {
-                        axis.drawCrosshair(e, point);
-                        // Axis has snapping crosshairs, but no hover point belongs to axis
-                    }
-                    else {
-                        axis.hideCrosshair();
-                    }
-                });
-            };
-            /**
-             * Scale series groups to a certain scale and translation.
-             *
-             * @private
-             * @function Highcharts.Pointer#scaleGroups
-             *
-             * @param {Highcharts.SeriesPlotBoxObject} [attribs]
-             *
-             * @param {boolean} [clip]
-             *
-             * @return {void}
-             */
-            Pointer.prototype.scaleGroups = function (attribs, clip) {
-                var chart = this.chart,
-                    seriesAttribs;
-                // Scale each series
-                chart.series.forEach(function (series) {
-                    seriesAttribs = attribs || series.getPlotBox(); // #1701
-                    if (series.xAxis && series.xAxis.zoomEnabled && series.group) {
-                        series.group.attr(seriesAttribs);
-                        if (series.markerGroup) {
-                            series.markerGroup.attr(seriesAttribs);
-                            series.markerGroup.clip(clip ? chart.clipRect : null);
-                        }
-                        if (series.dataLabelsGroup) {
-                            series.dataLabelsGroup.attr(seriesAttribs);
-                        }
-                    }
-                });
-                // Clip
-                chart.clipRect.attr(clip || chart.clipBox);
-            };
-            /**
-             * Set the JS DOM events on the container and document. This method should
-             * contain a one-to-one assignment between methods and their handlers. Any
-             * advanced logic should be moved to the handler reflecting the event's
-             * name.
-             *
-             * @private
-             * @function Highcharts.Pointer#setDOMEvents
-             *
-             * @return {void}
-             */
-            Pointer.prototype.setDOMEvents = function () {
-                var container = this.chart.container,
-                    ownerDoc = container.ownerDocument;
-                container.onmousedown = this.onContainerMouseDown.bind(this);
-                container.onmousemove = this.onContainerMouseMove.bind(this);
-                container.onclick = this.onContainerClick.bind(this);
-                this.unbindContainerMouseEnter = addEvent(container, 'mouseenter', this.onContainerMouseEnter.bind(this));
-                this.unbindContainerMouseLeave = addEvent(container, 'mouseleave', this.onContainerMouseLeave.bind(this));
-                if (!H.unbindDocumentMouseUp) {
-                    H.unbindDocumentMouseUp = addEvent(ownerDoc, 'mouseup', this.onDocumentMouseUp.bind(this));
-                }
-                if (H.hasTouch) {
-                    addEvent(container, 'touchstart', this.onContainerTouchStart.bind(this));
-                    addEvent(container, 'touchmove', this.onContainerTouchMove.bind(this));
-                    if (!H.unbindDocumentTouchEnd) {
-                        H.unbindDocumentTouchEnd = addEvent(ownerDoc, 'touchend', this.onDocumentTouchEnd.bind(this));
-                    }
-                }
-            };
-            /**
-             * Sets the index of the hovered chart and leaves the previous hovered
-             * chart, to reset states like tooltip.
-             *
-             * @private
-             * @function Highcharts.Pointer#setHoverChartIndex
-             */
-            Pointer.prototype.setHoverChartIndex = function () {
-                var chart = this.chart;
-                var hoverChart = H.charts[pick(H.hoverChartIndex, -1)];
-                if (hoverChart &&
-                    hoverChart !== chart) {
-                    hoverChart.pointer.onContainerMouseLeave({ relatedTarget: true });
-                }
-                if (!hoverChart ||
-                    !hoverChart.mouseIsDown) {
-                    H.hoverChartIndex = chart.index;
-                }
-            };
-            /**
-             * General touch handler shared by touchstart and touchmove.
-             *
-             * @private
-             * @function Highcharts.Pointer#touch
-             *
-             * @param {Highcharts.PointerEventObject} e
-             *
-             * @param {boolean} [start]
-             *
-             * @return {void}
-             */
-            Pointer.prototype.touch = function (e, start) {
-                var chart = this.chart,
-                    hasMoved,
-                    pinchDown,
-                    isInside;
-                this.setHoverChartIndex();
-                if (e.touches.length === 1) {
-                    e = this.normalize(e);
-                    isInside = chart.isInsidePlot(e.chartX - chart.plotLeft, e.chartY - chart.plotTop);
-                    if (isInside && !chart.openMenu) {
-                        // Run mouse events and display tooltip etc
-                        if (start) {
-                            this.runPointActions(e);
-                        }
-                        // Android fires touchmove events after the touchstart even if
-                        // the finger hasn't moved, or moved only a pixel or two. In iOS
-                        // however, the touchmove doesn't fire unless the finger moves
-                        // more than ~4px. So we emulate this behaviour in Android by
-                        // checking how much it moved, and cancelling on small
-                        // distances. #3450.
-                        if (e.type === 'touchmove') {
-                            pinchDown = this.pinchDown;
-                            hasMoved = pinchDown[0] ? Math.sqrt(// #5266
-                            Math.pow(pinchDown[0].chartX - e.chartX, 2) +
-                                Math.pow(pinchDown[0].chartY - e.chartY, 2)) >= 4 : false;
-                        }
-                        if (pick(hasMoved, true)) {
-                            this.pinch(e);
-                        }
-                    }
-                    else if (start) {
-                        // Hide the tooltip on touching outside the plot area (#1203)
-                        this.reset();
-                    }
-                }
-                else if (e.touches.length === 2) {
-                    this.pinch(e);
-                }
-            };
-            /**
-             * Resolve the zoomType option, this is reset on all touch start and mouse
-             * down events.
-             *
-             * @private
-             * @function Highcharts.Pointer#zoomOption
-             *
-             * @param {global.Event} e
-             *        Event object.
-             *
-             * @param {void}
-             */
-            Pointer.prototype.zoomOption = function (e) {
-                var chart = this.chart,
-                    options = chart.options.chart,
-                    zoomType = options.zoomType || '',
-                    inverted = chart.inverted,
-                    zoomX,
-                    zoomY;
-                // Look for the pinchType option
-                if (/touch/.test(e.type)) {
-                    zoomType = pick(options.pinchType, zoomType);
-                }
-                this.zoomX = zoomX = /x/.test(zoomType);
-                this.zoomY = zoomY = /y/.test(zoomType);
-                this.zoomHor = (zoomX && !inverted) || (zoomY && inverted);
-                this.zoomVert = (zoomY && !inverted) || (zoomX && inverted);
-                this.hasZoom = zoomX || zoomY;
-            };
-            return Pointer;
-        }());
-        H.Pointer = Pointer;
-
-        return Pointer;
-    });
-    _registerModule(_modules, 'Core/MSPointer.js', [_modules['Core/Globals.js'], _modules['Core/Pointer.js'], _modules['Core/Utilities.js']], function (H, Pointer, U) {
-        /* *
-         *
-         *  (c) 2010-2020 Torstein Honsi
-         *
-         *  License: www.highcharts.com/license
-         *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
-         *
-         * */
-        var __extends = (this && this.__extends) || (function () {
-                var extendStatics = function (d,
-            b) {
-                    extendStatics = Object.setPrototypeOf ||
-                        ({ __proto__: [] } instanceof Array && function (d,
-            b) { d.__proto__ = b; }) ||
-                        function (d,
-            b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
-                return extendStatics(d, b);
-            };
-            return function (d, b) {
-                extendStatics(d, b);
-                function __() { this.constructor = d; }
-                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
-            };
-        })();
-        var charts = H.charts,
-            doc = H.doc,
-            noop = H.noop,
-            win = H.win;
-        var addEvent = U.addEvent,
-            css = U.css,
-            objectEach = U.objectEach,
-            removeEvent = U.removeEvent;
-        /* globals MSPointerEvent, PointerEvent */
-        // The touches object keeps track of the points being touched at all times
-        var touches = {};
-        var hasPointerEvent = !!win.PointerEvent;
-        /* eslint-disable valid-jsdoc */
-        /** @private */
-        function getWebkitTouches() {
-            var fake = [];
-            fake.item = function (i) {
-                return this[i];
-            };
-            objectEach(touches, function (touch) {
-                fake.push({
-                    pageX: touch.pageX,
-                    pageY: touch.pageY,
-                    target: touch.target
-                });
-            });
-            return fake;
-        }
-        /** @private */
-        function translateMSPointer(e, method, wktype, func) {
-            var p;
-            if ((e.pointerType === 'touch' ||
-                e.pointerType === e.MSPOINTER_TYPE_TOUCH) && charts[H.hoverChartIndex]) {
-                func(e);
-                p = charts[H.hoverChartIndex].pointer;
-                p[method]({
-                    type: wktype,
-                    target: e.currentTarget,
-                    preventDefault: noop,
-                    touches: getWebkitTouches()
-                });
-            }
-        }
-        /** @private */
-        var MSPointer = /** @class */ (function (_super) {
-                __extends(MSPointer, _super);
-            function MSPointer() {
-                return _super !== null && _super.apply(this, arguments) || this;
-            }
-            /* *
-             *
-             *  Functions
-             *
-             * */
-            /**
-             * Add or remove the MS Pointer specific events
-             *
-             * @private
-             * @function Highcharts.Pointer#batchMSEvents
-             *
-             * @param {Function} fn
-             *
-             * @return {void}
-             */
-            MSPointer.prototype.batchMSEvents = function (fn) {
-                fn(this.chart.container, hasPointerEvent ? 'pointerdown' : 'MSPointerDown', this.onContainerPointerDown);
-                fn(this.chart.container, hasPointerEvent ? 'pointermove' : 'MSPointerMove', this.onContainerPointerMove);
-                fn(doc, hasPointerEvent ? 'pointerup' : 'MSPointerUp', this.onDocumentPointerUp);
-            };
-            // Destroy MS events also
-            MSPointer.prototype.destroy = function () {
-                this.batchMSEvents(removeEvent);
-                _super.prototype.destroy.call(this);
-            };
-            // Disable default IE actions for pinch and such on chart element
-            MSPointer.prototype.init = function (chart, options) {
-                _super.prototype.init.call(this, chart, options);
-                if (this.hasZoom) { // #4014
-                    css(chart.container, {
-                        '-ms-touch-action': 'none',
-                        'touch-action': 'none'
-                    });
-                }
-            };
-            /**
-             * @private
-             * @function Highcharts.Pointer#onContainerPointerDown
-             *
-             * @param {Highcharts.PointerEventObject} e
-             *
-             * @return {void}
-             */
-            MSPointer.prototype.onContainerPointerDown = function (e) {
-                translateMSPointer(e, 'onContainerTouchStart', 'touchstart', function (e) {
-                    touches[e.pointerId] = {
-                        pageX: e.pageX,
-                        pageY: e.pageY,
-                        target: e.currentTarget
-                    };
-                });
-            };
-            /**
-             * @private
-             * @function Highcharts.Pointer#onContainerPointerMove
-             *
-             * @param {Highcharts.PointerEventObject} e
-             *
-             * @return {void}
-             */
-            MSPointer.prototype.onContainerPointerMove = function (e) {
-                translateMSPointer(e, 'onContainerTouchMove', 'touchmove', function (e) {
-                    touches[e.pointerId] = ({ pageX: e.pageX, pageY: e.pageY });
-                    if (!touches[e.pointerId].target) {
-                        touches[e.pointerId].target = e.currentTarget;
-                    }
-                });
-            };
-            /**
-             * @private
-             * @function Highcharts.Pointer#onDocumentPointerUp
-             *
-             * @param {Highcharts.PointerEventObject} e
-             *
-             * @return {void}
-             */
-            MSPointer.prototype.onDocumentPointerUp = function (e) {
-                translateMSPointer(e, 'onDocumentTouchEnd', 'touchend', function (e) {
-                    delete touches[e.pointerId];
-                });
-            };
-            // Add IE specific touch events to chart
-            MSPointer.prototype.setDOMEvents = function () {
-                _super.prototype.setDOMEvents.call(this);
-                if (this.hasZoom || this.followTouchMove) {
-                    this.batchMSEvents(addEvent);
-                }
-            };
-            return MSPointer;
-        }(Pointer));
-
-        return MSPointer;
-    });
-    _registerModule(_modules, 'Core/Legend.js', [_modules['Core/Animation/AnimationUtilities.js'], _modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (A, H, U) {
-        /* *
-         *
-         *  (c) 2010-2020 Torstein Honsi
-         *
-         *  License: www.highcharts.com/license
-         *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
-         *
-         * */
-        var animObject = A.animObject,
-            setAnimation = A.setAnimation;
-        /**
-         * Gets fired when the legend item belonging to a point is clicked. The default
-         * action is to toggle the visibility of the point. This can be prevented by
-         * returning `false` or calling `event.preventDefault()`.
-         *
-         * @callback Highcharts.PointLegendItemClickCallbackFunction
-         *
-         * @param {Highcharts.Point} this
-         *        The point on which the event occured.
-         *
-         * @param {Highcharts.PointLegendItemClickEventObject} event
-         *        The event that occured.
-         */
-        /**
-         * Information about the legend click event.
-         *
-         * @interface Highcharts.PointLegendItemClickEventObject
-         */ /**
-        * Related browser event.
-        * @name Highcharts.PointLegendItemClickEventObject#browserEvent
-        * @type {Highcharts.PointerEvent}
-        */ /**
-        * Prevent the default action of toggle the visibility of the point.
-        * @name Highcharts.PointLegendItemClickEventObject#preventDefault
-        * @type {Function}
-        */ /**
-        * Related point.
-        * @name Highcharts.PointLegendItemClickEventObject#target
-        * @type {Highcharts.Point}
-        */ /**
-        * Event type.
-        * @name Highcharts.PointLegendItemClickEventObject#type
-        * @type {"legendItemClick"}
-        */
-        /**
-         * Gets fired when the legend item belonging to a series is clicked. The default
-         * action is to toggle the visibility of the series. This can be prevented by
-         * returning `false` or calling `event.preventDefault()`.
-         *
-         * @callback Highcharts.SeriesLegendItemClickCallbackFunction
-         *
-         * @param {Highcharts.Series} this
-         *        The series where the event occured.
-         *
-         * @param {Highcharts.SeriesLegendItemClickEventObject} event
-         *        The event that occured.
-         */
-        /**
-         * Information about the legend click event.
-         *
-         * @interface Highcharts.SeriesLegendItemClickEventObject
-         */ /**
-        * Related browser event.
-        * @name Highcharts.SeriesLegendItemClickEventObject#browserEvent
-        * @type {Highcharts.PointerEvent}
-        */ /**
-        * Prevent the default action of toggle the visibility of the series.
-        * @name Highcharts.SeriesLegendItemClickEventObject#preventDefault
-        * @type {Function}
-        */ /**
-        * Related series.
-        * @name Highcharts.SeriesLegendItemClickEventObject#target
-        * @type {Highcharts.Series}
-        */ /**
-        * Event type.
-        * @name Highcharts.SeriesLegendItemClickEventObject#type
-        * @type {"legendItemClick"}
-        */
-        var addEvent = U.addEvent,
-            css = U.css,
-            defined = U.defined,
-            discardElement = U.discardElement,
-            find = U.find,
-            fireEvent = U.fireEvent,
-            format = U.format,
-            isNumber = U.isNumber,
-            merge = U.merge,
-            pick = U.pick,
-            relativeLength = U.relativeLength,
-            stableSort = U.stableSort,
-            syncTimeout = U.syncTimeout,
-            wrap = U.wrap;
-        var isFirefox = H.isFirefox,
-            marginNames = H.marginNames,
-            win = H.win;
-        /* eslint-disable no-invalid-this, valid-jsdoc */
-        /**
-         * The overview of the chart's series. The legend object is instanciated
-         * internally in the chart constructor, and is available from the `chart.legend`
-         * property. Each chart has only one legend.
-         *
-         * @class
-         * @name Highcharts.Legend
-         *
-         * @param {Highcharts.Chart} chart
-         * The chart instance.
-         *
-         * @param {Highcharts.LegendOptions} options
-         * Legend options.
-         */
-        var Legend = /** @class */ (function () {
-                /* *
-                 *
-                 *  Constructors
-                 *
-                 * */
-                function Legend(chart, options) {
-                    /* *
-                     *
-                     *  Properties
-                     *
-                     * */
-                    this.allItems = [];
-                this.box = void 0;
-                this.contentGroup = void 0;
-                this.display = false;
-                this.group = void 0;
-                this.initialItemY = 0;
-                this.itemHeight = 0;
-                this.itemMarginBottom = 0;
-                this.itemMarginTop = 0;
-                this.itemX = 0;
-                this.itemY = 0;
-                this.lastItemY = 0;
-                this.lastLineHeight = 0;
-                this.legendHeight = 0;
-                this.legendWidth = 0;
-                this.maxItemWidth = 0;
-                this.maxLegendWidth = 0;
-                this.offsetWidth = 0;
-                this.options = {};
-                this.padding = 0;
-                this.pages = [];
-                this.proximate = false;
-                this.scrollGroup = void 0;
-                this.symbolHeight = 0;
-                this.symbolWidth = 0;
-                this.titleHeight = 0;
-                this.totalItemWidth = 0;
-                this.widthOption = 0;
-                this.chart = chart;
-                this.init(chart, options);
-            }
-            /* *
-             *
-             *  Functions
-             *
-             * */
-            /**
-             * Initialize the legend.
-             *
-             * @private
-             * @function Highcharts.Legend#init
-             *
-             * @param {Highcharts.Chart} chart
-             * The chart instance.
-             *
-             * @param {Highcharts.LegendOptions} options
-             * Legend options.
-             */
-            Legend.prototype.init = function (chart, options) {
-                /**
-                 * Chart of this legend.
-                 *
-                 * @readonly
-                 * @name Highcharts.Legend#chart
-                 * @type {Highcharts.Chart}
-                 */
-                this.chart = chart;
-                this.setOptions(options);
-                if (options.enabled) {
-                    // Render it
-                    this.render();
-                    // move checkboxes
-                    addEvent(this.chart, 'endResize', function () {
-                        this.legend.positionCheckboxes();
-                    });
-                    if (this.proximate) {
-                        this.unchartrender = addEvent(this.chart, 'render', function () {
-                            this.legend.proximatePositions();
-                            this.legend.positionItems();
-                        });
-                    }
-                    else if (this.unchartrender) {
-                        this.unchartrender();
-                    }
-                }
-            };
-            /**
-             * @private
-             * @function Highcharts.Legend#setOptions
-             * @param {Highcharts.LegendOptions} options
-             */
-            Legend.prototype.setOptions = function (options) {
-                var padding = pick(options.padding, 8);
-                /**
-                 * Legend options.
-                 *
-                 * @readonly
-                 * @name Highcharts.Legend#options
-                 * @type {Highcharts.LegendOptions}
-                 */
-                this.options = options;
-                if (!this.chart.styledMode) {
-                    this.itemStyle = options.itemStyle;
-                    this.itemHiddenStyle = merge(this.itemStyle, options.itemHiddenStyle);
-                }
-                this.itemMarginTop = options.itemMarginTop || 0;
-                this.itemMarginBottom = options.itemMarginBottom || 0;
-                this.padding = padding;
-                this.initialItemY = padding - 5; // 5 is pixels above the text
-                this.symbolWidth = pick(options.symbolWidth, 16);
-                this.pages = [];
-                this.proximate = options.layout === 'proximate' && !this.chart.inverted;
-                this.baseline = void 0; // #12705: baseline has to be reset on every update
-            };
-            /**
-             * Update the legend with new options. Equivalent to running `chart.update`
-             * with a legend configuration option.
-             *
-             * @sample highcharts/legend/legend-update/
-             *         Legend update
-             *
-             * @function Highcharts.Legend#update
-             *
-             * @param {Highcharts.LegendOptions} options
-             * Legend options.
-             *
-             * @param {boolean} [redraw=true]
-             * Whether to redraw the chart after the axis is altered. If doing more
-             * operations on the chart, it is a good idea to set redraw to false and
-             * call {@link Chart#redraw} after. Whether to redraw the chart.
-             *
-             * @fires Highcharts.Legends#event:afterUpdate
-             */
-            Legend.prototype.update = function (options, redraw) {
-                var chart = this.chart;
-                this.setOptions(merge(true, this.options, options));
-                this.destroy();
-                chart.isDirtyLegend = chart.isDirtyBox = true;
-                if (pick(redraw, true)) {
-                    chart.redraw();
-                }
-                fireEvent(this, 'afterUpdate');
-            };
-            /**
-             * Set the colors for the legend item.
-             *
-             * @private
-             * @function Highcharts.Legend#colorizeItem
-             * @param {Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series} item
-             *        A Series or Point instance
-             * @param {boolean} [visible=false]
-             *        Dimmed or colored
-             *
-             * @todo
-             * Make events official: Fires the event `afterColorizeItem`.
-             */
-            Legend.prototype.colorizeItem = function (item, visible) {
-                item.legendGroup[visible ? 'removeClass' : 'addClass']('highcharts-legend-item-hidden');
-                if (!this.chart.styledMode) {
-                    var legend = this,
-                        options = legend.options,
-                        legendItem = item.legendItem,
-                        legendLine = item.legendLine,
-                        legendSymbol = item.legendSymbol,
-                        hiddenColor = legend.itemHiddenStyle.color,
-                        textColor = visible ?
-                            options.itemStyle.color :
-                            hiddenColor,
-                        symbolColor = visible ?
-                            (item.color || hiddenColor) :
-                            hiddenColor,
-                        markerOptions = item.options && item.options.marker,
-                        symbolAttr = { fill: symbolColor };
-                    if (legendItem) {
-                        legendItem.css({
-                            fill: textColor,
-                            color: textColor // #1553, oldIE
-                        });
-                    }
-                    if (legendLine) {
-                        legendLine.attr({ stroke: symbolColor });
-                    }
-                    if (legendSymbol) {
-                        // Apply marker options
-                        if (markerOptions && legendSymbol.isMarker) { // #585
-                            symbolAttr = item.pointAttribs();
-                            if (!visible) {
-                                // #6769
-                                symbolAttr.stroke = symbolAttr.fill = hiddenColor;
-                            }
-                        }
-                        legendSymbol.attr(symbolAttr);
-                    }
-                }
-                fireEvent(this, 'afterColorizeItem', { item: item, visible: visible });
-            };
-            /**
-             * @private
-             * @function Highcharts.Legend#positionItems
-             */
-            Legend.prototype.positionItems = function () {
-                // Now that the legend width and height are established, put the items
-                // in the final position
-                this.allItems.forEach(this.positionItem, this);
-                if (!this.chart.isResizing) {
-                    this.positionCheckboxes();
-                }
-            };
-            /**
-             * Position the legend item.
-             *
-             * @private
-             * @function Highcharts.Legend#positionItem
-             * @param {Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series} item
-             * The item to position
-             */
-            Legend.prototype.positionItem = function (item) {
-                var _this = this;
-                var legend = this,
-                    options = legend.options,
-                    symbolPadding = options.symbolPadding,
-                    ltr = !options.rtl,
-                    legendItemPos = item._legendItemPos,
-                    itemX = legendItemPos[0],
-                    itemY = legendItemPos[1],
-                    checkbox = item.checkbox,
-                    legendGroup = item.legendGroup;
-                if (legendGroup && legendGroup.element) {
-                    var attribs = {
-                            translateX: ltr ?
-                                itemX :
-                                legend.legendWidth - itemX - 2 * symbolPadding - 4,
-                            translateY: itemY
-                        };
-                    var complete = function () {
-                            fireEvent(_this, 'afterPositionItem', { item: item });
-                    };
-                    if (defined(legendGroup.translateY)) {
-                        legendGroup.animate(attribs, void 0, complete);
-                    }
-                    else {
-                        legendGroup.attr(attribs);
-                        complete();
-                    }
-                }
-                if (checkbox) {
-                    checkbox.x = itemX;
-                    checkbox.y = itemY;
-                }
-            };
-            /**
-             * Destroy a single legend item, used internally on removing series items.
-             *
-             * @private
-             * @function Highcharts.Legend#destroyItem
-             * @param {Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series} item
-             * The item to remove
-             */
-            Legend.prototype.destroyItem = function (item) {
-                var checkbox = item.checkbox;
-                // destroy SVG elements
-                ['legendItem', 'legendLine', 'legendSymbol', 'legendGroup'].forEach(function (key) {
-                    if (item[key]) {
-                        item[key] = item[key].destroy();
-                    }
-                });
-                if (checkbox) {
-                    discardElement(item.checkbox);
-                }
-            };
-            /**
-             * Destroy the legend. Used internally. To reflow objects, `chart.redraw`
-             * must be called after destruction.
-             *
-             * @private
-             * @function Highcharts.Legend#destroy
-             */
-            Legend.prototype.destroy = function () {
-                /**
-                 * @private
-                 * @param {string} key
-                 * @return {void}
-                 */
-                function destroyItems(key) {
-                    if (this[key]) {
-                        this[key] = this[key].destroy();
-                    }
-                }
-                // Destroy items
-                this.getAllItems().forEach(function (item) {
-                    ['legendItem', 'legendGroup'].forEach(destroyItems, item);
-                });
-                // Destroy legend elements
-                [
-                    'clipRect',
-                    'up',
-                    'down',
-                    'pager',
-                    'nav',
-                    'box',
-                    'title',
-                    'group'
-                ].forEach(destroyItems, this);
-                this.display = null; // Reset in .render on update.
-            };
-            /**
-             * Position the checkboxes after the width is determined.
-             *
-             * @private
-             * @function Highcharts.Legend#positionCheckboxes
-             */
-            Legend.prototype.positionCheckboxes = function () {
-                var alignAttr = this.group && this.group.alignAttr,
-                    translateY,
-                    clipHeight = this.clipHeight || this.legendHeight,
-                    titleHeight = this.titleHeight;
-                if (alignAttr) {
-                    translateY = alignAttr.translateY;
-                    this.allItems.forEach(function (item) {
-                        var checkbox = item.checkbox,
-                            top;
-                        if (checkbox) {
-                            top = translateY + titleHeight + checkbox.y +
-                                (this.scrollOffset || 0) + 3;
-                            css(checkbox, {
-                                left: (alignAttr.translateX + item.checkboxOffset +
-                                    checkbox.x - 20) + 'px',
-                                top: top + 'px',
-                                display: this.proximate || (top > translateY - 6 &&
-                                    top < translateY + clipHeight - 6) ?
-                                    '' :
-                                    'none'
-                            });
-                        }
-                    }, this);
-                }
-            };
-            /**
-             * Render the legend title on top of the legend.
-             *
-             * @private
-             * @function Highcharts.Legend#renderTitle
-             */
-            Legend.prototype.renderTitle = function () {
-                var options = this.options,
-                    padding = this.padding,
-                    titleOptions = options.title,
-                    titleHeight = 0,
-                    bBox;
-                if (titleOptions.text) {
-                    if (!this.title) {
-                        /**
-                         * SVG element of the legend title.
-                         *
-                         * @readonly
-                         * @name Highcharts.Legend#title
-                         * @type {Highcharts.SVGElement}
-                         */
-                        this.title = this.chart.renderer.label(titleOptions.text, padding - 3, padding - 4, null, null, null, options.useHTML, null, 'legend-title')
-                            .attr({ zIndex: 1 });
-                        if (!this.chart.styledMode) {
-                            this.title.css(titleOptions.style);
-                        }
-                        this.title.add(this.group);
-                    }
-                    // Set the max title width (#7253)
-                    if (!titleOptions.width) {
-                        this.title.css({
-                            width: this.maxLegendWidth + 'px'
-                        });
-                    }
-                    bBox = this.title.getBBox();
-                    titleHeight = bBox.height;
-                    this.offsetWidth = bBox.width; // #1717
-                    this.contentGroup.attr({ translateY: titleHeight });
-                }
-                this.titleHeight = titleHeight;
-            };
-            /**
-             * Set the legend item text.
-             *
-             * @function Highcharts.Legend#setText
-             * @param {Highcharts.Point|Highcharts.Series} item
-             *        The item for which to update the text in the legend.
-             */
-            Legend.prototype.setText = function (item) {
-                var options = this.options;
-                item.legendItem.attr({
-                    text: options.labelFormat ?
-                        format(options.labelFormat, item, this.chart) :
-                        options.labelFormatter.call(item)
-                });
-            };
-            /**
-             * Render a single specific legend item. Called internally from the `render`
-             * function.
-             *
-             * @private
-             * @function Highcharts.Legend#renderItem
-             * @param {Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series} item
-             * The item to render.
-             */
-            Legend.prototype.renderItem = function (item) {
-                var legend = this,
-                    chart = legend.chart,
-                    renderer = chart.renderer,
-                    options = legend.options,
-                    horizontal = options.layout === 'horizontal',
-                    symbolWidth = legend.symbolWidth,
-                    symbolPadding = options.symbolPadding,
-                    itemStyle = legend.itemStyle,
-                    itemHiddenStyle = legend.itemHiddenStyle,
-                    itemDistance = horizontal ? pick(options.itemDistance, 20) : 0,
-                    ltr = !options.rtl,
-                    bBox,
-                    li = item.legendItem,
-                    isSeries = !item.series,
-                    series = !isSeries && item.series.drawLegendSymbol ?
-                        item.series :
-                        item,
-                    seriesOptions = series.options,
-                    showCheckbox = legend.createCheckboxForItem &&
-                        seriesOptions &&
-                        seriesOptions.showCheckbox, 
-                    // full width minus text width
-                    itemExtraWidth = symbolWidth + symbolPadding +
-                        itemDistance + (showCheckbox ? 20 : 0),
-                    useHTML = options.useHTML,
-                    itemClassName = item.options.className;
-                if (!li) { // generate it once, later move it
-                    // Generate the group box, a group to hold the symbol and text. Text
-                    // is to be appended in Legend class.
-                    item.legendGroup = renderer
-                        .g('legend-item')
-                        .addClass('highcharts-' + series.type + '-series ' +
-                        'highcharts-color-' + item.colorIndex +
-                        (itemClassName ? ' ' + itemClassName : '') +
-                        (isSeries ?
-                            ' highcharts-series-' + item.index :
-                            ''))
-                        .attr({ zIndex: 1 })
-                        .add(legend.scrollGroup);
-                    // Generate the list item text and add it to the group
-                    item.legendItem = li = renderer.text('', ltr ?
-                        symbolWidth + symbolPadding :
-                        -symbolPadding, legend.baseline || 0, useHTML);
-                    if (!chart.styledMode) {
-                        // merge to prevent modifying original (#1021)
-                        li.css(merge(item.visible ?
-                            itemStyle :
-                            itemHiddenStyle));
-                    }
-                    li
-                        .attr({
-                        align: ltr ? 'left' : 'right',
-                        zIndex: 2
-                    })
-                        .add(item.legendGroup);
-                    // Get the baseline for the first item - the font size is equal for
-                    // all
-                    if (!legend.baseline) {
-                        legend.fontMetrics = renderer.fontMetrics(chart.styledMode ? 12 : itemStyle.fontSize, li);
-                        legend.baseline =
-                            legend.fontMetrics.f + 3 + legend.itemMarginTop;
-                        li.attr('y', legend.baseline);
-                    }
-                    // Draw the legend symbol inside the group box
-                    legend.symbolHeight =
-                        options.symbolHeight || legend.fontMetrics.f;
-                    series.drawLegendSymbol(legend, item);
-                    if (legend.setItemEvents) {
-                        legend.setItemEvents(item, li, useHTML);
-                    }
-                }
-                // Add the HTML checkbox on top
-                if (showCheckbox && !item.checkbox && legend.createCheckboxForItem) {
-                    legend.createCheckboxForItem(item);
-                }
-                // Colorize the items
-                legend.colorizeItem(item, item.visible);
-                // Take care of max width and text overflow (#6659)
-                if (chart.styledMode || !itemStyle.width) {
-                    li.css({
-                        width: ((options.itemWidth ||
-                            legend.widthOption ||
-                            chart.spacingBox.width) - itemExtraWidth) + 'px'
-                    });
-                }
-                // Always update the text
-                legend.setText(item);
-                // calculate the positions for the next line
-                bBox = li.getBBox();
-                item.itemWidth = item.checkboxOffset =
-                    options.itemWidth ||
-                        item.legendItemWidth ||
-                        bBox.width + itemExtraWidth;
-                legend.maxItemWidth = Math.max(legend.maxItemWidth, item.itemWidth);
-                legend.totalItemWidth += item.itemWidth;
-                legend.itemHeight = item.itemHeight = Math.round(item.legendItemHeight || bBox.height || legend.symbolHeight);
-            };
-            /**
-             * Get the position of the item in the layout. We now know the
-             * maxItemWidth from the previous loop.
-             *
-             * @private
-             * @function Highcharts.Legend#layoutItem
-             * @param {Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series} item
-             */
-            Legend.prototype.layoutItem = function (item) {
-                var options = this.options,
-                    padding = this.padding,
-                    horizontal = options.layout === 'horizontal',
-                    itemHeight = item.itemHeight,
-                    itemMarginBottom = this.itemMarginBottom,
-                    itemMarginTop = this.itemMarginTop,
-                    itemDistance = horizontal ? pick(options.itemDistance, 20) : 0,
-                    maxLegendWidth = this.maxLegendWidth,
-                    itemWidth = (options.alignColumns &&
-                        this.totalItemWidth > maxLegendWidth) ?
-                        this.maxItemWidth :
-                        item.itemWidth;
-                // If the item exceeds the width, start a new line
-                if (horizontal &&
-                    this.itemX - padding + itemWidth > maxLegendWidth) {
-                    this.itemX = padding;
-                    if (this.lastLineHeight) { // Not for the first line (#10167)
-                        this.itemY += (itemMarginTop +
-                            this.lastLineHeight +
-                            itemMarginBottom);
-                    }
-                    this.lastLineHeight = 0; // reset for next line (#915, #3976)
-                }
-                // Set the edge positions
-                this.lastItemY = itemMarginTop + this.itemY + itemMarginBottom;
-                this.lastLineHeight = Math.max(// #915
-                itemHeight, this.lastLineHeight);
-                // cache the position of the newly generated or reordered items
-                item._legendItemPos = [this.itemX, this.itemY];
-                // advance
-                if (horizontal) {
-                    this.itemX += itemWidth;
-                }
-                else {
-                    this.itemY +=
-                        itemMarginTop + itemHeight + itemMarginBottom;
-                    this.lastLineHeight = itemHeight;
-                }
-                // the width of the widest item
-                this.offsetWidth = this.widthOption || Math.max((horizontal ? this.itemX - padding - (item.checkbox ?
-                    // decrease by itemDistance only when no checkbox #4853
-                    0 :
-                    itemDistance) : itemWidth) + padding, this.offsetWidth);
-            };
-            /**
-             * Get all items, which is one item per series for most series and one
-             * item per point for pie series and its derivatives. Fires the event
-             * `afterGetAllItems`.
-             *
-             * @private
-             * @function Highcharts.Legend#getAllItems
-             * @return {Array<(Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series)>}
-             * The current items in the legend.
-             * @fires Highcharts.Legend#event:afterGetAllItems
-             */
-            Legend.prototype.getAllItems = function () {
-                var allItems = [];
-                this.chart.series.forEach(function (series) {
-                    var seriesOptions = series && series.options;
-                    // Handle showInLegend. If the series is linked to another series,
-                    // defaults to false.
-                    if (series && pick(seriesOptions.showInLegend, !defined(seriesOptions.linkedTo) ? void 0 : false, true)) {
-                        // Use points or series for the legend item depending on
-                        // legendType
-                        allItems = allItems.concat(series.legendItems ||
-                            (seriesOptions.legendType === 'point' ?
-                                series.data :
-                                series));
-                    }
-                });
-                fireEvent(this, 'afterGetAllItems', { allItems: allItems });
-                return allItems;
-            };
-            /**
-             * Get a short, three letter string reflecting the alignment and layout.
-             *
-             * @private
-             * @function Highcharts.Legend#getAlignment
-             * @return {string}
-             * The alignment, empty string if floating
-             */
-            Legend.prototype.getAlignment = function () {
-                var options = this.options;
-                // Use the first letter of each alignment option in order to detect
-                // the side. (#4189 - use charAt(x) notation instead of [x] for IE7)
-                if (this.proximate) {
-                    return options.align.charAt(0) + 'tv';
-                }
-                return options.floating ? '' : (options.align.charAt(0) +
-                    options.verticalAlign.charAt(0) +
-                    options.layout.charAt(0));
-            };
-            /**
-             * Adjust the chart margins by reserving space for the legend on only one
-             * side of the chart. If the position is set to a corner, top or bottom is
-             * reserved for horizontal legends and left or right for vertical ones.
-             *
-             * @private
-             * @function Highcharts.Legend#adjustMargins
-             * @param {Array<number>} margin
-             * @param {Array<number>} spacing
-             */
-            Legend.prototype.adjustMargins = function (margin, spacing) {
-                var chart = this.chart,
-                    options = this.options,
-                    alignment = this.getAlignment();
-                if (alignment) {
-                    ([
-                        /(lth|ct|rth)/,
-                        /(rtv|rm|rbv)/,
-                        /(rbh|cb|lbh)/,
-                        /(lbv|lm|ltv)/
-                    ]).forEach(function (alignments, side) {
-                        if (alignments.test(alignment) && !defined(margin[side])) {
-                            // Now we have detected on which side of the chart we should
-                            // reserve space for the legend
-                            chart[marginNames[side]] = Math.max(chart[marginNames[side]], (chart.legend[(side + 1) % 2 ? 'legendHeight' : 'legendWidth'] +
-                                [1, -1, -1, 1][side] * options[(side % 2) ? 'x' : 'y'] +
-                                pick(options.margin, 12) +
-                                spacing[side] +
-                                (chart.titleOffset[side] || 0)));
-                        }
-                    });
-                }
-            };
-            /**
-             * @private
-             * @function Highcharts.Legend#proximatePositions
-             */
-            Legend.prototype.proximatePositions = function () {
-                var chart = this.chart,
-                    boxes = [],
-                    alignLeft = this.options.align === 'left';
-                this.allItems.forEach(function (item) {
-                    var lastPoint,
-                        height,
-                        useFirstPoint = alignLeft,
-                        target,
-                        top;
-                    if (item.yAxis) {
-                        if (item.xAxis.options.reversed) {
-                            useFirstPoint = !useFirstPoint;
-                        }
-                        if (item.points) {
-                            lastPoint = find(useFirstPoint ?
-                                item.points :
-                                item.points.slice(0).reverse(), function (item) {
-                                return isNumber(item.plotY);
-                            });
-                        }
-                        height = this.itemMarginTop +
-                            item.legendItem.getBBox().height +
-                            this.itemMarginBottom;
-                        top = item.yAxis.top - chart.plotTop;
-                        if (item.visible) {
-                            target = lastPoint ?
-                                lastPoint.plotY :
-                                item.yAxis.height;
-                            target += top - 0.3 * height;
-                        }
-                        else {
-                            target = top + item.yAxis.height;
-                        }
-                        boxes.push({
-                            target: target,
-                            size: height,
-                            item: item
-                        });
-                    }
-                }, this);
-                H.distribute(boxes, chart.plotHeight);
-                boxes.forEach(function (box) {
-                    box.item._legendItemPos[1] =
-                        chart.plotTop - chart.spacing[0] + box.pos;
-                });
-            };
-            /**
-             * Render the legend. This method can be called both before and after
-             * `chart.render`. If called after, it will only rearrange items instead
-             * of creating new ones. Called internally on initial render and after
-             * redraws.
-             *
-             * @private
-             * @function Highcharts.Legend#render
-             */
-            Legend.prototype.render = function () {
-                var legend = this,
-                    chart = legend.chart,
-                    renderer = chart.renderer,
-                    legendGroup = legend.group,
-                    allItems,
-                    display,
-                    legendWidth,
-                    legendHeight,
-                    box = legend.box,
-                    options = legend.options,
-                    padding = legend.padding,
-                    allowedWidth;
-                legend.itemX = padding;
-                legend.itemY = legend.initialItemY;
-                legend.offsetWidth = 0;
-                legend.lastItemY = 0;
-                legend.widthOption = relativeLength(options.width, chart.spacingBox.width - padding);
-                // Compute how wide the legend is allowed to be
-                allowedWidth =
-                    chart.spacingBox.width - 2 * padding - options.x;
-                if (['rm', 'lm'].indexOf(legend.getAlignment().substring(0, 2)) > -1) {
-                    allowedWidth /= 2;
-                }
-                legend.maxLegendWidth = legend.widthOption || allowedWidth;
-                if (!legendGroup) {
-                    /**
-                     * SVG group of the legend.
-                     *
-                     * @readonly
-                     * @name Highcharts.Legend#group
-                     * @type {Highcharts.SVGElement}
-                     */
-                    legend.group = legendGroup = renderer.g('legend')
-                        .attr({ zIndex: 7 })
-                        .add();
-                    legend.contentGroup = renderer.g()
-                        .attr({ zIndex: 1 }) // above background
-                        .add(legendGroup);
-                    legend.scrollGroup = renderer.g()
-                        .add(legend.contentGroup);
-                }
-                legend.renderTitle();
-                // add each series or point
-                allItems = legend.getAllItems();
-                // sort by legendIndex
-                stableSort(allItems, function (a, b) {
-                    return ((a.options && a.options.legendIndex) || 0) -
-                        ((b.options && b.options.legendIndex) || 0);
-                });
-                // reversed legend
-                if (options.reversed) {
-                    allItems.reverse();
-                }
-                /**
-                 * All items for the legend, which is an array of series for most series
-                 * and an array of points for pie series and its derivatives.
-                 *
-                 * @readonly
-                 * @name Highcharts.Legend#allItems
-                 * @type {Array<(Highcharts.Point|Highcharts.Series)>}
-                 */
-                legend.allItems = allItems;
-                legend.display = display = !!allItems.length;
-                // Render the items. First we run a loop to set the text and properties
-                // and read all the bounding boxes. The next loop computes the item
-                // positions based on the bounding boxes.
-                legend.lastLineHeight = 0;
-                legend.maxItemWidth = 0;
-                legend.totalItemWidth = 0;
-                legend.itemHeight = 0;
-                allItems.forEach(legend.renderItem, legend);
-                allItems.forEach(legend.layoutItem, legend);
-                // Get the box
-                legendWidth = (legend.widthOption || legend.offsetWidth) + padding;
-                legendHeight = legend.lastItemY + legend.lastLineHeight +
-                    legend.titleHeight;
-                legendHeight = legend.handleOverflow(legendHeight);
-                legendHeight += padding;
-                // Draw the border and/or background
-                if (!box) {
-                    /**
-                     * SVG element of the legend box.
-                     *
-                     * @readonly
-                     * @name Highcharts.Legend#box
-                     * @type {Highcharts.SVGElement}
-                     */
-                    legend.box = box = renderer.rect()
-                        .addClass('highcharts-legend-box')
-                        .attr({
-                        r: options.borderRadius
-                    })
-                        .add(legendGroup);
-                    box.isNew = true;
-                }
-                // Presentational
-                if (!chart.styledMode) {
-                    box
-                        .attr({
-                        stroke: options.borderColor,
-                        'stroke-width': options.borderWidth || 0,
-                        fill: options.backgroundColor || 'none'
-                    })
-                        .shadow(options.shadow);
-                }
-                if (legendWidth > 0 && legendHeight > 0) {
-                    box[box.isNew ? 'attr' : 'animate'](box.crisp.call({}, {
-                        x: 0,
-                        y: 0,
-                        width: legendWidth,
-                        height: legendHeight
-                    }, box.strokeWidth()));
-                    box.isNew = false;
-                }
-                // hide the border if no items
-                box[display ? 'show' : 'hide']();
-                // Open for responsiveness
-                if (chart.styledMode && legendGroup.getStyle('display') === 'none') {
-                    legendWidth = legendHeight = 0;
-                }
-                legend.legendWidth = legendWidth;
-                legend.legendHeight = legendHeight;
-                if (display) {
-                    legend.align();
-                }
-                if (!this.proximate) {
-                    this.positionItems();
-                }
-                fireEvent(this, 'afterRender');
-            };
-            /**
-             * Align the legend to chart's box.
-             *
-             * @private
-             * @function Highcharts.align
-             * @param {Highcharts.BBoxObject} alignTo
-             * @return {void}
-             */
-            Legend.prototype.align = function (alignTo) {
-                if (alignTo === void 0) { alignTo = this.chart.spacingBox; }
-                var chart = this.chart,
-                    options = this.options;
-                // If aligning to the top and the layout is horizontal, adjust for
-                // the title (#7428)
-                var y = alignTo.y;
-                if (/(lth|ct|rth)/.test(this.getAlignment()) &&
-                    chart.titleOffset[0] > 0) {
-                    y += chart.titleOffset[0];
-                }
-                else if (/(lbh|cb|rbh)/.test(this.getAlignment()) &&
-                    chart.titleOffset[2] > 0) {
-                    y -= chart.titleOffset[2];
-                }
-                if (y !== alignTo.y) {
-                    alignTo = merge(alignTo, { y: y });
-                }
-                this.group.align(merge(options, {
-                    width: this.legendWidth,
-                    height: this.legendHeight,
-                    verticalAlign: this.proximate ? 'top' : options.verticalAlign
-                }), true, alignTo);
-            };
-            /**
-             * Set up the overflow handling by adding navigation with up and down arrows
-             * below the legend.
-             *
-             * @private
-             * @function Highcharts.Legend#handleOverflow
-             * @param {number} legendHeight
-             * @return {number}
-             */
-            Legend.prototype.handleOverflow = function (legendHeight) {
-                var legend = this,
-                    chart = this.chart,
-                    renderer = chart.renderer,
-                    options = this.options,
-                    optionsY = options.y,
-                    alignTop = options.verticalAlign === 'top',
-                    padding = this.padding,
-                    spaceHeight = (chart.spacingBox.height +
-                        (alignTop ? -optionsY : optionsY) - padding),
-                    maxHeight = options.maxHeight,
-                    clipHeight,
-                    clipRect = this.clipRect,
-                    navOptions = options.navigation,
-                    animation = pick(navOptions.animation,
-                    true),
-                    arrowSize = navOptions.arrowSize || 12,
-                    nav = this.nav,
-                    pages = this.pages,
-                    lastY,
-                    allItems = this.allItems,
-                    clipToHeight = function (height) {
-                        if (typeof height === 'number') {
-                            clipRect.attr({
-                                height: height
-                            });
-                    }
-                    else if (clipRect) { // Reset (#5912)
-                        legend.clipRect = clipRect.destroy();
-                        legend.contentGroup.clip();
-                    }
-                    // useHTML
-                    if (legend.contentGroup.div) {
-                        legend.contentGroup.div.style.clip = height ?
-                            'rect(' + padding + 'px,9999px,' +
-                                (padding + height) + 'px,0)' :
-                            'auto';
-                    }
-                }, addTracker = function (key) {
-                    legend[key] = renderer
-                        .circle(0, 0, arrowSize * 1.3)
-                        .translate(arrowSize / 2, arrowSize / 2)
-                        .add(nav);
-                    if (!chart.styledMode) {
-                        legend[key].attr('fill', 'rgba(0,0,0,0.0001)');
-                    }
-                    return legend[key];
-                };
-                // Adjust the height
-                if (options.layout === 'horizontal' &&
-                    options.verticalAlign !== 'middle' &&
-                    !options.floating) {
-                    spaceHeight /= 2;
-                }
-                if (maxHeight) {
-                    spaceHeight = Math.min(spaceHeight, maxHeight);
-                }
-                // Reset the legend height and adjust the clipping rectangle
-                pages.length = 0;
-                if (legendHeight > spaceHeight &&
-                    navOptions.enabled !== false) {
-                    this.clipHeight = clipHeight =
-                        Math.max(spaceHeight - 20 - this.titleHeight - padding, 0);
-                    this.currentPage = pick(this.currentPage, 1);
-                    this.fullHeight = legendHeight;
-                    // Fill pages with Y positions so that the top of each a legend item
-                    // defines the scroll top for each page (#2098)
-                    allItems.forEach(function (item, i) {
-                        var y = item._legendItemPos[1],
-                            h = Math.round(item.legendItem.getBBox().height),
-                            len = pages.length;
-                        if (!len || (y - pages[len - 1] > clipHeight &&
-                            (lastY || y) !== pages[len - 1])) {
-                            pages.push(lastY || y);
-                            len++;
-                        }
-                        // Keep track of which page each item is on
-                        item.pageIx = len - 1;
-                        if (lastY) {
-                            allItems[i - 1].pageIx = len - 1;
-                        }
-                        if (i === allItems.length - 1 &&
-                            y + h - pages[len - 1] > clipHeight &&
-                            y !== lastY // #2617
-                        ) {
-                            pages.push(y);
-                            item.pageIx = len;
-                        }
-                        if (y !== lastY) {
-                            lastY = y;
-                        }
-                    });
-                    // Only apply clipping if needed. Clipping causes blurred legend in
-                    // PDF export (#1787)
-                    if (!clipRect) {
-                        clipRect = legend.clipRect =
-                            renderer.clipRect(0, padding, 9999, 0);
-                        legend.contentGroup.clip(clipRect);
-                    }
-                    clipToHeight(clipHeight);
-                    // Add navigation elements
-                    if (!nav) {
-                        this.nav = nav = renderer.g()
-                            .attr({ zIndex: 1 })
-                            .add(this.group);
-                        this.up = renderer
-                            .symbol('triangle', 0, 0, arrowSize, arrowSize)
-                            .add(nav);
-                        addTracker('upTracker')
-                            .on('click', function () {
-                            legend.scroll(-1, animation);
-                        });
-                        this.pager = renderer.text('', 15, 10)
-                            .addClass('highcharts-legend-navigation');
-                        if (!chart.styledMode) {
-                            this.pager.css(navOptions.style);
-                        }
-                        this.pager.add(nav);
-                        this.down = renderer
-                            .symbol('triangle-down', 0, 0, arrowSize, arrowSize)
-                            .add(nav);
-                        addTracker('downTracker')
-                            .on('click', function () {
-                            legend.scroll(1, animation);
-                        });
-                    }
-                    // Set initial position
-                    legend.scroll(0);
-                    legendHeight = spaceHeight;
-                    // Reset
-                }
-                else if (nav) {
-                    clipToHeight();
-                    this.nav = nav.destroy(); // #6322
-                    this.scrollGroup.attr({
-                        translateY: 1
-                    });
-                    this.clipHeight = 0; // #1379
-                }
-                return legendHeight;
-            };
-            /**
-             * Scroll the legend by a number of pages.
-             *
-             * @private
-             * @function Highcharts.Legend#scroll
-             *
-             * @param {number} scrollBy
-             *        The number of pages to scroll.
-             *
-             * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation]
-             *        Whether and how to apply animation.
-             *
-             * @return {void}
-             */
-            Legend.prototype.scroll = function (scrollBy, animation) {
-                var _this = this;
-                var chart = this.chart,
-                    pages = this.pages,
-                    pageCount = pages.length,
-                    currentPage = this.currentPage + scrollBy,
-                    clipHeight = this.clipHeight,
-                    navOptions = this.options.navigation,
-                    pager = this.pager,
-                    padding = this.padding;
-                // When resizing while looking at the last page
-                if (currentPage > pageCount) {
-                    currentPage = pageCount;
-                }
-                if (currentPage > 0) {
-                    if (typeof animation !== 'undefined') {
-                        setAnimation(animation, chart);
-                    }
-                    this.nav.attr({
-                        translateX: padding,
-                        translateY: clipHeight + this.padding + 7 + this.titleHeight,
-                        visibility: 'visible'
-                    });
-                    [this.up, this.upTracker].forEach(function (elem) {
-                        elem.attr({
-                            'class': currentPage === 1 ?
-                                'highcharts-legend-nav-inactive' :
-                                'highcharts-legend-nav-active'
-                        });
-                    });
-                    pager.attr({
-                        text: currentPage + '/' + pageCount
-                    });
-                    [this.down, this.downTracker].forEach(function (elem) {
-                        elem.attr({
-                            // adjust to text width
-                            x: 18 + this.pager.getBBox().width,
-                            'class': currentPage === pageCount ?
-                                'highcharts-legend-nav-inactive' :
-                                'highcharts-legend-nav-active'
-                        });
-                    }, this);
-                    if (!chart.styledMode) {
-                        this.up
-                            .attr({
-                            fill: currentPage === 1 ?
-                                navOptions.inactiveColor :
-                                navOptions.activeColor
-                        });
-                        this.upTracker
-                            .css({
-                            cursor: currentPage === 1 ? 'default' : 'pointer'
-                        });
-                        this.down
-                            .attr({
-                            fill: currentPage === pageCount ?
-                                navOptions.inactiveColor :
-                                navOptions.activeColor
-                        });
-                        this.downTracker
-                            .css({
-                            cursor: currentPage === pageCount ?
-                                'default' :
-                                'pointer'
-                        });
-                    }
-                    this.scrollOffset = -pages[currentPage - 1] + this.initialItemY;
-                    this.scrollGroup.animate({
-                        translateY: this.scrollOffset
-                    });
-                    this.currentPage = currentPage;
-                    this.positionCheckboxes();
-                    // Fire event after scroll animation is complete
-                    var animOptions = animObject(pick(animation,
-                        chart.renderer.globalAnimation,
-                        true));
-                    syncTimeout(function () {
-                        fireEvent(_this, 'afterScroll', { currentPage: currentPage });
-                    }, animOptions.duration);
-                }
-            };
-            return Legend;
-        }());
-        // Workaround for #2030, horizontal legend items not displaying in IE11 Preview,
-        // and for #2580, a similar drawing flaw in Firefox 26.
-        // Explore if there's a general cause for this. The problem may be related
-        // to nested group elements, as the legend item texts are within 4 group
-        // elements.
-        if (/Trident\/7\.0/.test(win.navigator && win.navigator.userAgent) ||
-            isFirefox) {
-            wrap(Legend.prototype, 'positionItem', function (proceed, item) {
-                var legend = this, 
-                    // If chart destroyed in sync, this is undefined (#2030)
-                    runPositionItem = function () {
-                        if (item._legendItemPos) {
-                            proceed.call(legend,
-                    item);
-                    }
-                };
-                // Do it now, for export and to get checkbox placement
-                runPositionItem();
-                // Do it after to work around the core issue
-                if (!legend.bubbleLegend) {
-                    setTimeout(runPositionItem);
-                }
-            });
-        }
-        H.Legend = Legend;
-
-        return H.Legend;
-    });
-    _registerModule(_modules, 'Core/Series/Point.js', [_modules['Core/Animation/AnimationUtilities.js'], _modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (A, H, U) {
-        /* *
-         *
-         *  (c) 2010-2020 Torstein Honsi
-         *
-         *  License: www.highcharts.com/license
-         *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
-         *
-         * */
-        var animObject = A.animObject;
-        var defined = U.defined,
-            erase = U.erase,
-            extend = U.extend,
-            fireEvent = U.fireEvent,
-            format = U.format,
-            getNestedProperty = U.getNestedProperty,
-            isArray = U.isArray,
-            isNumber = U.isNumber,
-            isObject = U.isObject,
-            syncTimeout = U.syncTimeout,
-            pick = U.pick,
-            removeEvent = U.removeEvent,
-            uniqueKey = U.uniqueKey;
-        /**
-         * Function callback when a series point is clicked. Return false to cancel the
-         * action.
-         *
-         * @callback Highcharts.PointClickCallbackFunction
-         *
-         * @param {Highcharts.Point} this
-         *        The point where the event occured.
-         *
-         * @param {Highcharts.PointClickEventObject} event
-         *        Event arguments.
-         */
-        /**
-         * Common information for a click event on a series point.
-         *
-         * @interface Highcharts.PointClickEventObject
-         * @extends Highcharts.PointerEventObject
-         */ /**
-        * Clicked point.
-        * @name Highcharts.PointClickEventObject#point
-        * @type {Highcharts.Point}
-        */
-        /**
-         * Configuration hash for the data label and tooltip formatters.
-         *
-         * @interface Highcharts.PointLabelObject
-         */ /**
-        * The point's current color.
-        * @name Highcharts.PointLabelObject#color
-        * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject|undefined}
-        */ /**
-        * The point's current color index, used in styled mode instead of `color`. The
-        * color index is inserted in class names used for styling.
-        * @name Highcharts.PointLabelObject#colorIndex
-        * @type {number}
-        */ /**
-        * The name of the related point.
-        * @name Highcharts.PointLabelObject#key
-        * @type {string|undefined}
-        */ /**
-        * The percentage for related points in a stacked series or pies.
-        * @name Highcharts.PointLabelObject#percentage
-        * @type {number}
-        */ /**
-        * The related point. The point name, if defined, is available through
-        * `this.point.name`.
-        * @name Highcharts.PointLabelObject#point
-        * @type {Highcharts.Point}
-        */ /**
-        * The related series. The series name is available through `this.series.name`.
-        * @name Highcharts.PointLabelObject#series
-        * @type {Highcharts.Series}
-        */ /**
-        * The total of values in either a stack for stacked series, or a pie in a pie
-        * series.
-        * @name Highcharts.PointLabelObject#total
-        * @type {number|undefined}
-        */ /**
-        * For categorized axes this property holds the category name for the point. For
-        * other axes it holds the X value.
-        * @name Highcharts.PointLabelObject#x
-        * @type {number|string|undefined}
-        */ /**
-        * The y value of the point.
-        * @name Highcharts.PointLabelObject#y
-        * @type {number|undefined}
-        */
-        /**
-         * Gets fired when the mouse leaves the area close to the point.
-         *
-         * @callback Highcharts.PointMouseOutCallbackFunction
-         *
-         * @param {Highcharts.Point} this
-         *        Point where the event occured.
-         *
-         * @param {global.PointerEvent} event
-         *        Event that occured.
-         */
-        /**
-         * Gets fired when the mouse enters the area close to the point.
-         *
-         * @callback Highcharts.PointMouseOverCallbackFunction
-         *
-         * @param {Highcharts.Point} this
-         *        Point where the event occured.
-         *
-         * @param {global.Event} event
-         *        Event that occured.
-         */
-        /**
-         * The generic point options for all series.
-         *
-         * In TypeScript you have to extend `PointOptionsObject` with an additional
-         * declaration to allow custom data options:
-         *
-         * ```
-         * declare interface PointOptionsObject {
-         *     customProperty: string;
-         * }
-         * ```
-         *
-         * @interface Highcharts.PointOptionsObject
-         */
-        /**
-         * Possible option types for a data point. Use `null` to indicate a gap.
-         *
-         * @typedef {number|string|Highcharts.PointOptionsObject|Array<(number|string|null)>|null} Highcharts.PointOptionsType
-         */
-        /**
-         * Gets fired when the point is removed using the `.remove()` method.
-         *
-         * @callback Highcharts.PointRemoveCallbackFunction
-         *
-         * @param {Highcharts.Point} this
-         *        Point where the event occured.
-         *
-         * @param {global.Event} event
-         *        Event that occured.
-         */
-        /**
-         * Possible key values for the point state options.
-         *
-         * @typedef {"hover"|"inactive"|"normal"|"select"} Highcharts.PointStateValue
-         */
-        /**
-         * Gets fired when the point is updated programmatically through the `.update()`
-         * method.
-         *
-         * @callback Highcharts.PointUpdateCallbackFunction
-         *
-         * @param {Highcharts.Point} this
-         *        Point where the event occured.
-         *
-         * @param {Highcharts.PointUpdateEventObject} event
-         *        Event that occured.
-         */
-        /**
-         * Information about the update event.
-         *
-         * @interface Highcharts.PointUpdateEventObject
-         * @extends global.Event
-         */ /**
-        * Options data of the update event.
-        * @name Highcharts.PointUpdateEventObject#options
-        * @type {Highcharts.PointOptionsType}
-        */
-        ''; // detach doclet above
-        /* eslint-disable no-invalid-this, valid-jsdoc */
-        /**
-         * The Point object. The point objects are generated from the `series.data`
-         * configuration objects or raw numbers. They can be accessed from the
-         * `Series.points` array. Other ways to instantiate points are through {@link
-         * Highcharts.Series#addPoint} or {@link Highcharts.Series#setData}.
-         *
-         * @class
-         * @name Highcharts.Point
-         */
-        var Point = /** @class */ (function () {
-                function Point() {
-                    /* *
-                     *
-                     *  Properties
-                     *
-                     * */
-                    /**
-                     * For categorized axes this property holds the category name for the
-                     * point. For other axes it holds the X value.
-                     *
-                     * @name Highcharts.Point#category
-                     * @type {string}
-                     */
-                    this.category = void 0;
-                /**
-                 * The point's current color index, used in styled mode instead of
-                 * `color`. The color index is inserted in class names used for styling.
-                 *
-                 * @name Highcharts.Point#colorIndex
-                 * @type {number}
-                 */
-                this.colorIndex = void 0;
-                this.formatPrefix = 'point';
-                this.id = void 0;
-                this.isNull = false;
-                /**
-                 * The name of the point. The name can be given as the first position of the
-                 * point configuration array, or as a `name` property in the configuration:
-                 *
-                 * @example
-                 * // Array config
-                 * data: [
-                 *     ['John', 1],
-                 *     ['Jane', 2]
-                 * ]
-                 *
-                 * // Object config
-                 * data: [{
-                 *        name: 'John',
-                 *        y: 1
-                 * }, {
-                 *     name: 'Jane',
-                 *     y: 2
-                 * }]
-                 *
-                 * @name Highcharts.Point#name
-                 * @type {string}
-                 */
-                this.name = void 0;
-                /**
-                 * The point's options as applied in the initial configuration, or
-                 * extended through `Point.update`.
-                 *
-                 * In TypeScript you have to extend `PointOptionsObject` via an
-                 * additional interface to allow custom data options:
-                 *
-                 * ```
-                 * declare interface PointOptionsObject {
-                 *     customProperty: string;
-                 * }
-                 * ```
-                 *
-                 * @name Highcharts.Point#options
-                 * @type {Highcharts.PointOptionsObject}
-                 */
-                this.options = void 0;
-                /**
-                 * The percentage for points in a stacked series or pies.
-                 *
-                 * @name Highcharts.Point#percentage
-                 * @type {number|undefined}
-                 */
-                this.percentage = void 0;
-                this.selected = false;
-                /**
-                 * The series object associated with the point.
-                 *
-                 * @name Highcharts.Point#series
-                 * @type {Highcharts.Series}
-                 */
-                this.series = void 0;
-                /**
-                 * The total of values in either a stack for stacked series, or a pie in a
-                 * pie series.
-                 *
-                 * @name Highcharts.Point#total
-                 * @type {number|undefined}
-                 */
-                this.total = void 0;
-                /**
-                 * For certain series types, like pie charts, where individual points can
-                 * be shown or hidden.
-                 *
-                 * @name Highcharts.Point#visible
-                 * @type {boolean}
-                 * @default true
-                 */
-                this.visible = true;
-                this.x = void 0;
-            }
-            /* *
-             *
-             *  Functions
-             *
-             * */
-            /**
-             * Animate SVG elements associated with the point.
-             *
-             * @private
-             * @function Highcharts.Point#animateBeforeDestroy
-             */
-            Point.prototype.animateBeforeDestroy = function () {
-                var point = this,
-                    animateParams = { x: point.startXPos,
-                    opacity: 0 },
-                    isDataLabel,
-                    graphicalProps = point.getGraphicalProps();
-                graphicalProps.singular.forEach(function (prop) {
-                    isDataLabel = prop === 'dataLabel';
-                    point[prop] = point[prop].animate(isDataLabel ? {
-                        x: point[prop].startXPos,
-                        y: point[prop].startYPos,
-                        opacity: 0
-                    } : animateParams);
-                });
-                graphicalProps.plural.forEach(function (plural) {
-                    point[plural].forEach(function (item) {
-                        if (item.element) {
-                            item.animate(extend({ x: point.startXPos }, (item.startYPos ? {
-                                x: item.startXPos,
-                                y: item.startYPos
-                            } : {})));
-                        }
-                    });
-                });
-            };
-            /**
-             * Apply the options containing the x and y data and possible some extra
-             * properties. Called on point init or from point.update.
-             *
-             * @private
-             * @function Highcharts.Point#applyOptions
-             *
-             * @param {Highcharts.PointOptionsType} options
-             *        The point options as defined in series.data.
-             *
-             * @param {number} [x]
-             *        Optionally, the x value.
-             *
-             * @return {Highcharts.Point}
-             *         The Point instance.
-             */
-            Point.prototype.applyOptions = function (options, x) {
-                var point = this,
-                    series = point.series,
-                    pointValKey = series.options.pointValKey || series.pointValKey;
-                options = Point.prototype.optionsToObject.call(this, options);
-                // copy options directly to point
-                extend(point, options);
-                point.options = point.options ? extend(point.options, options) : options;
-                // Since options are copied into the Point instance, some accidental
-                // options must be shielded (#5681)
-                if (options.group) {
-                    delete point.group;
-                }
-                if (options.dataLabels) {
-                    delete point.dataLabels;
-                }
-                /**
-                 * The y value of the point.
-                 * @name Highcharts.Point#y
-                 * @type {number|undefined}
-                 */
-                // For higher dimension series types. For instance, for ranges, point.y
-                // is mapped to point.low.
-                if (pointValKey) {
-                    point.y = Point.prototype.getNestedProperty.call(point, pointValKey);
-                }
-                point.isNull = pick(point.isValid && !point.isValid(), point.x === null || !isNumber(point.y)); // #3571, check for NaN
-                point.formatPrefix = point.isNull ? 'null' : 'point'; // #9233, #10874
-                // The point is initially selected by options (#5777)
-                if (point.selected) {
-                    point.state = 'select';
-                }
-                /**
-                 * The x value of the point.
-                 * @name Highcharts.Point#x
-                 * @type {number}
-                 */
-                // If no x is set by now, get auto incremented value. All points must
-                // have an x value, however the y value can be null to create a gap in
-                // the series
-                if ('name' in point &&
-                    typeof x === 'undefined' &&
-                    series.xAxis &&
-                    series.xAxis.hasNames) {
-                    point.x = series.xAxis.nameToX(point);
-                }
-                if (typeof point.x === 'undefined' && series) {
-                    if (typeof x === 'undefined') {
-                        point.x = series.autoIncrement(point);
-                    }
-                    else {
-                        point.x = x;
-                    }
-                }
-                return point;
-            };
-            /**
-             * Destroy a point to clear memory. Its reference still stays in
-             * `series.data`.
-             *
-             * @private
-             * @function Highcharts.Point#destroy
-             */
-            Point.prototype.destroy = function () {
-                var point = this,
-                    series = point.series,
-                    chart = series.chart,
-                    dataSorting = series.options.dataSorting,
-                    hoverPoints = chart.hoverPoints,
-                    globalAnimation = point.series.chart.renderer.globalAnimation,
-                    animation = animObject(globalAnimation),
-                    prop;
-                /**
-                 * Allow to call after animation.
-                 * @private
-                 */
-                function destroyPoint() {
-                    // Remove all events and elements
-                    if (point.graphic || point.dataLabel || point.dataLabels) {
-                        removeEvent(point);
-                        point.destroyElements();
-                    }
-                    for (prop in point) { // eslint-disable-line guard-for-in
-                        point[prop] = null;
-                    }
-                }
-                if (point.legendItem) { // pies have legend items
-                    chart.legend.destroyItem(point);
-                }
-                if (hoverPoints) {
-                    point.setState();
-                    erase(hoverPoints, point);
-                    if (!hoverPoints.length) {
-                        chart.hoverPoints = null;
-                    }
-                }
-                if (point === chart.hoverPoint) {
-                    point.onMouseOut();
-                }
-                // Remove properties after animation
-                if (!dataSorting || !dataSorting.enabled) {
-                    destroyPoint();
-                }
-                else {
-                    this.animateBeforeDestroy();
-                    syncTimeout(destroyPoint, animation.duration);
-                }
-                chart.pointCount--;
-            };
-            /**
-             * Destroy SVG elements associated with the point.
-             *
-             * @private
-             * @function Highcharts.Point#destroyElements
-             * @param {Highcharts.Dictionary<number>} [kinds]
-             */
-            Point.prototype.destroyElements = function (kinds) {
-                var point = this,
-                    props = point.getGraphicalProps(kinds);
-                props.singular.forEach(function (prop) {
-                    point[prop] = point[prop].destroy();
-                });
-                props.plural.forEach(function (plural) {
-                    point[plural].forEach(function (item) {
-                        if (item.element) {
-                            item.destroy();
-                        }
-                    });
-                    delete point[plural];
-                });
-            };
-            /**
-             * Fire an event on the Point object.
-             *
-             * @private
-             * @function Highcharts.Point#firePointEvent
-             *
-             * @param {string} eventType
-             *        Type of the event.
-             *
-             * @param {Highcharts.Dictionary<any>|Event} [eventArgs]
-             *        Additional event arguments.
-             *
-             * @param {Highcharts.EventCallbackFunction<Highcharts.Point>|Function} [defaultFunction]
-             *        Default event handler.
-             *
-             * @fires Highcharts.Point#event:*
-             */
-            Point.prototype.firePointEvent = function (eventType, eventArgs, defaultFunction) {
-                var point = this,
-                    series = this.series,
-                    seriesOptions = series.options;
-                // load event handlers on demand to save time on mouseover/out
-                if (seriesOptions.point.events[eventType] ||
-                    (point.options &&
-                        point.options.events &&
-                        point.options.events[eventType])) {
-                    point.importEvents();
-                }
-                // add default handler if in selection mode
-                if (eventType === 'click' && seriesOptions.allowPointSelect) {
-                    defaultFunction = function (event) {
-                        // Control key is for Windows, meta (= Cmd key) for Mac, Shift
-                        // for Opera.
-                        if (point.select) { // #2911
-                            point.select(null, event.ctrlKey || event.metaKey || event.shiftKey);
-                        }
-                    };
-                }
-                fireEvent(point, eventType, eventArgs, defaultFunction);
-            };
-            /**
-             * Get the CSS class names for individual points. Used internally where the
-             * returned value is set on every point.
-             *
-             * @function Highcharts.Point#getClassName
-             *
-             * @return {string}
-             *         The class names.
-             */
-            Point.prototype.getClassName = function () {
-                var point = this;
-                return 'highcharts-point' +
-                    (point.selected ? ' highcharts-point-select' : '') +
-                    (point.negative ? ' highcharts-negative' : '') +
-                    (point.isNull ? ' highcharts-null-point' : '') +
-                    (typeof point.colorIndex !== 'undefined' ?
-                        ' highcharts-color-' + point.colorIndex : '') +
-                    (point.options.className ? ' ' + point.options.className : '') +
-                    (point.zone && point.zone.className ? ' ' +
-                        point.zone.className.replace('highcharts-negative', '') : '');
-            };
-            /**
-             * Get props of all existing graphical point elements.
-             *
-             * @private
-             * @function Highcharts.Point#getGraphicalProps
-             * @param {Highcharts.Dictionary<number>} [kinds]
-             * @return {Highcharts.PointGraphicalProps}
-             */
-            Point.prototype.getGraphicalProps = function (kinds) {
-                var point = this,
-                    props = [],
-                    prop,
-                    i,
-                    graphicalProps = { singular: [],
-                    plural: [] };
-                kinds = kinds || { graphic: 1, dataLabel: 1 };
-                if (kinds.graphic) {
-                    props.push('graphic', 'shadowGroup');
-                }
-                if (kinds.dataLabel) {
-                    props.push('dataLabel', 'dataLabelUpper', 'connector');
-                }
-                i = props.length;
-                while (i--) {
-                    prop = props[i];
-                    if (point[prop]) {
-                        graphicalProps.singular.push(prop);
-                    }
-                }
-                ['dataLabel', 'connector'].forEach(function (prop) {
-                    var plural = prop + 's';
-                    if (kinds[prop] && point[plural]) {
-                        graphicalProps.plural.push(plural);
-                    }
-                });
-                return graphicalProps;
-            };
-            /**
-             * Return the configuration hash needed for the data label and tooltip
-             * formatters.
-             *
-             * @function Highcharts.Point#getLabelConfig
-             *
-             * @return {Highcharts.PointLabelObject}
-             *         Abstract object used in formatters and formats.
-             */
-            Point.prototype.getLabelConfig = function () {
-                return {
-                    x: this.category,
-                    y: this.y,
-                    color: this.color,
-                    colorIndex: this.colorIndex,
-                    key: this.name || this.category,
-                    series: this.series,
-                    point: this,
-                    percentage: this.percentage,
-                    total: this.total || this.stackTotal
-                };
-            };
-            /**
-             * Returns the value of the point property for a given value.
-             * @private
-             */
-            Point.prototype.getNestedProperty = function (key) {
-                if (!key) {
-                    return;
-                }
-                if (key.indexOf('custom.') === 0) {
-                    return getNestedProperty(key, this.options);
-                }
-                return this[key];
-            };
-            /**
-             * In a series with `zones`, return the zone that the point belongs to.
-             *
-             * @function Highcharts.Point#getZone
-             *
-             * @return {Highcharts.SeriesZonesOptionsObject}
-             *         The zone item.
-             */
-            Point.prototype.getZone = function () {
-                var series = this.series,
-                    zones = series.zones,
-                    zoneAxis = series.zoneAxis || 'y',
-                    i = 0,
-                    zone;
-                zone = zones[i];
-                while (this[zoneAxis] >= zone.value) {
-                    zone = zones[++i];
-                }
-                // For resetting or reusing the point (#8100)
-                if (!this.nonZonedColor) {
-                    this.nonZonedColor = this.color;
-                }
-                if (zone && zone.color && !this.options.color) {
-                    this.color = zone.color;
-                }
-                else {
-                    this.color = this.nonZonedColor;
-                }
-                return zone;
-            };
-            /**
-             * Utility to check if point has new shape type. Used in column series and
-             * all others that are based on column series.
-             *
-             * @return boolean|undefined
-             */
-            Point.prototype.hasNewShapeType = function () {
-                var point = this;
-                var oldShapeType = point.graphic &&
-                        (point.graphic.symbolName || point.graphic.element.nodeName);
-                return oldShapeType !== this.shapeType;
-            };
-            /**
-             * Initialize the point. Called internally based on the `series.data`
-             * option.
-             *
-             * @function Highcharts.Point#init
-             *
-             * @param {Highcharts.Series} series
-             *        The series object containing this point.
-             *
-             * @param {Highcharts.PointOptionsType} options
-             *        The data in either number, array or object format.
-             *
-             * @param {number} [x]
-             *        Optionally, the X value of the point.
-             *
-             * @return {Highcharts.Point}
-             *         The Point instance.
-             *
-             * @fires Highcharts.Point#event:afterInit
-             */
-            Point.prototype.init = function (series, options, x) {
-                this.series = series;
-                this.applyOptions(options, x);
-                // Add a unique ID to the point if none is assigned
-                this.id = defined(this.id) ? this.id : uniqueKey();
-                this.resolveColor();
-                series.chart.pointCount++;
-                fireEvent(this, 'afterInit');
-                return this;
-            };
-            /**
-             * Transform number or array configs into objects. Also called for object
-             * configs. Used internally to unify the different configuration formats for
-             * points. For example, a simple number `10` in a line series will be
-             * transformed to `{ y: 10 }`, and an array config like `[1, 10]` in a
-             * scatter series will be transformed to `{ x: 1, y: 10 }`.
-             *
-             * @function Highcharts.Point#optionsToObject
-             *
-             * @param {Highcharts.PointOptionsType} options
-             *        The input option.
-             *
-             * @return {Highcharts.Dictionary<*>}
-             *         Transformed options.
-             */
-            Point.prototype.optionsToObject = function (options) {
-                var ret = {},
-                    series = this.series,
-                    keys = series.options.keys,
-                    pointArrayMap = keys || series.pointArrayMap || ['y'],
-                    valueCount = pointArrayMap.length,
-                    firstItemType,
-                    i = 0,
-                    j = 0;
-                if (isNumber(options) || options === null) {
-                    ret[pointArrayMap[0]] = options;
-                }
-                else if (isArray(options)) {
-                    // with leading x value
-                    if (!keys && options.length > valueCount) {
-                        firstItemType = typeof options[0];
-                        if (firstItemType === 'string') {
-                            ret.name = options[0];
-                        }
-                        else if (firstItemType === 'number') {
-                            ret.x = options[0];
-                        }
-                        i++;
-                    }
-                    while (j < valueCount) {
-                        // Skip undefined positions for keys
-                        if (!keys || typeof options[i] !== 'undefined') {
-                            if (pointArrayMap[j].indexOf('.') > 0) {
-                                // Handle nested keys, e.g. ['color.pattern.image']
-                                // Avoid function call unless necessary.
-                                Point.prototype.setNestedProperty(ret, options[i], pointArrayMap[j]);
-                            }
-                            else {
-                                ret[pointArrayMap[j]] = options[i];
-                            }
-                        }
-                        i++;
-                        j++;
-                    }
-                }
-                else if (typeof options === 'object') {
-                    ret = options;
-                    // This is the fastest way to detect if there are individual point
-                    // dataLabels that need to be considered in drawDataLabels. These
-                    // can only occur in object configs.
-                    if (options.dataLabels) {
-                        series._hasPointLabels = true;
-                    }
-                    // Same approach as above for markers
-                    if (options.marker) {
-                        series._hasPointMarkers = true;
-                    }
-                }
-                return ret;
-            };
-            /**
-             * @private
-             * @function Highcharts.Point#resolveColor
-             * @return {void}
-             */
-            Point.prototype.resolveColor = function () {
-                var series = this.series,
-                    colors,
-                    optionsChart = series.chart.options.chart,
-                    colorCount = optionsChart.colorCount,
-                    styledMode = series.chart.styledMode,
-                    colorIndex;
-                // remove points nonZonedColor for later recalculation
-                delete this.nonZonedColor;
-                /**
-                 * The point's current color.
-                 *
-                 * @name Highcharts.Point#color
-                 * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject|undefined}
-                 */
-                if (!styledMode && !this.options.color) {
-                    this.color = series.color; // #3445
-                }
-                if (series.options.colorByPoint) {
-                    if (!styledMode) {
-                        colors = series.options.colors || series.chart.options.colors;
-                        this.color = this.color || colors[series.colorCounter];
-                        colorCount = colors.length;
-                    }
-                    colorIndex = series.colorCounter;
-                    series.colorCounter++;
-                    // loop back to zero
-                    if (series.colorCounter === colorCount) {
-                        series.colorCounter = 0;
-                    }
-                }
-                else {
-                    colorIndex = series.colorIndex;
-                }
-                this.colorIndex = pick(this.colorIndex, colorIndex);
-            };
-            /**
-             * Set a value in an object, on the property defined by key. The key
-             * supports nested properties using dot notation. The function modifies the
-             * input object and does not make a copy.
-             *
-             * @function Highcharts.Point#setNestedProperty<T>
-             *
-             * @param {T} object
-             *        The object to set the value on.
-             *
-             * @param {*} value
-             *        The value to set.
-             *
-             * @param {string} key
-             *        Key to the property to set.
-             *
-             * @return {T}
-             *         The modified object.
-             */
-            Point.prototype.setNestedProperty = function (object, value, key) {
-                var nestedKeys = key.split('.');
-                nestedKeys.reduce(function (result, key, i, arr) {
-                    var isLastKey = arr.length - 1 === i;
-                    result[key] = (isLastKey ?
-                        value :
-                        isObject(result[key], true) ?
-                            result[key] :
-                            {});
-                    return result[key];
-                }, object);
-                return object;
-            };
-            /**
-             * Extendable method for formatting each point's tooltip line.
-             *
-             * @function Highcharts.Point#tooltipFormatter
-             *
-             * @param {string} pointFormat
-             *        The point format.
-             *
-             * @return {string}
-             *         A string to be concatenated in to the common tooltip text.
-             */
-            Point.prototype.tooltipFormatter = function (pointFormat) {
-                // Insert options for valueDecimals, valuePrefix, and valueSuffix
-                var series = this.series, seriesTooltipOptions = series.tooltipOptions, valueDecimals = pick(seriesTooltipOptions.valueDecimals, ''), valuePrefix = seriesTooltipOptions.valuePrefix || '', valueSuffix = seriesTooltipOptions.valueSuffix || '';
-                // Replace default point style with class name
-                if (series.chart.styledMode) {
-                    pointFormat =
-                        series.chart.tooltip.styledModeFormat(pointFormat);
-                }
-                // Loop over the point array map and replace unformatted values with
-                // sprintf formatting markup
-                (series.pointArrayMap || ['y']).forEach(function (key) {
-                    key = '{point.' + key; // without the closing bracket
-                    if (valuePrefix || valueSuffix) {
-                        pointFormat = pointFormat.replace(RegExp(key + '}', 'g'), valuePrefix + key + '}' + valueSuffix);
-                    }
-                    pointFormat = pointFormat.replace(RegExp(key + '}', 'g'), key + ':,.' + valueDecimals + 'f}');
-                });
-                return format(pointFormat, {
-                    point: this,
-                    series: this.series
-                }, series.chart);
-            };
-            return Point;
-        }());
-        H.Point = Point;
-
-        return Point;
-    });
-    _registerModule(_modules, 'Core/Series/Series.js', [_modules['Core/Globals.js'], _modules['Core/Series/Point.js'], _modules['Core/Utilities.js']], function (H, Point, U) {
-        /* *
-         *
-         *  (c) 2010-2020 Torstein Honsi
-         *
-         *  License: www.highcharts.com/license
-         *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
-         *
-         * */
-        var error = U.error,
-            extendClass = U.extendClass,
-            fireEvent = U.fireEvent,
-            getOptions = U.getOptions,
-            isObject = U.isObject,
-            merge = U.merge,
-            objectEach = U.objectEach;
-        /**
-         * @class
-         * @name Highcharts.Series
-         */
-        var BaseSeries = /** @class */ (function () {
-                /* *
-                 *
-                 *  Constructor
-                 *
-                 * */
-                function BaseSeries(chart, options) {
-                    var mergedOptions = merge(BaseSeries.defaultOptions, options);
-                this.chart = chart;
-                this._i = chart.series.length;
-                chart.series.push(this);
-                this.options = mergedOptions;
-                this.userOptions = merge(options);
-            }
-            /* *
-             *
-             *  Static Functions
-             *
-             * */
-            BaseSeries.addSeries = function (seriesName, seriesType) {
-                BaseSeries.seriesTypes[seriesName] = seriesType;
-            };
-            BaseSeries.cleanRecursively = function (toClean, reference) {
-                var clean = {};
-                objectEach(toClean, function (_val, key) {
-                    var ob;
-                    // Dive into objects (except DOM nodes)
-                    if (isObject(toClean[key], true) &&
-                        !toClean.nodeType && // #10044
-                        reference[key]) {
-                        ob = BaseSeries.cleanRecursively(toClean[key], reference[key]);
-                        if (Object.keys(ob).length) {
-                            clean[key] = ob;
-                        }
-                        // Arrays, primitives and DOM nodes are copied directly
-                    }
-                    else if (isObject(toClean[key]) ||
-                        toClean[key] !== reference[key]) {
-                        clean[key] = toClean[key];
-                    }
-                });
-                return clean;
-            };
-            // eslint-disable-next-line valid-jsdoc
-            /**
-             * Internal function to initialize an individual series.
-             * @private
-             */
-            BaseSeries.getSeries = function (chart, options) {
-                if (options === void 0) { options = {}; }
-                var optionsChart = chart.options.chart,
-                    type = (options.type ||
-                        optionsChart.type ||
-                        optionsChart.defaultSeriesType ||
-                        ''),
-                    Series = BaseSeries.seriesTypes[type];
-                // No such series type
-                if (!Series) {
-                    error(17, true, chart, { missingModuleFor: type });
-                }
-                return new Series(chart, options);
-            };
-            /**
-             * Factory to create new series prototypes.
-             *
-             * @function Highcharts.seriesType
-             *
-             * @param {string} type
-             * The series type name.
-             *
-             * @param {string} parent
-             * The parent series type name. Use `line` to inherit from the basic
-             * {@link Series} object.
-             *
-             * @param {Highcharts.SeriesOptionsType|Highcharts.Dictionary<*>} options
-             * The additional default options that are merged with the parent's options.
-             *
-             * @param {Highcharts.Dictionary<*>} [props]
-             * The properties (functions and primitives) to set on the new prototype.
-             *
-             * @param {Highcharts.Dictionary<*>} [pointProps]
-             * Members for a series-specific extension of the {@link Point} prototype if
-             * needed.
-             *
-             * @return {Highcharts.Series}
-             * The newly created prototype as extended from {@link Series} or its
-             * derivatives.
-             */
-            // docs: add to API + extending Highcharts
-            BaseSeries.seriesType = function (type, parent, options, seriesProto, pointProto) {
-                var defaultOptions = getOptions().plotOptions || {},
-                    seriesTypes = BaseSeries.seriesTypes;
-                parent = parent || '';
-                // Merge the options
-                defaultOptions[type] = merge(defaultOptions[parent], options);
-                // Create the class
-                BaseSeries.addSeries(type, extendClass(seriesTypes[parent] || function () { }, seriesProto));
-                seriesTypes[type].prototype.type = type;
-                // Create the point class if needed
-                if (pointProto) {
-                    seriesTypes[type].prototype.pointClass =
-                        extendClass(Point, pointProto);
-                }
-                return seriesTypes[type];
-            };
-            BaseSeries.prototype.update = function (newOptions, redraw) {
-                if (redraw === void 0) { redraw = true; }
-                var series = this;
-                newOptions = BaseSeries.cleanRecursively(newOptions, this.userOptions);
-                var newType = newOptions.type;
-                if (typeof newType !== 'undefined' &&
-                    newType !== series.type) {
-                    series = BaseSeries.getSeries(series.chart, newOptions);
-                }
-                fireEvent(series, 'update', { newOptions: newOptions });
-                series.userOptions = merge(newOptions);
-                fireEvent(series, 'afterUpdate', { newOptions: newOptions });
-                if (redraw) {
-                    series.chart.redraw();
-                }
-                return series;
-            };
-            /* *
-             *
-             *  Static Properties
-             *
-             * */
-            BaseSeries.defaultOptions = {
-                type: 'base'
-            };
-            BaseSeries.seriesTypes = {};
-            return BaseSeries;
-        }());
-        BaseSeries.prototype.pointClass = Point;
-        // backwards compatibility
-        H.seriesType = BaseSeries.seriesType;
-        H.seriesTypes = BaseSeries.seriesTypes;
-        /* *
-         *
-         *  Export
-         *
-         * */
-
-        return BaseSeries;
-    });
-    _registerModule(_modules, 'Core/Chart/Chart.js', [_modules['Core/Animation/AnimationUtilities.js'], _modules['Core/Axis/Axis.js'], _modules['Core/Series/Series.js'], _modules['Core/Globals.js'], _modules['Core/Legend.js'], _modules['Core/MSPointer.js'], _modules['Core/Options.js'], _modules['Core/Pointer.js'], _modules['Core/Time.js'], _modules['Core/Utilities.js']], function (A, Axis, BaseSeries, H, Legend, MSPointer, O, Pointer, Time, U) {
-        /* *
-         *
-         *  (c) 2010-2020 Torstein Honsi
-         *
-         *  License: www.highcharts.com/license
-         *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
-         *
-         * */
-        var animate = A.animate,
-            animObject = A.animObject,
-            setAnimation = A.setAnimation;
-        var charts = H.charts,
-            doc = H.doc,
-            win = H.win;
-        var defaultOptions = O.defaultOptions;
-        var addEvent = U.addEvent,
-            attr = U.attr,
-            createElement = U.createElement,
-            css = U.css,
-            defined = U.defined,
-            discardElement = U.discardElement,
-            erase = U.erase,
-            error = U.error,
-            extend = U.extend,
-            find = U.find,
-            fireEvent = U.fireEvent,
-            getStyle = U.getStyle,
-            isArray = U.isArray,
-            isFunction = U.isFunction,
-            isNumber = U.isNumber,
-            isObject = U.isObject,
-            isString = U.isString,
-            merge = U.merge,
-            numberFormat = U.numberFormat,
-            objectEach = U.objectEach,
-            pick = U.pick,
-            pInt = U.pInt,
-            relativeLength = U.relativeLength,
-            removeEvent = U.removeEvent,
-            splat = U.splat,
-            syncTimeout = U.syncTimeout,
-            uniqueKey = U.uniqueKey;
-        /**
-         * Callback for chart constructors.
-         *
-         * @callback Highcharts.ChartCallbackFunction
-         *
-         * @param {Highcharts.Chart} chart
-         *        Created chart.
-         */
-        /**
-         * Format a number and return a string based on input settings.
-         *
-         * @callback Highcharts.NumberFormatterCallbackFunction
-         *
-         * @param {number} number
-         *        The input number to format.
-         *
-         * @param {number} decimals
-         *        The amount of decimals. A value of -1 preserves the amount in the
-         *        input number.
-         *
-         * @param {string} [decimalPoint]
-         *        The decimal point, defaults to the one given in the lang options, or
-         *        a dot.
-         *
-         * @param {string} [thousandsSep]
-         *        The thousands separator, defaults to the one given in the lang
-         *        options, or a space character.
-         *
-         * @return {string} The formatted number.
-         */
-        /**
-         * The chart title. The title has an `update` method that allows modifying the
-         * options directly or indirectly via `chart.update`.
-         *
-         * @interface Highcharts.TitleObject
-         * @extends Highcharts.SVGElement
-         */ /**
-        * Modify options for the title.
-        *
-        * @function Highcharts.TitleObject#update
-        *
-        * @param {Highcharts.TitleOptions} titleOptions
-        *        Options to modify.
-        *
-        * @param {boolean} [redraw=true]
-        *        Whether to redraw the chart after the title is altered. If doing more
-        *        operations on the chart, it is a good idea to set redraw to false and
-        *        call {@link Chart#redraw} after.
-        */
-        /**
-         * The chart subtitle. The subtitle has an `update` method that
-         * allows modifying the options directly or indirectly via
-         * `chart.update`.
-         *
-         * @interface Highcharts.SubtitleObject
-         * @extends Highcharts.SVGElement
-         */ /**
-        * Modify options for the subtitle.
-        *
-        * @function Highcharts.SubtitleObject#update
-        *
-        * @param {Highcharts.SubtitleOptions} subtitleOptions
-        *        Options to modify.
-        *
-        * @param {boolean} [redraw=true]
-        *        Whether to redraw the chart after the subtitle is altered. If doing
-        *        more operations on the chart, it is a good idea to set redraw to false
-        *        and call {@link Chart#redraw} after.
-        */
-        /**
-         * The chart caption. The caption has an `update` method that
-         * allows modifying the options directly or indirectly via
-         * `chart.update`.
-         *
-         * @interface Highcharts.CaptionObject
-         * @extends Highcharts.SVGElement
-         */ /**
-        * Modify options for the caption.
-        *
-        * @function Highcharts.CaptionObject#update
-        *
-        * @param {Highcharts.CaptionOptions} captionOptions
-        *        Options to modify.
-        *
-        * @param {boolean} [redraw=true]
-        *        Whether to redraw the chart after the caption is altered. If doing
-        *        more operations on the chart, it is a good idea to set redraw to false
-        *        and call {@link Chart#redraw} after.
-        */
-        var marginNames = H.marginNames;
-        /* eslint-disable no-invalid-this, valid-jsdoc */
-        /**
-         * The Chart class. The recommended constructor is {@link Highcharts#chart}.
-         *
-         * @example
-         * var chart = Highcharts.chart('container', {
-         *        title: {
-         *               text: 'My chart'
-         *        },
-         *        series: [{
-         *            data: [1, 3, 2, 4]
-         *        }]
-         * })
-         *
-         * @class
-         * @name Highcharts.Chart
-         *
-         * @param {string|Highcharts.HTMLDOMElement} [renderTo]
-         *        The DOM element to render to, or its id.
-         *
-         * @param {Highcharts.Options} options
-         *        The chart options structure.
-         *
-         * @param {Highcharts.ChartCallbackFunction} [callback]
-         *        Function to run when the chart has loaded and and all external images
-         *        are loaded. Defining a
-         *        [chart.events.load](https://api.highcharts.com/highcharts/chart.events.load)
-         *        handler is equivalent.
-         */
-        var Chart = /** @class */ (function () {
-                function Chart(a, b, c) {
-                    this.axes = void 0;
-                this.axisOffset = void 0;
-                this.bounds = void 0;
-                this.chartHeight = void 0;
-                this.chartWidth = void 0;
-                this.clipBox = void 0;
-                this.colorCounter = void 0;
-                this.container = void 0;
-                this.index = void 0;
-                this.isResizing = void 0;
-                this.labelCollectors = void 0;
-                this.legend = void 0;
-                this.margin = void 0;
-                this.numberFormatter = void 0;
-                this.options = void 0;
-                this.plotBox = void 0;
-                this.plotHeight = void 0;
-                this.plotLeft = void 0;
-                this.plotTop = void 0;
-                this.plotWidth = void 0;
-                this.pointCount = void 0;
-                this.pointer = void 0;
-                this.renderer = void 0;
-                this.renderTo = void 0;
-                this.series = void 0;
-                this.spacing = void 0;
-                this.spacingBox = void 0;
-                this.symbolCounter = void 0;
-                this.time = void 0;
-                this.titleOffset = void 0;
-                this.userOptions = void 0;
-                this.xAxis = void 0;
-                this.yAxis = void 0;
-                this.getArgs(a, b, c);
-            }
-            /* *
-             *
-             *  Functions
-             *
-             * */
-            /**
-             * Handle the arguments passed to the constructor.
-             *
-             * @private
-             * @function Highcharts.Chart#getArgs
-             *
-             * @param {...Array<*>} arguments
-             * All arguments for the constructor.
-             *
-             * @fires Highcharts.Chart#event:init
-             * @fires Highcharts.Chart#event:afterInit
-             */
-            Chart.prototype.getArgs = function (a, b, c) {
-                // Remove the optional first argument, renderTo, and
-                // set it on this.
-                if (isString(a) || a.nodeName) {
-                    this.renderTo = a;
-                    this.init(b, c);
-                }
-                else {
-                    this.init(a, b);
-                }
-            };
-            /**
-             * Overridable function that initializes the chart. The constructor's
-             * arguments are passed on directly.
-             *
-             * @function Highcharts.Chart#init
-             *
-             * @param {Highcharts.Options} userOptions
-             *        Custom options.
-             *
-             * @param {Function} [callback]
-             *        Function to run when the chart has loaded and and all external
-             *        images are loaded.
-             *
-             * @return {void}
-             *
-             * @fires Highcharts.Chart#event:init
-             * @fires Highcharts.Chart#event:afterInit
-             */
-            Chart.prototype.init = function (userOptions, callback) {
-                // Handle regular options
-                var options, 
-                    // skip merging data points to increase performance
-                    seriesOptions = userOptions.series,
-                    userPlotOptions = userOptions.plotOptions || {};
-                // Fire the event with a default function
-                fireEvent(this, 'init', { args: arguments }, function () {
-                    userOptions.series = null;
-                    options = merge(defaultOptions, userOptions); // do the merge
-                    var optionsChart = options.chart || {};
-                    // Override (by copy of user options) or clear tooltip options
-                    // in chart.options.plotOptions (#6218)
-                    objectEach(options.plotOptions, function (typeOptions, type) {
-                        if (isObject(typeOptions)) { // #8766
-                            typeOptions.tooltip = (userPlotOptions[type] && // override by copy:
-                                merge(userPlotOptions[type].tooltip)) || void 0; // or clear
-                        }
-                    });
-                    // User options have higher priority than default options
-                    // (#6218). In case of exporting: path is changed
-                    options.tooltip.userOptions = (userOptions.chart &&
-                        userOptions.chart.forExport &&
-                        userOptions.tooltip.userOptions) || userOptions.tooltip;
-                    // set back the series data
-                    options.series = userOptions.series = seriesOptions;
-                    /**
-                     * The original options given to the constructor or a chart factory
-                     * like {@link Highcharts.chart} and {@link Highcharts.stockChart}.
-                     *
-                     * @name Highcharts.Chart#userOptions
-                     * @type {Highcharts.Options}
-                     */
-                    this.userOptions = userOptions;
-                    var chartEvents = optionsChart.events;
-                    this.margin = [];
-                    this.spacing = [];
-                    // Pixel data bounds for touch zoom
-                    this.bounds = { h: {}, v: {} };
-                    // An array of functions that returns labels that should be
-                    // considered for anti-collision
-                    this.labelCollectors = [];
-                    this.callback = callback;
-                    this.isResizing = 0;
-                    /**
-                     * The options structure for the chart after merging
-                     * {@link #defaultOptions} and {@link #userOptions}. It contains
-                     * members for the sub elements like series, legend, tooltip etc.
-                     *
-                     * @name Highcharts.Chart#options
-                     * @type {Highcharts.Options}
-                     */
-                    this.options = options;
-                    /**
-                     * All the axes in the chart.
-                     *
-                     * @see  Highcharts.Chart.xAxis
-                     * @see  Highcharts.Chart.yAxis
-                     *
-                     * @name Highcharts.Chart#axes
-                     * @type {Array<Highcharts.Axis>}
-                     */
-                    this.axes = [];
-                    /**
-                     * All the current series in the chart.
-                     *
-                     * @name Highcharts.Chart#series
-                     * @type {Array<Highcharts.Series>}
-                     */
-                    this.series = [];
-                    /**
-                     * The `Time` object associated with the chart. Since v6.0.5,
-                     * time settings can be applied individually for each chart. If
-                     * no individual settings apply, the `Time` object is shared by
-                     * all instances.
-                     *
-                     * @name Highcharts.Chart#time
-                     * @type {Highcharts.Time}
-                     */
-                    this.time =
-                        userOptions.time && Object.keys(userOptions.time).length ?
-                            new Time(userOptions.time) :
-                            H.time;
-                    /**
-                     * Callback function to override the default function that formats
-                     * all the numbers in the chart. Returns a string with the formatted
-                     * number.
-                     *
-                     * @name Highcharts.Chart#numberFormatter
-                     * @type {Highcharts.NumberFormatterCallbackFunction}
-                     */
-                    this.numberFormatter = optionsChart.numberFormatter || numberFormat;
-                    /**
-                     * Whether the chart is in styled mode, meaning all presentatinoal
-                     * attributes are avoided.
-                     *
-                     * @name Highcharts.Chart#styledMode
-                     * @type {boolean}
-                     */
-                    this.styledMode = optionsChart.styledMode;
-                    this.hasCartesianSeries = optionsChart.showAxes;
-                    var chart = this;
-                    /**
-                     * Index position of the chart in the {@link Highcharts#charts}
-                     * property.
-                     *
-                     * @name Highcharts.Chart#index
-                     * @type {number}
-                     * @readonly
-                     */
-                    chart.index = charts.length; // Add the chart to the global lookup
-                    charts.push(chart);
-                    H.chartCount++;
-                    // Chart event handlers
-                    if (chartEvents) {
-                        objectEach(chartEvents, function (event, eventType) {
-                            if (isFunction(event)) {
-                                addEvent(chart, eventType, event);
-                            }
-                        });
-                    }
-                    /**
-                     * A collection of the X axes in the chart.
-                     *
-                     * @name Highcharts.Chart#xAxis
-                     * @type {Array<Highcharts.Axis>}
-                     */
-                    chart.xAxis = [];
-                    /**
-                     * A collection of the Y axes in the chart.
-                     *
-                     * @name Highcharts.Chart#yAxis
-                     * @type {Array<Highcharts.Axis>}
-                     *
-                     * @todo
-                     * Make events official: Fire the event `afterInit`.
-                     */
-                    chart.yAxis = [];
-                    chart.pointCount = chart.colorCounter = chart.symbolCounter = 0;
-                    // Fire after init but before first render, before axes and series
-                    // have been initialized.
-                    fireEvent(chart, 'afterInit');
-                    chart.firstRender();
-                });
-            };
-            /**
-             * Internal function to unitialize an individual series.
-             *
-             * @private
-             * @function Highcharts.Chart#initSeries
-             */
-            Chart.prototype.initSeries = function (options) {
-                var chart = this,
-                    optionsChart = chart.options.chart,
-                    type = (options.type ||
-                        optionsChart.type ||
-                        optionsChart.defaultSeriesType),
-                    series,
-                    Constr = BaseSeries.seriesTypes[type];
-                // No such series type
-                if (!Constr) {
-                    error(17, true, chart, { missingModuleFor: type });
-                }
-                series = new Constr(chart, options);
-                if (typeof series.init === 'function') {
-                    series.init(this, options);
-                }
-                return series;
-            };
-            /**
-             * Internal function to set data for all series with enabled sorting.
-             *
-             * @private
-             * @function Highcharts.Chart#setSeriesData
-             */
-            Chart.prototype.setSeriesData = function () {
-                this.getSeriesOrderByLinks().forEach(function (series) {
-                    // We need to set data for series with sorting after series init
-                    if (!series.points && !series.data && series.enabledDataSorting) {
-                        series.setData(series.options.data, false);
-                    }
-                });
-            };
-            /**
-             * Sort and return chart series in order depending on the number of linked
-             * series.
-             *
-             * @private
-             * @function Highcharts.Series#getSeriesOrderByLinks
-             * @return {Array<Highcharts.Series>}
-             */
-            Chart.prototype.getSeriesOrderByLinks = function () {
-                return this.series.concat().sort(function (a, b) {
-                    if (a.linkedSeries.length || b.linkedSeries.length) {
-                        return b.linkedSeries.length - a.linkedSeries.length;
-                    }
-                    return 0;
-                });
-            };
-            /**
-             * Order all series above a given index. When series are added and ordered
-             * by configuration, only the last series is handled (#248, #1123, #2456,
-             * #6112). This function is called on series initialization and destroy.
-             *
-             * @private
-             * @function Highcharts.Series#orderSeries
-             * @param {number} [fromIndex]
-             * If this is given, only the series above this index are handled.
-             */
-            Chart.prototype.orderSeries = function (fromIndex) {
-                var series = this.series,
-                    i = fromIndex || 0;
-                for (; i < series.length; i++) {
-                    if (series[i]) {
-                        /**
-                         * Contains the series' index in the `Chart.series` array.
-                         *
-                         * @name Highcharts.Series#index
-                         * @type {number}
-                         * @readonly
-                         */
-                        series[i].index = i;
-                        series[i].name = series[i].getName();
-                    }
-                }
-            };
-            /**
-             * Check whether a given point is within the plot area.
-             *
-             * @function Highcharts.Chart#isInsidePlot
-             *
-             * @param {number} plotX
-             * Pixel x relative to the plot area.
-             *
-             * @param {number} plotY
-             * Pixel y relative to the plot area.
-             *
-             * @param {boolean} [inverted]
-             * Whether the chart is inverted.
-             *
-             * @return {boolean}
-             * Returns true if the given point is inside the plot area.
-             */
-            Chart.prototype.isInsidePlot = function (plotX, plotY, inverted) {
-                var x = inverted ? plotY : plotX,
-                    y = inverted ? plotX : plotY,
-                    e = {
-                        x: x,
-                        y: y,
-                        isInsidePlot: x >= 0 &&
-                            x <= this.plotWidth &&
-                            y >= 0 &&
-                            y <= this.plotHeight
-                    };
-                fireEvent(this, 'afterIsInsidePlot', e);
-                return e.isInsidePlot;
-            };
-            /**
-             * Redraw the chart after changes have been done to the data, axis extremes
-             * chart size or chart elements. All methods for updating axes, series or
-             * points have a parameter for redrawing the chart. This is `true` by
-             * default. But in many cases you want to do more than one operation on the
-             * chart before redrawing, for example add a number of points. In those
-             * cases it is a waste of resources to redraw the chart for each new point
-             * added. So you add the points and call `chart.redraw()` after.
-             *
-             * @function Highcharts.Chart#redraw
-             *
-             * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation]
-             * If or how to apply animation to the redraw.
-             *
-             * @fires Highcharts.Chart#event:afterSetExtremes
-             * @fires Highcharts.Chart#event:beforeRedraw
-             * @fires Highcharts.Chart#event:predraw
-             * @fires Highcharts.Chart#event:redraw
-             * @fires Highcharts.Chart#event:render
-             * @fires Highcharts.Chart#event:updatedData
-             */
-            Chart.prototype.redraw = function (animation) {
-                fireEvent(this, 'beforeRedraw');
-                var chart = this,
-                    axes = chart.axes,
-                    series = chart.series,
-                    pointer = chart.pointer,
-                    legend = chart.legend,
-                    legendUserOptions = chart.userOptions.legend,
-                    redrawLegend = chart.isDirtyLegend,
-                    hasStackedSeries,
-                    hasDirtyStacks,
-                    hasCartesianSeries = chart.hasCartesianSeries,
-                    isDirtyBox = chart.isDirtyBox,
-                    i,
-                    serie,
-                    renderer = chart.renderer,
-                    isHiddenChart = renderer.isHidden(),
-                    afterRedraw = [];
-                // Handle responsive rules, not only on resize (#6130)
-                if (chart.setResponsive) {
-                    chart.setResponsive(false);
-                }
-                // Set the global animation. When chart.hasRendered is not true, the
-                // redraw call comes from a responsive rule and animation should not
-                // occur.
-                setAnimation(chart.hasRendered ? animation : false, chart);
-                if (isHiddenChart) {
-                    chart.temporaryDisplay();
-                }
-                // Adjust title layout (reflow multiline text)
-                chart.layOutTitles();
-                // link stacked series
-                i = series.length;
-                while (i--) {
-                    serie = series[i];
-                    if (serie.options.stacking) {
-                        hasStackedSeries = true;
-                        if (serie.isDirty) {
-                            hasDirtyStacks = true;
-                            break;
-                        }
-                    }
-                }
-                if (hasDirtyStacks) { // mark others as dirty
-                    i = series.length;
-                    while (i--) {
-                        serie = series[i];
-                        if (serie.options.stacking) {
-                            serie.isDirty = true;
-                        }
-                    }
-                }
-                // Handle updated data in the series
-                series.forEach(function (serie) {
-                    if (serie.isDirty) {
-                        if (serie.options.legendType === 'point') {
-                            if (typeof serie.updateTotals === 'function') {
-                                serie.updateTotals();
-                            }
-                            redrawLegend = true;
-                        }
-                        else if (legendUserOptions &&
-                            (legendUserOptions.labelFormatter ||
-                                legendUserOptions.labelFormat)) {
-                            redrawLegend = true; // #2165
-                        }
-                    }
-                    if (serie.isDirtyData) {
-                        fireEvent(serie, 'updatedData');
-                    }
-                });
-                // handle added or removed series
-                if (redrawLegend && legend && legend.options.enabled) {
-                    // draw legend graphics
-                    legend.render();
-                    chart.isDirtyLegend = false;
-                }
-                // reset stacks
-                if (hasStackedSeries) {
-                    chart.getStacks();
-                }
-                if (hasCartesianSeries) {
-                    // set axes scales
-                    axes.forEach(function (axis) {
-                        // Don't do setScale again if we're only resizing. Regression
-                        // #13507. But we need it after chart.update (responsive), as
-                        // axis is initialized again (#12137).
-                        if (!chart.isResizing || !isNumber(axis.min)) {
-                            axis.updateNames();
-                            axis.setScale();
-                        }
-                    });
-                }
-                chart.getMargins(); // #3098
-                if (hasCartesianSeries) {
-                    // If one axis is dirty, all axes must be redrawn (#792, #2169)
-                    axes.forEach(function (axis) {
-                        if (axis.isDirty) {
-                            isDirtyBox = true;
-                        }
-                    });
-                    // redraw axes
-                    axes.forEach(function (axis) {
-                        // Fire 'afterSetExtremes' only if extremes are set
-                        var key = axis.min + ',' + axis.max;
-                        if (axis.extKey !== key) { // #821, #4452
-                            axis.extKey = key;
-                            // prevent a recursive call to chart.redraw() (#1119)
-                            afterRedraw.push(function () {
-                                fireEvent(axis, 'afterSetExtremes', extend(axis.eventArgs, axis.getExtremes())); // #747, #751
-                                delete axis.eventArgs;
-                            });
-                        }
-                        if (isDirtyBox || hasStackedSeries) {
-                            axis.redraw();
-                        }
-                    });
-                }
-                // the plot areas size has changed
-                if (isDirtyBox) {
-                    chart.drawChartBox();
-                }
-                // Fire an event before redrawing series, used by the boost module to
-                // clear previous series renderings.
-                fireEvent(chart, 'predraw');
-                // redraw affected series
-                series.forEach(function (serie) {
-                    if ((isDirtyBox || serie.isDirty) && serie.visible) {
-                        serie.redraw();
-                    }
-                    // Set it here, otherwise we will have unlimited 'updatedData' calls
-                    // for a hidden series after setData(). Fixes #6012
-                    serie.isDirtyData = false;
-                });
-                // move tooltip or reset
-                if (pointer) {
-                    pointer.reset(true);
-                }
-                // redraw if canvas
-                renderer.draw();
-                // Fire the events
-                fireEvent(chart, 'redraw');
-                fireEvent(chart, 'render');
-                if (isHiddenChart) {
-                    chart.temporaryDisplay(true);
-                }
-                // Fire callbacks that are put on hold until after the redraw
-                afterRedraw.forEach(function (callback) {
-                    callback.call();
-                });
-            };
-            /**
-             * Get an axis, series or point object by `id` as given in the configuration
-             * options. Returns `undefined` if no item is found.
-             *
-             * @sample highcharts/plotoptions/series-id/
-             *         Get series by id
-             *
-             * @function Highcharts.Chart#get
-             *
-             * @param {string} id
-             * The id as given in the configuration options.
-             *
-             * @return {Highcharts.Axis|Highcharts.Series|Highcharts.Point|undefined}
-             * The retrieved item.
-             */
-            Chart.prototype.get = function (id) {
-                var ret,
-                    series = this.series,
-                    i;
-                /**
-                 * @private
-                 * @param {Highcharts.Axis|Highcharts.Series} item
-                 * @return {boolean}
-                 */
-                function itemById(item) {
-                    return (item.id === id ||
-                        (item.options && item.options.id === id));
-                }
-                ret =
-                    // Search axes
-                    find(this.axes, itemById) ||
-                        // Search series
-                        find(this.series, itemById);
-                // Search points
-                for (i = 0; !ret && i < series.length; i++) {
-                    ret = find(series[i].points || [], itemById);
-                }
-                return ret;
-            };
-            /**
-             * Create the Axis instances based on the config options.
-             *
-             * @private
-             * @function Highcharts.Chart#getAxes
-             * @fires Highcharts.Chart#event:afterGetAxes
-             * @fires Highcharts.Chart#event:getAxes
-             */
-            Chart.prototype.getAxes = function () {
-                var chart = this,
-                    options = this.options,
-                    xAxisOptions = options.xAxis = splat(options.xAxis || {}),
-                    yAxisOptions = options.yAxis = splat(options.yAxis || {}),
-                    optionsArray;
-                fireEvent(this, 'getAxes');
-                // make sure the options are arrays and add some members
-                xAxisOptions.forEach(function (axis, i) {
-                    axis.index = i;
-                    axis.isX = true;
-                });
-                yAxisOptions.forEach(function (axis, i) {
-                    axis.index = i;
-                });
-                // concatenate all axis options into one array
-                optionsArray = xAxisOptions.concat(yAxisOptions);
-                optionsArray.forEach(function (axisOptions) {
-                    new Axis(chart, axisOptions); // eslint-disable-line no-new
-                });
-                fireEvent(this, 'afterGetAxes');
-            };
-            /**
-             * Returns an array of all currently selected points in the chart. Points
-             * can be selected by clicking or programmatically by the
-             * {@link Highcharts.Point#select}
-             * function.
-             *
-             * @sample highcharts/plotoptions/series-allowpointselect-line/
-             *         Get selected points
-             *
-             * @function Highcharts.Chart#getSelectedPoints
-             *
-             * @return {Array<Highcharts.Point>}
-             *         The currently selected points.
-             */
-            Chart.prototype.getSelectedPoints = function () {
-                var points = [];
-                this.series.forEach(function (serie) {
-                    // For one-to-one points inspect series.data in order to retrieve
-                    // points outside the visible range (#6445). For grouped data,
-                    // inspect the generated series.points.
-                    points = points.concat(serie.getPointsCollection().filter(function (point) {
-                        return pick(point.selectedStaging, point.selected);
-                    }));
-                });
-                return points;
-            };
-            /**
-             * Returns an array of all currently selected series in the chart. Series
-             * can be selected either programmatically by the
-             * {@link Highcharts.Series#select}
-             * function or by checking the checkbox next to the legend item if
-             * [series.showCheckBox](https://api.highcharts.com/highcharts/plotOptions.series.showCheckbox)
-             * is true.
-             *
-             * @sample highcharts/members/chart-getselectedseries/
-             *         Get selected series
-             *
-             * @function Highcharts.Chart#getSelectedSeries
-             *
-             * @return {Array<Highcharts.Series>}
-             *         The currently selected series.
-             */
-            Chart.prototype.getSelectedSeries = function () {
-                return this.series.filter(function (serie) {
-                    return serie.selected;
-                });
-            };
-            /**
-             * Set a new title or subtitle for the chart.
-             *
-             * @sample highcharts/members/chart-settitle/
-             *         Set title text and styles
-             *
-             * @function Highcharts.Chart#setTitle
-             *
-             * @param {Highcharts.TitleOptions} [titleOptions]
-             *        New title options. The title text itself is set by the
-             *        `titleOptions.text` property.
-             *
-             * @param {Highcharts.SubtitleOptions} [subtitleOptions]
-             *        New subtitle options. The subtitle text itself is set by the
-             *        `subtitleOptions.text` property.
-             *
-             * @param {boolean} [redraw]
-             *        Whether to redraw the chart or wait for a later call to
-             *        `chart.redraw()`.
-             */
-            Chart.prototype.setTitle = function (titleOptions, subtitleOptions, redraw) {
-                this.applyDescription('title', titleOptions);
-                this.applyDescription('subtitle', subtitleOptions);
-                // The initial call also adds the caption. On update, chart.update will
-                // relay to Chart.setCaption.
-                this.applyDescription('caption', void 0);
-                this.layOutTitles(redraw);
-            };
-            /**
-             * Apply a title, subtitle or caption for the chart
-             *
-             * @private
-             * @function Highcharts.Chart#applyDescription
-             * @param name {string}
-             * Either title, subtitle or caption
-             * @param {Highcharts.TitleOptions|Highcharts.SubtitleOptions|Highcharts.CaptionOptions|undefined} explicitOptions
-             * The options to set, will be merged with default options.
-             */
-            Chart.prototype.applyDescription = function (name, explicitOptions) {
-                var chart = this;
-                // Default style
-                var style = name === 'title' ? {
-                        color: '#333333',
-                        fontSize: this.options.isStock ? '16px' : '18px' // #2944
-                    } : {
-                        color: '#666666'
-                    };
-                // Merge default options with explicit options
-                var options = this.options[name] = merge(
-                    // Default styles
-                    (!this.styledMode && { style: style }),
-                    this.options[name],
-                    explicitOptions);
-                var elem = this[name];
-                if (elem && explicitOptions) {
-                    this[name] = elem = elem.destroy(); // remove old
-                }
-                if (options && !elem) {
-                    elem = this.renderer.text(options.text, 0, 0, options.useHTML)
-                        .attr({
-                        align: options.align,
-                        'class': 'highcharts-' + name,
-                        zIndex: options.zIndex || 4
-                    })
-                        .add();
-                    // Update methods, shortcut to Chart.setTitle, Chart.setSubtitle and
-                    // Chart.setCaption
-                    elem.update = function (updateOptions) {
-                        var fn = {
-                                title: 'setTitle',
-                                subtitle: 'setSubtitle',
-                                caption: 'setCaption'
-                            }[name];
-                        chart[fn](updateOptions);
-                    };
-                    // Presentational
-                    if (!this.styledMode) {
-                        elem.css(options.style);
-                    }
-                    /**
-                     * The chart title. The title has an `update` method that allows
-                     * modifying the options directly or indirectly via
-                     * `chart.update`.
-                     *
-                     * @sample highcharts/members/title-update/
-                     *         Updating titles
-                     *
-                     * @name Highcharts.Chart#title
-                     * @type {Highcharts.TitleObject}
-                     */
-                    /**
-                     * The chart subtitle. The subtitle has an `update` method that
-                     * allows modifying the options directly or indirectly via
-                     * `chart.update`.
-                     *
-                     * @name Highcharts.Chart#subtitle
-                     * @type {Highcharts.SubtitleObject}
-                     */
-                    this[name] = elem;
-                }
-            };
-            /**
-             * Internal function to lay out the chart title, subtitle and caption, and
-             * cache the full offset height for use in `getMargins`. The result is
-             * stored in `this.titleOffset`.
-             *
-             * @private
-             * @function Highcharts.Chart#layOutTitles
-             *
-             * @param {boolean} [redraw=true]
-             * @fires Highcharts.Chart#event:afterLayOutTitles
-             */
-            Chart.prototype.layOutTitles = function (redraw) {
-                var titleOffset = [0, 0, 0],
-                    requiresDirtyBox,
-                    renderer = this.renderer,
-                    spacingBox = this.spacingBox;
-                // Lay out the title and the subtitle respectively
-                ['title', 'subtitle', 'caption'].forEach(function (key) {
-                    var title = this[key], titleOptions = this.options[key], verticalAlign = titleOptions.verticalAlign || 'top', offset = key === 'title' ? -3 :
-                            // Floating subtitle (#6574)
-                            verticalAlign === 'top' ? titleOffset[0] + 2 : 0, titleSize, height;
-                    if (title) {
-                        if (!this.styledMode) {
-                            titleSize = titleOptions.style.fontSize;
-                        }
-                        titleSize = renderer.fontMetrics(titleSize, title).b;
-                        title
-                            .css({
-                            width: (titleOptions.width ||
-                                spacingBox.width + (titleOptions.widthAdjust || 0)) + 'px'
-                        });
-                        // Skip the cache for HTML (#3481, #11666)
-                        height = Math.round(title.getBBox(titleOptions.useHTML).height);
-                        title.align(extend({
-                            y: verticalAlign === 'bottom' ?
-                                titleSize :
-                                offset + titleSize,
-                            height: height
-                        }, titleOptions), false, 'spacingBox');
-                        if (!titleOptions.floating) {
-                            if (verticalAlign === 'top') {
-                                titleOffset[0] = Math.ceil(titleOffset[0] +
-                                    height);
-                            }
-                            else if (verticalAlign === 'bottom') {
-                                titleOffset[2] = Math.ceil(titleOffset[2] +
-                                    height);
-                            }
-                        }
-                    }
-                }, this);
-                // Handle title.margin and caption.margin
-                if (titleOffset[0] &&
-                    (this.options.title.verticalAlign || 'top') === 'top') {
-                    titleOffset[0] += this.options.title.margin;
-                }
-                if (titleOffset[2] &&
-                    this.options.caption.verticalAlign === 'bottom') {
-                    titleOffset[2] += this.options.caption.margin;
-                }
-                requiresDirtyBox = (!this.titleOffset ||
-                    this.titleOffset.join(',') !== titleOffset.join(','));
-                // Used in getMargins
-                this.titleOffset = titleOffset;
-                fireEvent(this, 'afterLayOutTitles');
-                if (!this.isDirtyBox && requiresDirtyBox) {
-                    this.isDirtyBox = this.isDirtyLegend = requiresDirtyBox;
-                    // Redraw if necessary (#2719, #2744)
-                    if (this.hasRendered && pick(redraw, true) && this.isDirtyBox) {
-                        this.redraw();
-                    }
-                }
-            };
-            /**
-             * Internal function to get the chart width and height according to options
-             * and container size. Sets {@link Chart.chartWidth} and
-             * {@link Chart.chartHeight}.
-             *
-             * @private
-             * @function Highcharts.Chart#getChartSize
-             */
-            Chart.prototype.getChartSize = function () {
-                var chart = this,
-                    optionsChart = chart.options.chart,
-                    widthOption = optionsChart.width,
-                    heightOption = optionsChart.height,
-                    renderTo = chart.renderTo;
-                // Get inner width and height
-                if (!defined(widthOption)) {
-                    chart.containerWidth = getStyle(renderTo, 'width');
-                }
-                if (!defined(heightOption)) {
-                    chart.containerHeight = getStyle(renderTo, 'height');
-                }
-                /**
-                 * The current pixel width of the chart.
-                 *
-                 * @name Highcharts.Chart#chartWidth
-                 * @type {number}
-                 */
-                chart.chartWidth = Math.max(// #1393
-                0, widthOption || chart.containerWidth || 600 // #1460
-                );
-                /**
-                 * The current pixel height of the chart.
-                 *
-                 * @name Highcharts.Chart#chartHeight
-                 * @type {number}
-                 */
-                chart.chartHeight = Math.max(0, relativeLength(heightOption, chart.chartWidth) ||
-                    (chart.containerHeight > 1 ?
-                        chart.containerHeight :
-                        400));
-            };
-            /**
-             * If the renderTo element has no offsetWidth, most likely one or more of
-             * its parents are hidden. Loop up the DOM tree to temporarily display the
-             * parents, then save the original display properties, and when the true
-             * size is retrieved, reset them. Used on first render and on redraws.
-             *
-             * @private
-             * @function Highcharts.Chart#temporaryDisplay
-             *
-             * @param {boolean} [revert]
-             * Revert to the saved original styles.
-             */
-            Chart.prototype.temporaryDisplay = function (revert) {
-                var node = this.renderTo,
-                    tempStyle;
-                if (!revert) {
-                    while (node && node.style) {
-                        // When rendering to a detached node, it needs to be temporarily
-                        // attached in order to read styling and bounding boxes (#5783,
-                        // #7024).
-                        if (!doc.body.contains(node) && !node.parentNode) {
-                            node.hcOrigDetached = true;
-                            doc.body.appendChild(node);
-                        }
-                        if (getStyle(node, 'display', false) === 'none' ||
-                            node.hcOricDetached) {
-                            node.hcOrigStyle = {
-                                display: node.style.display,
-                                height: node.style.height,
-                                overflow: node.style.overflow
-                            };
-                            tempStyle = {
-                                display: 'block',
-                                overflow: 'hidden'
-                            };
-                            if (node !== this.renderTo) {
-                                tempStyle.height = 0;
-                            }
-                            css(node, tempStyle);
-                            // If it still doesn't have an offset width after setting
-                            // display to block, it probably has an !important priority
-                            // #2631, 6803
-                            if (!node.offsetWidth) {
-                                node.style.setProperty('display', 'block', 'important');
-                            }
-                        }
-                        node = node.parentNode;
-                        if (node === doc.body) {
-                            break;
-                        }
-                    }
-                }
-                else {
-                    while (node && node.style) {
-                        if (node.hcOrigStyle) {
-                            css(node, node.hcOrigStyle);
-                            delete node.hcOrigStyle;
-                        }
-                        if (node.hcOrigDetached) {
-                            doc.body.removeChild(node);
-                            node.hcOrigDetached = false;
-                        }
-                        node = node.parentNode;
-                    }
-                }
-            };
-            /**
-             * Set the {@link Chart.container|chart container's} class name, in
-             * addition to `highcharts-container`.
-             *
-             * @function Highcharts.Chart#setClassName
-             *
-             * @param {string} [className]
-             * The additional class name.
-             */
-            Chart.prototype.setClassName = function (className) {
-                this.container.className = 'highcharts-container ' + (className || '');
-            };
-            /**
-             * Get the containing element, determine the size and create the inner
-             * container div to hold the chart.
-             *
-             * @private
-             * @function Highcharts.Chart#afterGetContainer
-             * @fires Highcharts.Chart#event:afterGetContainer
-             */
-            Chart.prototype.getContainer = function () {
-                var chart = this,
-                    container,
-                    options = chart.options,
-                    optionsChart = options.chart,
-                    chartWidth,
-                    chartHeight,
-                    renderTo = chart.renderTo,
-                    indexAttrName = 'data-highcharts-chart',
-                    oldChartIndex,
-                    Ren,
-                    containerId = uniqueKey(),
-                    containerStyle,
-                    key;
-                if (!renderTo) {
-                    chart.renderTo = renderTo =
-                        optionsChart.renderTo;
-                }
-                if (isString(renderTo)) {
-                    chart.renderTo = renderTo =
-                        doc.getElementById(renderTo);
-                }
-                // Display an error if the renderTo is wrong
-                if (!renderTo) {
-                    error(13, true, chart);
-                }
-                // If the container already holds a chart, destroy it. The check for
-                // hasRendered is there because web pages that are saved to disk from
-                // the browser, will preserve the data-highcharts-chart attribute and
-                // the SVG contents, but not an interactive chart. So in this case,
-                // charts[oldChartIndex] will point to the wrong chart if any (#2609).
-                oldChartIndex = pInt(attr(renderTo, indexAttrName));
-                if (isNumber(oldChartIndex) &&
-                    charts[oldChartIndex] &&
-                    charts[oldChartIndex].hasRendered) {
-                    charts[oldChartIndex].destroy();
-                }
-                // Make a reference to the chart from the div
-                attr(renderTo, indexAttrName, chart.index);
-                // remove previous chart
-                renderTo.innerHTML = '';
-                // If the container doesn't have an offsetWidth, it has or is a child of
-                // a node that has display:none. We need to temporarily move it out to a
-                // visible state to determine the size, else the legend and tooltips
-                // won't render properly. The skipClone option is used in sparklines as
-                // a micro optimization, saving about 1-2 ms each chart.
-                if (!optionsChart.skipClone && !renderTo.offsetWidth) {
-                    chart.temporaryDisplay();
-                }
-                // get the width and height
-                chart.getChartSize();
-                chartWidth = chart.chartWidth;
-                chartHeight = chart.chartHeight;
-                // Allow table cells and flex-boxes to shrink without the chart blocking
-                // them out (#6427)
-                css(renderTo, { overflow: 'hidden' });
-                // Create the inner container
-                if (!chart.styledMode) {
-                    containerStyle = extend({
-                        position: 'relative',
-                        // needed for context menu (avoidscrollbars) and content
-                        // overflow in IE
-                        overflow: 'hidden',
-                        width: chartWidth + 'px',
-                        height: chartHeight + 'px',
-                        textAlign: 'left',
-                        lineHeight: 'normal',
-                        zIndex: 0,
-                        '-webkit-tap-highlight-color': 'rgba(0,0,0,0)',
-                        userSelect: 'none' // #13503
-                    }, optionsChart.style);
-                }
-                /**
-                 * The containing HTML element of the chart. The container is
-                 * dynamically inserted into the element given as the `renderTo`
-                 * parameter in the {@link Highcharts#chart} constructor.
-                 *
-                 * @name Highcharts.Chart#container
-                 * @type {Highcharts.HTMLDOMElement}
-                 */
-                container = createElement('div', {
-                    id: containerId
-                }, containerStyle, renderTo);
-                chart.container = container;
-                // cache the cursor (#1650)
-                chart._cursor = container.style.cursor;
-                // Initialize the renderer
-                Ren = H[optionsChart.renderer] || H.Renderer;
-                /**
-                 * The renderer instance of the chart. Each chart instance has only one
-                 * associated renderer.
-                 *
-                 * @name Highcharts.Chart#renderer
-                 * @type {Highcharts.SVGRenderer}
-                 */
-                chart.renderer = new Ren(container, chartWidth, chartHeight, null, optionsChart.forExport, options.exporting && options.exporting.allowHTML, chart.styledMode);
-                // Set the initial animation from the options
-                setAnimation(void 0, chart);
-                chart.setClassName(optionsChart.className);
-                if (!chart.styledMode) {
-                    chart.renderer.setStyle(optionsChart.style);
-                }
-                else {
-                    // Initialize definitions
-                    for (key in options.defs) { // eslint-disable-line guard-for-in
-                        this.renderer.definition(options.defs[key]);
-                    }
-                }
-                // Add a reference to the charts index
-                chart.renderer.chartIndex = chart.index;
-                fireEvent(this, 'afterGetContainer');
-            };
-            /**
-             * Calculate margins by rendering axis labels in a preliminary position.
-             * Title, subtitle and legend have already been rendered at this stage, but
-             * will be moved into their final positions.
-             *
-             * @private
-             * @function Highcharts.Chart#getMargins
-             * @fires Highcharts.Chart#event:getMargins
-             */
-            Chart.prototype.getMargins = function (skipAxes) {
-                var _a = this,
-                    spacing = _a.spacing,
-                    margin = _a.margin,
-                    titleOffset = _a.titleOffset;
-                this.resetMargins();
-                // Adjust for title and subtitle
-                if (titleOffset[0] && !defined(margin[0])) {
-                    this.plotTop = Math.max(this.plotTop, titleOffset[0] + spacing[0]);
-                }
-                if (titleOffset[2] && !defined(margin[2])) {
-                    this.marginBottom = Math.max(this.marginBottom, titleOffset[2] + spacing[2]);
-                }
-                // Adjust for legend
-                if (this.legend && this.legend.display) {
-                    this.legend.adjustMargins(margin, spacing);
-                }
-                fireEvent(this, 'getMargins');
-                if (!skipAxes) {
-                    this.getAxisMargins();
-                }
-            };
-            /**
-             * @private
-             * @function Highcharts.Chart#getAxisMargins
-             */
-            Chart.prototype.getAxisMargins = function () {
-                var chart = this, 
-                    // [top, right, bottom, left]
-                    axisOffset = chart.axisOffset = [0, 0, 0, 0],
-                    colorAxis = chart.colorAxis,
-                    margin = chart.margin,
-                    getOffset = function (axes) {
-                        axes.forEach(function (axis) {
-                            if (axis.visible) {
-                                axis.getOffset();
-                        }
-                    });
-                };
-                // pre-render axes to get labels offset width
-                if (chart.hasCartesianSeries) {
-                    getOffset(chart.axes);
-                }
-                else if (colorAxis && colorAxis.length) {
-                    getOffset(colorAxis);
-                }
-                // Add the axis offsets
-                marginNames.forEach(function (m, side) {
-                    if (!defined(margin[side])) {
-                        chart[m] += axisOffset[side];
-                    }
-                });
-                chart.setChartSize();
-            };
-            /**
-             * Reflows the chart to its container. By default, the chart reflows
-             * automatically to its container following a `window.resize` event, as per
-             * the [chart.reflow](https://api.highcharts.com/highcharts/chart.reflow)
-             * option. However, there are no reliable events for div resize, so if the
-             * container is resized without a window resize event, this must be called
-             * explicitly.
-             *
-             * @sample highcharts/members/chart-reflow/
-             *         Resize div and reflow
-             * @sample highcharts/chart/events-container/
-             *         Pop up and reflow
-             *
-             * @function Highcharts.Chart#reflow
-             *
-             * @param {global.Event} [e]
-             *        Event arguments. Used primarily when the function is called
-             *        internally as a response to window resize.
-             */
-            Chart.prototype.reflow = function (e) {
-                var chart = this, optionsChart = chart.options.chart, renderTo = chart.renderTo, hasUserSize = (defined(optionsChart.width) &&
-                        defined(optionsChart.height)), width = optionsChart.width || getStyle(renderTo, 'width'), height = optionsChart.height || getStyle(renderTo, 'height'), target = e ? e.target : win;
-                // Width and height checks for display:none. Target is doc in IE8 and
-                // Opera, win in Firefox, Chrome and IE9.
-                if (!hasUserSize &&
-                    !chart.isPrinting &&
-                    width &&
-                    height &&
-                    (target === win || target === doc)) {
-                    if (width !== chart.containerWidth ||
-                        height !== chart.containerHeight) {
-                        U.clearTimeout(chart.reflowTimeout);
-                        // When called from window.resize, e is set, else it's called
-                        // directly (#2224)
-                        chart.reflowTimeout = syncTimeout(function () {
-                            // Set size, it may have been destroyed in the meantime
-                            // (#1257)
-                            if (chart.container) {
-                                chart.setSize(void 0, void 0, false);
-                            }
-                        }, e ? 100 : 0);
-                    }
-                    chart.containerWidth = width;
-                    chart.containerHeight = height;
-                }
-            };
-            /**
-             * Toggle the event handlers necessary for auto resizing, depending on the
-             * `chart.reflow` option.
-             *
-             * @private
-             * @function Highcharts.Chart#setReflow
-             */
-            Chart.prototype.setReflow = function (reflow) {
-                var chart = this;
-                if (reflow !== false && !this.unbindReflow) {
-                    this.unbindReflow = addEvent(win, 'resize', function (e) {
-                        // a removed event listener still runs in Edge and IE if the
-                        // listener was removed while the event runs, so check if the
-                        // chart is not destroyed (#11609)
-                        if (chart.options) {
-                            chart.reflow(e);
-                        }
-                    });
-                    addEvent(this, 'destroy', this.unbindReflow);
-                }
-                else if (reflow === false && this.unbindReflow) {
-                    // Unbind and unset
-                    this.unbindReflow = this.unbindReflow();
-                }
-                // The following will add listeners to re-fit the chart before and after
-                // printing (#2284). However it only works in WebKit. Should have worked
-                // in Firefox, but not supported in IE.
-                /*
-                if (win.matchMedia) {
-                    win.matchMedia('print').addListener(function reflow() {
-                        chart.reflow();
-                    });
-                }
-                //*/
-            };
-            /**
-             * Resize the chart to a given width and height. In order to set the width
-             * only, the height argument may be skipped. To set the height only, pass
-             * `undefined` for the width.
-             *
-             * @sample highcharts/members/chart-setsize-button/
-             *         Test resizing from buttons
-             * @sample highcharts/members/chart-setsize-jquery-resizable/
-             *         Add a jQuery UI resizable
-             * @sample stock/members/chart-setsize/
-             *         Highstock with UI resizable
-             *
-             * @function Highcharts.Chart#setSize
-             *
-             * @param {number|null} [width]
-             *        The new pixel width of the chart. Since v4.2.6, the argument can
-             *        be `undefined` in order to preserve the current value (when
-             *        setting height only), or `null` to adapt to the width of the
-             *        containing element.
-             *
-             * @param {number|null} [height]
-             *        The new pixel height of the chart. Since v4.2.6, the argument can
-             *        be `undefined` in order to preserve the current value, or `null`
-             *        in order to adapt to the height of the containing element.
-             *
-             * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation=true]
-             *        Whether and how to apply animation.
-             *
-             * @return {void}
-             *
-             * @fires Highcharts.Chart#event:endResize
-             * @fires Highcharts.Chart#event:resize
-             */
-            Chart.prototype.setSize = function (width, height, animation) {
-                var chart = this,
-                    renderer = chart.renderer,
-                    globalAnimation;
-                // Handle the isResizing counter
-                chart.isResizing += 1;
-                // set the animation for the current process
-                setAnimation(animation, chart);
-                globalAnimation = renderer.globalAnimation;
-                chart.oldChartHeight = chart.chartHeight;
-                chart.oldChartWidth = chart.chartWidth;
-                if (typeof width !== 'undefined') {
-                    chart.options.chart.width = width;
-                }
-                if (typeof height !== 'undefined') {
-                    chart.options.chart.height = height;
-                }
-                chart.getChartSize();
-                // Resize the container with the global animation applied if enabled
-                // (#2503)
-                if (!chart.styledMode) {
-                    (globalAnimation ? animate : css)(chart.container, {
-                        width: chart.chartWidth + 'px',
-                        height: chart.chartHeight + 'px'
-                    }, globalAnimation);
-                }
-                chart.setChartSize(true);
-                renderer.setSize(chart.chartWidth, chart.chartHeight, globalAnimation);
-                // handle axes
-                chart.axes.forEach(function (axis) {
-                    axis.isDirty = true;
-                    axis.setScale();
-                });
-                chart.isDirtyLegend = true; // force legend redraw
-                chart.isDirtyBox = true; // force redraw of plot and chart border
-                chart.layOutTitles(); // #2857
-                chart.getMargins();
-                chart.redraw(globalAnimation);
-                chart.oldChartHeight = null;
-                fireEvent(chart, 'resize');
-                // Fire endResize and set isResizing back. If animation is disabled,
-                // fire without delay
-                syncTimeout(function () {
-                    if (chart) {
-                        fireEvent(chart, 'endResize', null, function () {
-                            chart.isResizing -= 1;
-                        });
-                    }
-                }, animObject(globalAnimation).duration);
-            };
-            /**
-             * Set the public chart properties. This is done before and after the
-             * pre-render to determine margin sizes.
-             *
-             * @private
-             * @function Highcharts.Chart#setChartSize
-             * @fires Highcharts.Chart#event:afterSetChartSize
-             */
-            Chart.prototype.setChartSize = function (skipAxes) {
-                var chart = this,
-                    inverted = chart.inverted,
-                    renderer = chart.renderer,
-                    chartWidth = chart.chartWidth,
-                    chartHeight = chart.chartHeight,
-                    optionsChart = chart.options.chart,
-                    spacing = chart.spacing,
-                    clipOffset = chart.clipOffset,
-                    clipX,
-                    clipY,
-                    plotLeft,
-                    plotTop,
-                    plotWidth,
-                    plotHeight,
-                    plotBorderWidth;
-                /**
-                 * The current left position of the plot area in pixels.
-                 *
-                 * @name Highcharts.Chart#plotLeft
-                 * @type {number}
-                 */
-                chart.plotLeft = plotLeft = Math.round(chart.plotLeft);
-                /**
-                 * The current top position of the plot area in pixels.
-                 *
-                 * @name Highcharts.Chart#plotTop
-                 * @type {number}
-                 */
-                chart.plotTop = plotTop = Math.round(chart.plotTop);
-                /**
-                 * The current width of the plot area in pixels.
-                 *
-                 * @name Highcharts.Chart#plotWidth
-                 * @type {number}
-                 */
-                chart.plotWidth = plotWidth = Math.max(0, Math.round(chartWidth - plotLeft - chart.marginRight));
-                /**
-                 * The current height of the plot area in pixels.
-                 *
-                 * @name Highcharts.Chart#plotHeight
-                 * @type {number}
-                 */
-                chart.plotHeight = plotHeight = Math.max(0, Math.round(chartHeight - plotTop - chart.marginBottom));
-                chart.plotSizeX = inverted ? plotHeight : plotWidth;
-                chart.plotSizeY = inverted ? plotWidth : plotHeight;
-                chart.plotBorderWidth = optionsChart.plotBorderWidth || 0;
-                // Set boxes used for alignment
-                chart.spacingBox = renderer.spacingBox = {
-                    x: spacing[3],
-                    y: spacing[0],
-                    width: chartWidth - spacing[3] - spacing[1],
-                    height: chartHeight - spacing[0] - spacing[2]
-                };
-                chart.plotBox = renderer.plotBox = {
-                    x: plotLeft,
-                    y: plotTop,
-                    width: plotWidth,
-                    height: plotHeight
-                };
-                plotBorderWidth = 2 * Math.floor(chart.plotBorderWidth / 2);
-                clipX = Math.ceil(Math.max(plotBorderWidth, clipOffset[3]) / 2);
-                clipY = Math.ceil(Math.max(plotBorderWidth, clipOffset[0]) / 2);
-                chart.clipBox = {
-                    x: clipX,
-                    y: clipY,
-                    width: Math.floor(chart.plotSizeX -
-                        Math.max(plotBorderWidth, clipOffset[1]) / 2 -
-                        clipX),
-                    height: Math.max(0, Math.floor(chart.plotSizeY -
-                        Math.max(plotBorderWidth, clipOffset[2]) / 2 -
-                        clipY))
-                };
-                if (!skipAxes) {
-                    chart.axes.forEach(function (axis) {
-                        axis.setAxisSize();
-                        axis.setAxisTranslation();
-                    });
-                }
-                fireEvent(chart, 'afterSetChartSize', { skipAxes: skipAxes });
-            };
-            /**
-             * Initial margins before auto size margins are applied.
-             *
-             * @private
-             * @function Highcharts.Chart#resetMargins
-             */
-            Chart.prototype.resetMargins = function () {
-                fireEvent(this, 'resetMargins');
-                var chart = this,
-                    chartOptions = chart.options.chart;
-                // Create margin and spacing array
-                ['margin', 'spacing'].forEach(function splashArrays(target) {
-                    var value = chartOptions[target],
-                        values = isObject(value) ? value : [value,
-                        value,
-                        value,
-                        value];
-                    [
-                        'Top',
-                        'Right',
-                        'Bottom',
-                        'Left'
-                    ].forEach(function (sideName, side) {
-                        chart[target][side] = pick(chartOptions[target + sideName], values[side]);
-                    });
-                });
-                // Set margin names like chart.plotTop, chart.plotLeft,
-                // chart.marginRight, chart.marginBottom.
-                marginNames.forEach(function (m, side) {
-                    chart[m] = pick(chart.margin[side], chart.spacing[side]);
-                });
-                chart.axisOffset = [0, 0, 0, 0]; // top, right, bottom, left
-                chart.clipOffset = [0, 0, 0, 0];
-            };
-            /**
-             * Internal function to draw or redraw the borders and backgrounds for chart
-             * and plot area.
-             *
-             * @private
-             * @function Highcharts.Chart#drawChartBox
-             * @fires Highcharts.Chart#event:afterDrawChartBox
-             */
-            Chart.prototype.drawChartBox = function () {
-                var chart = this,
-                    optionsChart = chart.options.chart,
-                    renderer = chart.renderer,
-                    chartWidth = chart.chartWidth,
-                    chartHeight = chart.chartHeight,
-                    chartBackground = chart.chartBackground,
-                    plotBackground = chart.plotBackground,
-                    plotBorder = chart.plotBorder,
-                    chartBorderWidth,
-                    styledMode = chart.styledMode,
-                    plotBGImage = chart.plotBGImage,
-                    chartBackgroundColor = optionsChart.backgroundColor,
-                    plotBackgroundColor = optionsChart.plotBackgroundColor,
-                    plotBackgroundImage = optionsChart.plotBackgroundImage,
-                    mgn,
-                    bgAttr,
-                    plotLeft = chart.plotLeft,
-                    plotTop = chart.plotTop,
-                    plotWidth = chart.plotWidth,
-                    plotHeight = chart.plotHeight,
-                    plotBox = chart.plotBox,
-                    clipRect = chart.clipRect,
-                    clipBox = chart.clipBox,
-                    verb = 'animate';
-                // Chart area
-                if (!chartBackground) {
-                    chart.chartBackground = chartBackground = renderer.rect()
-                        .addClass('highcharts-background')
-                        .add();
-                    verb = 'attr';
-                }
-                if (!styledMode) {
-                    // Presentational
-                    chartBorderWidth = optionsChart.borderWidth || 0;
-                    mgn = chartBorderWidth + (optionsChart.shadow ? 8 : 0);
-                    bgAttr = {
-                        fill: chartBackgroundColor || 'none'
-                    };
-                    if (chartBorderWidth || chartBackground['stroke-width']) { // #980
-                        bgAttr.stroke = optionsChart.borderColor;
-                        bgAttr['stroke-width'] = chartBorderWidth;
-                    }
-                    chartBackground
-                        .attr(bgAttr)
-                        .shadow(optionsChart.shadow);
-                }
-                else {
-                    chartBorderWidth = mgn = chartBackground.strokeWidth();
-                }
-                chartBackground[verb]({
-                    x: mgn / 2,
-                    y: mgn / 2,
-                    width: chartWidth - mgn - chartBorderWidth % 2,
-                    height: chartHeight - mgn - chartBorderWidth % 2,
-                    r: optionsChart.borderRadius
-                });
-                // Plot background
-                verb = 'animate';
-                if (!plotBackground) {
-                    verb = 'attr';
-                    chart.plotBackground = plotBackground = renderer.rect()
-                        .addClass('highcharts-plot-background')
-                        .add();
-                }
-                plotBackground[verb](plotBox);
-                if (!styledMode) {
-                    // Presentational attributes for the background
-                    plotBackground
-                        .attr({
-                        fill: plotBackgroundColor || 'none'
-                    })
-                        .shadow(optionsChart.plotShadow);
-                    // Create the background image
-                    if (plotBackgroundImage) {
-                        if (!plotBGImage) {
-                            chart.plotBGImage = renderer.image(plotBackgroundImage, plotLeft, plotTop, plotWidth, plotHeight).add();
-                        }
-                        else {
-                            if (plotBackgroundImage !== plotBGImage.attr('href')) {
-                                plotBGImage.attr('href', plotBackgroundImage);
-                            }
-                            plotBGImage.animate(plotBox);
-                        }
-                    }
-                }
-                // Plot clip
-                if (!clipRect) {
-                    chart.clipRect = renderer.clipRect(clipBox);
-                }
-                else {
-                    clipRect.animate({
-                        width: clipBox.width,
-                        height: clipBox.height
-                    });
-                }
-                // Plot area border
-                verb = 'animate';
-                if (!plotBorder) {
-                    verb = 'attr';
-                    chart.plotBorder = plotBorder = renderer.rect()
-                        .addClass('highcharts-plot-border')
-                        .attr({
-                        zIndex: 1 // Above the grid
-                    })
-                        .add();
-                }
-                if (!styledMode) {
-                    // Presentational
-                    plotBorder.attr({
-                        stroke: optionsChart.plotBorderColor,
-                        'stroke-width': optionsChart.plotBorderWidth || 0,
-                        fill: 'none'
-                    });
-                }
-                plotBorder[verb](plotBorder.crisp({
-                    x: plotLeft,
-                    y: plotTop,
-                    width: plotWidth,
-                    height: plotHeight
-                }, -plotBorder.strokeWidth())); // #3282 plotBorder should be negative;
-                // reset
-                chart.isDirtyBox = false;
-                fireEvent(this, 'afterDrawChartBox');
-            };
-            /**
-             * Detect whether a certain chart property is needed based on inspecting its
-             * options and series. This mainly applies to the chart.inverted property,
-             * and in extensions to the chart.angular and chart.polar properties.
-             *
-             * @private
-             * @function Highcharts.Chart#propFromSeries
-             * @return {void}
-             */
-            Chart.prototype.propFromSeries = function () {
-                var chart = this,
-                    optionsChart = chart.options.chart,
-                    klass,
-                    seriesOptions = chart.options.series,
-                    i,
-                    value;
-                /**
-                 * The flag is set to `true` if a series of the chart is inverted.
-                 *
-                 * @name Highcharts.Chart#inverted
-                 * @type {boolean|undefined}
-                 */
-                ['inverted', 'angular', 'polar'].forEach(function (key) {
-                    // The default series type's class
-                    klass = BaseSeries.seriesTypes[(optionsChart.type ||
-                        optionsChart.defaultSeriesType)];
-                    // Get the value from available chart-wide properties
-                    value =
-                        // It is set in the options:
-                        optionsChart[key] ||
-                            // The default series class:
-                            (klass && klass.prototype[key]);
-                    // requires it
-                    // 4. Check if any the chart's series require it
-                    i = seriesOptions && seriesOptions.length;
-                    while (!value && i--) {
-                        klass = BaseSeries.seriesTypes[seriesOptions[i].type];
-                        if (klass && klass.prototype[key]) {
-                            value = true;
-                        }
-                    }
-                    // Set the chart property
-                    chart[key] = value;
-                });
-            };
-            /**
-             * Internal function to link two or more series together, based on the
-             * `linkedTo` option. This is done from `Chart.render`, and after
-             * `Chart.addSeries` and `Series.remove`.
-             *
-             * @private
-             * @function Highcharts.Chart#linkSeries
-             * @fires Highcharts.Chart#event:afterLinkSeries
-             */
-            Chart.prototype.linkSeries = function () {
-                var chart = this,
-                    chartSeries = chart.series;
-                // Reset links
-                chartSeries.forEach(function (series) {
-                    series.linkedSeries.length = 0;
-                });
-                // Apply new links
-                chartSeries.forEach(function (series) {
-                    var linkedTo = series.options.linkedTo;
-                    if (isString(linkedTo)) {
-                        if (linkedTo === ':previous') {
-                            linkedTo = chart.series[series.index - 1];
-                        }
-                        else {
-                            linkedTo = chart.get(linkedTo);
-                        }
-                        // #3341 avoid mutual linking
-                        if (linkedTo && linkedTo.linkedParent !== series) {
-                            linkedTo.linkedSeries.push(series);
-                            series.linkedParent = linkedTo;
-                            if (linkedTo.enabledDataSorting) {
-                                series.setDataSortingOptions();
-                            }
-                            series.visible = pick(series.options.visible, linkedTo.options.visible, series.visible); // #3879
-                        }
-                    }
-                });
-                fireEvent(this, 'afterLinkSeries');
-            };
-            /**
-             * Render series for the chart.
-             *
-             * @private
-             * @function Highcharts.Chart#renderSeries
-             */
-            Chart.prototype.renderSeries = function () {
-                this.series.forEach(function (serie) {
-                    serie.translate();
-                    serie.render();
-                });
-            };
-            /**
-             * Render labels for the chart.
-             *
-             * @private
-             * @function Highcharts.Chart#renderLabels
-             */
-            Chart.prototype.renderLabels = function () {
-                var chart = this,
-                    labels = chart.options.labels;
-                if (labels.items) {
-                    labels.items.forEach(function (label) {
-                        var style = extend(labels.style,
-                            label.style),
-                            x = pInt(style.left) + chart.plotLeft,
-                            y = pInt(style.top) + chart.plotTop + 12;
-                        // delete to prevent rewriting in IE
-                        delete style.left;
-                        delete style.top;
-                        chart.renderer.text(label.html, x, y)
-                            .attr({ zIndex: 2 })
-                            .css(style)
-                            .add();
-                    });
-                }
-            };
-            /**
-             * Render all graphics for the chart. Runs internally on initialization.
-             *
-             * @private
-             * @function Highcharts.Chart#render
-             */
-            Chart.prototype.render = function () {
-                var chart = this,
-                    axes = chart.axes,
-                    colorAxis = chart.colorAxis,
-                    renderer = chart.renderer,
-                    options = chart.options,
-                    correction = 0, // correction for X axis labels
-                    tempWidth,
-                    tempHeight,
-                    redoHorizontal,
-                    redoVertical,
-                    renderAxes = function (axes) {
-                        axes.forEach(function (axis) {
-                            if (axis.visible) {
-                                axis.render();
-                        }
-                    });
-                };
-                // Title
-                chart.setTitle();
-                /**
-                 * The overview of the chart's series.
-                 *
-                 * @name Highcharts.Chart#legend
-                 * @type {Highcharts.Legend}
-                 */
-                chart.legend = new Legend(chart, options.legend);
-                // Get stacks
-                if (chart.getStacks) {
-                    chart.getStacks();
-                }
-                // Get chart margins
-                chart.getMargins(true);
-                chart.setChartSize();
-                // Record preliminary dimensions for later comparison
-                tempWidth = chart.plotWidth;
-                axes.some(function (axis) {
-                    if (axis.horiz &&
-                        axis.visible &&
-                        axis.options.labels.enabled &&
-                        axis.series.length) {
-                        // 21 is the most common correction for X axis labels
-                        correction = 21;
-                        return true;
-                    }
-                });
-                // use Math.max to prevent negative plotHeight
-                chart.plotHeight = Math.max(chart.plotHeight - correction, 0);
-                tempHeight = chart.plotHeight;
-                // Get margins by pre-rendering axes
-                axes.forEach(function (axis) {
-                    axis.setScale();
-                });
-                chart.getAxisMargins();
-                // If the plot area size has changed significantly, calculate tick
-                // positions again
-                redoHorizontal = tempWidth / chart.plotWidth > 1.1;
-                // Height is more sensitive, use lower threshold
-                redoVertical = tempHeight / chart.plotHeight > 1.05;
-                if (redoHorizontal || redoVertical) {
-                    axes.forEach(function (axis) {
-                        if ((axis.horiz && redoHorizontal) ||
-                            (!axis.horiz && redoVertical)) {
-                            // update to reflect the new margins
-                            axis.setTickInterval(true);
-                        }
-                    });
-                    chart.getMargins(); // second pass to check for new labels
-                }
-                // Draw the borders and backgrounds
-                chart.drawChartBox();
-                // Axes
-                if (chart.hasCartesianSeries) {
-                    renderAxes(axes);
-                }
-                else if (colorAxis && colorAxis.length) {
-                    renderAxes(colorAxis);
-                }
-                // The series
-                if (!chart.seriesGroup) {
-                    chart.seriesGroup = renderer.g('series-group')
-                        .attr({ zIndex: 3 })
-                        .add();
-                }
-                chart.renderSeries();
-                // Labels
-                chart.renderLabels();
-                // Credits
-                chart.addCredits();
-                // Handle responsiveness
-                if (chart.setResponsive) {
-                    chart.setResponsive();
-                }
-                // Handle scaling
-                chart.updateContainerScaling();
-                // Set flag
-                chart.hasRendered = true;
-            };
-            /**
-             * Set a new credits label for the chart.
-             *
-             * @sample highcharts/credits/credits-update/
-             *         Add and update credits
-             *
-             * @function Highcharts.Chart#addCredits
-             *
-             * @param {Highcharts.CreditsOptions} [credits]
-             * A configuration object for the new credits.
-             */
-            Chart.prototype.addCredits = function (credits) {
-                var chart = this,
-                    creds = merge(true,
-                    this.options.credits,
-                    credits);
-                if (creds.enabled && !this.credits) {
-                    /**
-                     * The chart's credits label. The label has an `update` method that
-                     * allows setting new options as per the
-                     * [credits options set](https://api.highcharts.com/highcharts/credits).
-                     *
-                     * @name Highcharts.Chart#credits
-                     * @type {Highcharts.SVGElement}
-                     */
-                    this.credits = this.renderer.text(creds.text + (this.mapCredits || ''), 0, 0)
-                        .addClass('highcharts-credits')
-                        .on('click', function () {
-                        if (creds.href) {
-                            win.location.href = creds.href;
-                        }
-                    })
-                        .attr({
-                        align: creds.position.align,
-                        zIndex: 8
-                    });
-                    if (!chart.styledMode) {
-                        this.credits.css(creds.style);
-                    }
-                    this.credits
-                        .add()
-                        .align(creds.position);
-                    // Dynamically update
-                    this.credits.update = function (options) {
-                        chart.credits = chart.credits.destroy();
-                        chart.addCredits(options);
-                    };
-                }
-            };
-            /**
-             * Handle scaling, #11329 - when there is scaling/transform on the container
-             * or on a parent element, we need to take this into account. We calculate
-             * the scaling once here and it is picked up where we need to use it
-             * (Pointer, Tooltip).
-             *
-             * @private
-             * @function Highcharts.Chart#updateContainerScaling
-             */
-            Chart.prototype.updateContainerScaling = function () {
-                var container = this.container;
-                // #13342 - tooltip was not visible in Chrome, when chart
-                // updates height.
-                if (container.offsetWidth > 2 && // #13342
-                    container.offsetHeight > 2 && // #13342
-                    container.getBoundingClientRect) {
-                    var bb = container.getBoundingClientRect(),
-                        scaleX = bb.width / container.offsetWidth,
-                        scaleY = bb.height / container.offsetHeight;
-                    if (scaleX !== 1 || scaleY !== 1) {
-                        this.containerScaling = { scaleX: scaleX, scaleY: scaleY };
-                    }
-                    else {
-                        delete this.containerScaling;
-                    }
-                }
-            };
-            /**
-             * Remove the chart and purge memory. This method is called internally
-             * before adding a second chart into the same container, as well as on
-             * window unload to prevent leaks.
-             *
-             * @sample highcharts/members/chart-destroy/
-             *         Destroy the chart from a button
-             * @sample stock/members/chart-destroy/
-             *         Destroy with Highstock
-             *
-             * @function Highcharts.Chart#destroy
-             *
-             * @fires Highcharts.Chart#event:destroy
-             */
-            Chart.prototype.destroy = function () {
-                var chart = this,
-                    axes = chart.axes,
-                    series = chart.series,
-                    container = chart.container,
-                    i,
-                    parentNode = container && container.parentNode;
-                // fire the chart.destoy event
-                fireEvent(chart, 'destroy');
-                // Delete the chart from charts lookup array
-                if (chart.renderer.forExport) {
-                    erase(charts, chart); // #6569
-                }
-                else {
-                    charts[chart.index] = void 0;
-                }
-                H.chartCount--;
-                chart.renderTo.removeAttribute('data-highcharts-chart');
-                // remove events
-                removeEvent(chart);
-                // ==== Destroy collections:
-                // Destroy axes
-                i = axes.length;
-                while (i--) {
-                    axes[i] = axes[i].destroy();
-                }
-                // Destroy scroller & scroller series before destroying base series
-                if (this.scroller && this.scroller.destroy) {
-                    this.scroller.destroy();
-                }
-                // Destroy each series
-                i = series.length;
-                while (i--) {
-                    series[i] = series[i].destroy();
-                }
-                // ==== Destroy chart properties:
-                [
-                    'title', 'subtitle', 'chartBackground', 'plotBackground',
-                    'plotBGImage', 'plotBorder', 'seriesGroup', 'clipRect', 'credits',
-                    'pointer', 'rangeSelector', 'legend', 'resetZoomButton', 'tooltip',
-                    'renderer'
-                ].forEach(function (name) {
-                    var prop = chart[name];
-                    if (prop && prop.destroy) {
-                        chart[name] = prop.destroy();
-                    }
-                });
-                // Remove container and all SVG, check container as it can break in IE
-                // when destroyed before finished loading
-                if (container) {
-                    container.innerHTML = '';
-                    removeEvent(container);
-                    if (parentNode) {
-                        discardElement(container);
-                    }
-                }
-                // clean it all up
-                objectEach(chart, function (val, key) {
-                    delete chart[key];
-                });
-            };
-            /**
-             * Prepare for first rendering after all data are loaded.
-             *
-             * @private
-             * @function Highcharts.Chart#firstRender
-             * @fires Highcharts.Chart#event:beforeRender
-             */
-            Chart.prototype.firstRender = function () {
-                var chart = this,
-                    options = chart.options;
-                // Hook for oldIE to check whether the chart is ready to render
-                if (chart.isReadyToRender && !chart.isReadyToRender()) {
-                    return;
-                }
-                // Create the container
-                chart.getContainer();
-                chart.resetMargins();
-                chart.setChartSize();
-                // Set the common chart properties (mainly invert) from the given series
-                chart.propFromSeries();
-                // get axes
-                chart.getAxes();
-                // Initialize the series
-                (isArray(options.series) ? options.series : []).forEach(
-                // #9680
-                function (serieOptions) {
-                    chart.initSeries(serieOptions);
-                });
-                chart.linkSeries();
-                chart.setSeriesData();
-                // Run an event after axes and series are initialized, but before
-                // render. At this stage, the series data is indexed and cached in the
-                // xData and yData arrays, so we can access those before rendering. Used
-                // in Highstock.
-                fireEvent(chart, 'beforeRender');
-                // depends on inverted and on margins being set
-                if (Pointer) {
-                    if (!H.hasTouch && (win.PointerEvent || win.MSPointerEvent)) {
-                        chart.pointer = new MSPointer(chart, options);
-                    }
-                    else {
-                        /**
-                         * The Pointer that keeps track of mouse and touch interaction.
-                         *
-                         * @memberof Highcharts.Chart
-                         * @name pointer
-                         * @type {Highcharts.Pointer}
-                         * @instance
-                         */
-                        chart.pointer = new Pointer(chart, options);
-                    }
-                }
-                chart.render();
-                // Fire the load event if there are no external images
-                if (!chart.renderer.imgCount && !chart.hasLoaded) {
-                    chart.onload();
-                }
-                // If the chart was rendered outside the top container, put it back in
-                // (#3679)
-                chart.temporaryDisplay(true);
-            };
-            /**
-             * Internal function that runs on chart load, async if any images are loaded
-             * in the chart. Runs the callbacks and triggers the `load` and `render`
-             * events.
-             *
-             * @private
-             * @function Highcharts.Chart#onload
-             * @fires Highcharts.Chart#event:load
-             * @fires Highcharts.Chart#event:render
-             */
-            Chart.prototype.onload = function () {
-                // Run callbacks, first the ones registered by modules, then user's one
-                this.callbacks.concat([this.callback]).forEach(function (fn) {
-                    // Chart destroyed in its own callback (#3600)
-                    if (fn && typeof this.index !== 'undefined') {
-                        fn.apply(this, [this]);
-                    }
-                }, this);
-                fireEvent(this, 'load');
-                fireEvent(this, 'render');
-                // Set up auto resize, check for not destroyed (#6068)
-                if (defined(this.index)) {
-                    this.setReflow(this.options.chart.reflow);
-                }
-                // Don't run again
-                this.hasLoaded = true;
-            };
-            return Chart;
-        }());
-        // Hook for adding callbacks in modules
-        Chart.prototype.callbacks = [];
-        /**
-         * Factory function for basic charts.
-         *
-         * @example
-         * // Render a chart in to div#container
-         * var chart = Highcharts.chart('container', {
-         *     title: {
-         *         text: 'My chart'
-         *     },
-         *     series: [{
-         *         data: [1, 3, 2, 4]
-         *     }]
-         * });
-         *
-         * @function Highcharts.chart
-         *
-         * @param {string|Highcharts.HTMLDOMElement} [renderTo]
-         *        The DOM element to render to, or its id.
-         *
-         * @param {Highcharts.Options} options
-         *        The chart options structure.
-         *
-         * @param {Highcharts.ChartCallbackFunction} [callback]
-         *        Function to run when the chart has loaded and and all external images
-         *        are loaded. Defining a
-         *        [chart.events.load](https://api.highcharts.com/highcharts/chart.events.load)
-         *        handler is equivalent.
-         *
-         * @return {Highcharts.Chart}
-         *         Returns the Chart object.
-         */
-        function chart(a, b, c) {
-            return new Chart(a, b, c);
-        }
-        H.chart = chart;
-        H.Chart = Chart;
-
-        return Chart;
-    });
-    _registerModule(_modules, 'Extensions/ScrollablePlotArea.js', [_modules['Core/Animation/AnimationUtilities.js'], _modules['Core/Chart/Chart.js'], _modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (A, Chart, H, U) {
-        /* *
-         *
-         *  (c) 2010-2020 Torstein Honsi
-         *
-         *  License: www.highcharts.com/license
-         *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
-         *
-         *  Highcharts feature to make the Y axis stay fixed when scrolling the chart
-         *  horizontally on mobile devices. Supports left and right side axes.
-         */
-        /*
-        WIP on vertical scrollable plot area (#9378). To do:
-        - Bottom axis positioning
-        - Test with Gantt
-        - Look for size optimizing the code
-        - API and demos
-         */
-        var stop = A.stop;
-        var addEvent = U.addEvent,
-            createElement = U.createElement,
-            pick = U.pick;
-        /**
-         * Options for a scrollable plot area. This feature provides a minimum size for
-         * the plot area of the chart. If the size gets smaller than this, typically
-         * on mobile devices, a native browser scrollbar is presented. This scrollbar
-         * provides smooth scrolling for the contents of the plot area, whereas the
-         * title, legend and unaffected axes are fixed.
-         *
-         * Since v7.1.2, a scrollable plot area can be defined for either horizontal or
-         * vertical scrolling, depending on whether the `minWidth` or `minHeight`
-         * option is set.
-         *
-         * @sample highcharts/chart/scrollable-plotarea
-         *         Scrollable plot area
-         * @sample highcharts/chart/scrollable-plotarea-vertical
-         *         Vertically scrollable plot area
-         * @sample {gantt} highcharts/chart/scrollable-plotarea-vertical
-         *         Gantt chart with vertically scrollable plot area
-         *
-         * @since     6.1.0
-         * @product   highcharts gantt
-         * @apioption chart.scrollablePlotArea
-         */
-        /**
-         * The minimum height for the plot area. If it gets smaller than this, the plot
-         * area will become scrollable.
-         *
-         * @type      {number}
-         * @apioption chart.scrollablePlotArea.minHeight
-         */
-        /**
-         * The minimum width for the plot area. If it gets smaller than this, the plot
-         * area will become scrollable.
-         *
-         * @type      {number}
-         * @apioption chart.scrollablePlotArea.minWidth
-         */
-        /**
-         * The initial scrolling position of the scrollable plot area. Ranges from 0 to
-         * 1, where 0 aligns the plot area to the left and 1 aligns it to the right.
-         * Typically we would use 1 if the chart has right aligned Y axes.
-         *
-         * @type      {number}
-         * @apioption chart.scrollablePlotArea.scrollPositionX
-         */
-        /**
-         * The initial scrolling position of the scrollable plot area. Ranges from 0 to
-         * 1, where 0 aligns the plot area to the top and 1 aligns it to the bottom.
-         *
-         * @type      {number}
-         * @apioption chart.scrollablePlotArea.scrollPositionY
-         */
-        /**
-         * The opacity of mask applied on one of the sides of the plot
-         * area.
-         *
-         * @sample {highcharts} highcharts/chart/scrollable-plotarea-opacity
-         *         Disabled opacity for the mask
-         *
-         * @type        {number}
-         * @default     0.85
-         * @since       7.1.1
-         * @apioption   chart.scrollablePlotArea.opacity
-         */
-        ''; // detach API doclets
-        /* eslint-disable no-invalid-this, valid-jsdoc */
-        addEvent(Chart, 'afterSetChartSize', function (e) {
-            var scrollablePlotArea = this.options.chart.scrollablePlotArea,
-                scrollableMinWidth = scrollablePlotArea && scrollablePlotArea.minWidth,
-                scrollableMinHeight = scrollablePlotArea && scrollablePlotArea.minHeight,
-                scrollablePixelsX,
-                scrollablePixelsY,
-                corrections;
-            if (!this.renderer.forExport) {
-                // The amount of pixels to scroll, the difference between chart
-                // width and scrollable width
-                if (scrollableMinWidth) {
-                    this.scrollablePixelsX = scrollablePixelsX = Math.max(0, scrollableMinWidth - this.chartWidth);
-                    if (scrollablePixelsX) {
-                        this.plotWidth += scrollablePixelsX;
-                        if (this.inverted) {
-                            this.clipBox.height += scrollablePixelsX;
-                            this.plotBox.height += scrollablePixelsX;
-                        }
-                        else {
-                            this.clipBox.width += scrollablePixelsX;
-                            this.plotBox.width += scrollablePixelsX;
-                        }
-                        corrections = {
-                            // Corrections for right side
-                            1: { name: 'right', value: scrollablePixelsX }
-                        };
-                    }
-                    // Currently we can only do either X or Y
-                }
-                else if (scrollableMinHeight) {
-                    this.scrollablePixelsY = scrollablePixelsY = Math.max(0, scrollableMinHeight - this.chartHeight);
-                    if (scrollablePixelsY) {
-                        this.plotHeight += scrollablePixelsY;
-                        if (this.inverted) {
-                            this.clipBox.width += scrollablePixelsY;
-                            this.plotBox.width += scrollablePixelsY;
-                        }
-                        else {
-                            this.clipBox.height += scrollablePixelsY;
-                            this.plotBox.height += scrollablePixelsY;
-                        }
-                        corrections = {
-                            2: { name: 'bottom', value: scrollablePixelsY }
-                        };
-                    }
-                }
-                if (corrections && !e.skipAxes) {
-                    this.axes.forEach(function (axis) {
-                        // For right and bottom axes, only fix the plot line length
-                        if (corrections[axis.side]) {
-                            // Get the plot lines right in getPlotLinePath,
-                            // temporarily set it to the adjusted plot width.
-                            axis.getPlotLinePath = function () {
-                                var marginName = corrections[axis.side].name,
-                                    correctionValue = corrections[axis.side].value, 
-                                    // axis.right or axis.bottom
-                                    margin = this[marginName],
-                                    path;
-                                // Temporarily adjust
-                                this[marginName] = margin - correctionValue;
-                                path = H.Axis.prototype.getPlotLinePath.apply(this, arguments);
-                                // Reset
-                                this[marginName] = margin;
-                                return path;
-                            };
-                        }
-                        else {
-                            // Apply the corrected plotWidth
-                            axis.setAxisSize();
-                            axis.setAxisTranslation();
-                        }
-                    });
-                }
-            }
-        });
-        addEvent(Chart, 'render', function () {
-            if (this.scrollablePixelsX || this.scrollablePixelsY) {
-                if (this.setUpScrolling) {
-                    this.setUpScrolling();
-                }
-                this.applyFixed();
-            }
-            else if (this.fixedDiv) { // Has been in scrollable mode
-                this.applyFixed();
-            }
-        });
-        /**
-         * @private
-         * @function Highcharts.Chart#setUpScrolling
-         * @return {void}
-         */
-        Chart.prototype.setUpScrolling = function () {
-            var _this = this;
-            var attribs = {
-                    WebkitOverflowScrolling: 'touch',
-                    overflowX: 'hidden',
-                    overflowY: 'hidden'
-                };
-            if (this.scrollablePixelsX) {
-                attribs.overflowX = 'auto';
-            }
-            if (this.scrollablePixelsY) {
-                attribs.overflowY = 'auto';
-            }
-            // Insert a container with position relative
-            // that scrolling and fixed container renders to (#10555)
-            this.scrollingParent = createElement('div', {
-                className: 'highcharts-scrolling-parent'
-            }, {
-                position: 'relative'
-            }, this.renderTo);
-            // Add the necessary divs to provide scrolling
-            this.scrollingContainer = createElement('div', {
-                'className': 'highcharts-scrolling'
-            }, attribs, this.scrollingParent);
-            // On scroll, reset the chart position because it applies to the scrolled
-            // container
-            addEvent(this.scrollingContainer, 'scroll', function () {
-                if (_this.pointer) {
-                    delete _this.pointer.chartPosition;
-                }
-            });
-            this.innerContainer = createElement('div', {
-                'className': 'highcharts-inner-container'
-            }, null, this.scrollingContainer);
-            // Now move the container inside
-            this.innerContainer.appendChild(this.container);
-            // Don't run again
-            this.setUpScrolling = null;
-        };
-        /**
-         * These elements are moved over to the fixed renderer and stay fixed when the
-         * user scrolls the chart
-         * @private
-         */
-        Chart.prototype.moveFixedElements = function () {
-            var container = this.container,
-                fixedRenderer = this.fixedRenderer,
-                fixedSelectors = [
-                    '.highcharts-contextbutton',
-                    '.highcharts-credits',
-                    '.highcharts-legend',
-                    '.highcharts-legend-checkbox',
-                    '.highcharts-navigator-series',
-                    '.highcharts-navigator-xaxis',
-                    '.highcharts-navigator-yaxis',
-                    '.highcharts-navigator',
-                    '.highcharts-reset-zoom',
-                    '.highcharts-scrollbar',
-                    '.highcharts-subtitle',
-                    '.highcharts-title'
-                ],
-                axisClass;
-            if (this.scrollablePixelsX && !this.inverted) {
-                axisClass = '.highcharts-yaxis';
-            }
-            else if (this.scrollablePixelsX && this.inverted) {
-                axisClass = '.highcharts-xaxis';
-            }
-            else if (this.scrollablePixelsY && !this.inverted) {
-                axisClass = '.highcharts-xaxis';
-            }
-            else if (this.scrollablePixelsY && this.inverted) {
-                axisClass = '.highcharts-yaxis';
-            }
-            fixedSelectors.push(axisClass, axisClass + '-labels');
-            fixedSelectors.forEach(function (className) {
-                [].forEach.call(container.querySelectorAll(className), function (elem) {
-                    (elem.namespaceURI === fixedRenderer.SVG_NS ?
-                        fixedRenderer.box :
-                        fixedRenderer.box.parentNode).appendChild(elem);
-                    elem.style.pointerEvents = 'auto';
-                });
-            });
-        };
-        /**
-         * @private
-         * @function Highcharts.Chart#applyFixed
-         * @return {void}
-         */
-        Chart.prototype.applyFixed = function () {
-            var _a,
-                _b;
-            var fixedRenderer,
-                scrollableWidth,
-                scrollableHeight,
-                firstTime = !this.fixedDiv,
-                scrollableOptions = this.options.chart.scrollablePlotArea;
-            // First render
-            if (firstTime) {
-                this.fixedDiv = createElement('div', {
-                    className: 'highcharts-fixed'
-                }, {
-                    position: 'absolute',
-                    overflow: 'hidden',
-                    pointerEvents: 'none',
-                    zIndex: 2,
-                    top: 0
-                }, null, true);
-                (_a = this.scrollingContainer) === null || _a === void 0 ? void 0 : _a.parentNode.insertBefore(this.fixedDiv, this.scrollingContainer);
-                this.renderTo.style.overflow = 'visible';
-                this.fixedRenderer = fixedRenderer = new H.Renderer(this.fixedDiv, this.chartWidth, this.chartHeight, (_b = this.options.chart) === null || _b === void 0 ? void 0 : _b.style);
-                // Mask
-                this.scrollableMask = fixedRenderer
-                    .path()
-                    .attr({
-                    fill: this.options.chart.backgroundColor || '#fff',
-                    'fill-opacity': pick(scrollableOptions.opacity, 0.85),
-                    zIndex: -1
-                })
-                    .addClass('highcharts-scrollable-mask')
-                    .add();
-                this.moveFixedElements();
-                addEvent(this, 'afterShowResetZoom', this.moveFixedElements);
-                addEvent(this, 'afterLayOutTitles', this.moveFixedElements);
-            }
-            else {
-                // Set the size of the fixed renderer to the visible width
-                this.fixedRenderer.setSize(this.chartWidth, this.chartHeight);
-            }
-            // Increase the size of the scrollable renderer and background
-            scrollableWidth = this.chartWidth + (this.scrollablePixelsX || 0);
-            scrollableHeight = this.chartHeight + (this.scrollablePixelsY || 0);
-            stop(this.container);
-            this.container.style.width = scrollableWidth + 'px';
-            this.container.style.height = scrollableHeight + 'px';
-            this.renderer.boxWrapper.attr({
-                width: scrollableWidth,
-                height: scrollableHeight,
-                viewBox: [0, 0, scrollableWidth, scrollableHeight].join(' ')
-            });
-            this.chartBackground.attr({
-                width: scrollableWidth,
-                height: scrollableHeight
-            });
-            this.scrollingContainer.style.height = this.chartHeight + 'px';
-            // Set scroll position
-            if (firstTime) {
-                if (scrollableOptions.scrollPositionX) {
-                    this.scrollingContainer.scrollLeft =
-                        this.scrollablePixelsX *
-                            scrollableOptions.scrollPositionX;
-                }
-                if (scrollableOptions.scrollPositionY) {
-                    this.scrollingContainer.scrollTop =
-                        this.scrollablePixelsY *
-                            scrollableOptions.scrollPositionY;
-                }
-            }
-            // Mask behind the left and right side
-            var axisOffset = this.axisOffset,
-                maskTop = this.plotTop - axisOffset[0] - 1,
-                maskLeft = this.plotLeft - axisOffset[3] - 1,
-                maskBottom = this.plotTop + this.plotHeight + axisOffset[2] + 1,
-                maskRight = this.plotLeft + this.plotWidth + axisOffset[1] + 1,
-                maskPlotRight = this.plotLeft + this.plotWidth -
-                    (this.scrollablePixelsX || 0),
-                maskPlotBottom = this.plotTop + this.plotHeight -
-                    (this.scrollablePixelsY || 0),
-                d;
-            if (this.scrollablePixelsX) {
-                d = [
-                    // Left side
-                    ['M', 0, maskTop],
-                    ['L', this.plotLeft - 1, maskTop],
-                    ['L', this.plotLeft - 1, maskBottom],
-                    ['L', 0, maskBottom],
-                    ['Z'],
-                    // Right side
-                    ['M', maskPlotRight, maskTop],
-                    ['L', this.chartWidth, maskTop],
-                    ['L', this.chartWidth, maskBottom],
-                    ['L', maskPlotRight, maskBottom],
-                    ['Z']
-                ];
-            }
-            else if (this.scrollablePixelsY) {
-                d = [
-                    // Top side
-                    ['M', maskLeft, 0],
-                    ['L', maskLeft, this.plotTop - 1],
-                    ['L', maskRight, this.plotTop - 1],
-                    ['L', maskRight, 0],
-                    ['Z'],
-                    // Bottom side
-                    ['M', maskLeft, maskPlotBottom],
-                    ['L', maskLeft, this.chartHeight],
-                    ['L', maskRight, this.chartHeight],
-                    ['L', maskRight, maskPlotBottom],
-                    ['Z']
-                ];
-            }
-            else {
-                d = [['M', 0, 0]];
-            }
-            if (this.redrawTrigger !== 'adjustHeight') {
-                this.scrollableMask.attr({ d: d });
-            }
-        };
-
-    });
-    _registerModule(_modules, 'Core/Axis/StackingAxis.js', [_modules['Core/Animation/AnimationUtilities.js'], _modules['Core/Utilities.js']], function (A, U) {
-        /* *
-         *
-         *  (c) 2010-2020 Torstein Honsi
-         *
-         *  License: www.highcharts.com/license
-         *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
-         *
-         * */
-        var getDeferredAnimation = A.getDeferredAnimation;
-        var addEvent = U.addEvent,
-            destroyObjectProperties = U.destroyObjectProperties,
-            fireEvent = U.fireEvent,
-            objectEach = U.objectEach,
-            pick = U.pick;
-        /* eslint-disable valid-jsdoc */
-        /**
-         * Adds stacking support to axes.
-         * @private
-         * @class
-         */
-        var StackingAxisAdditions = /** @class */ (function () {
-                /* *
-                 *
-                 *  Constructors
-                 *
-                 * */
-                function StackingAxisAdditions(axis) {
-                    this.oldStacks = {};
-                this.stacks = {};
-                this.stacksTouched = 0;
-                this.axis = axis;
-            }
-            /* *
-             *
-             *  Functions
-             *
-             * */
-            /**
-             * Build the stacks from top down
-             * @private
-             */
-            StackingAxisAdditions.prototype.buildStacks = function () {
-                var stacking = this;
-                var axis = stacking.axis;
-                var axisSeries = axis.series;
-                var reversedStacks = pick(axis.options.reversedStacks,
-                    true);
-                var len = axisSeries.length;
-                var actualSeries,
-                    i;
-                if (!axis.isXAxis) {
-                    stacking.usePercentage = false;
-                    i = len;
-                    while (i--) {
-                        actualSeries = axisSeries[reversedStacks ? i : len - i - 1];
-                        actualSeries.setStackedPoints();
-                        actualSeries.setGroupedPoints();
-                    }
-                    // Loop up again to compute percent and stream stack
-                    for (i = 0; i < len; i++) {
-                        axisSeries[i].modifyStacks();
-                    }
-                    fireEvent(axis, 'afterBuildStacks');
-                }
-            };
-            /**
-             * @private
-             */
-            StackingAxisAdditions.prototype.cleanStacks = function () {
-                var stacking = this;
-                var axis = stacking.axis;
-                var stacks;
-                if (!axis.isXAxis) {
-                    if (stacking.oldStacks) {
-                        stacks = stacking.stacks = stacking.oldStacks;
-                    }
-                    // reset stacks
-                    objectEach(stacks, function (type) {
-                        objectEach(type, function (stack) {
-                            stack.cumulative = stack.total;
-                        });
-                    });
-                }
-            };
-            /**
-             * Set all the stacks to initial states and destroy unused ones.
-             * @private
-             */
-            StackingAxisAdditions.prototype.resetStacks = function () {
-                var stacking = this;
-                var axis = stacking.axis;
-                var stacks = stacking.stacks;
-                if (!axis.isXAxis) {
-                    objectEach(stacks, function (type) {
-                        objectEach(type, function (stack, key) {
-                            // Clean up memory after point deletion (#1044, #4320)
-                            if (stack.touched < stacking.stacksTouched) {
-                                stack.destroy();
-                                delete type[key];
-                                // Reset stacks
-                            }
-                            else {
-                                stack.total = null;
-                                stack.cumulative = null;
-                            }
-                        });
-                    });
-                }
-            };
-            /**
-             * @private
-             */
-            StackingAxisAdditions.prototype.renderStackTotals = function () {
-                var stacking = this;
-                var axis = stacking.axis;
-                var chart = axis.chart;
-                var renderer = chart.renderer;
-                var stacks = stacking.stacks;
-                var stackLabelsAnim = axis.options.stackLabels.animation;
-                var animationConfig = getDeferredAnimation(chart,
-                    stackLabelsAnim);
-                var stackTotalGroup = stacking.stackTotalGroup = (stacking.stackTotalGroup ||
-                        renderer
-                            .g('stack-labels')
-                            .attr({
-                            visibility: 'visible',
-                            zIndex: 6,
-                            opacity: 0
-                        })
-                            .add());
-                // plotLeft/Top will change when y axis gets wider so we need to
-                // translate the stackTotalGroup at every render call. See bug #506
-                // and #516
-                stackTotalGroup.translate(chart.plotLeft, chart.plotTop);
-                // Render each stack total
-                objectEach(stacks, function (type) {
-                    objectEach(type, function (stack) {
-                        stack.render(stackTotalGroup);
-                    });
-                });
-                stackTotalGroup.animate({
-                    opacity: 1
-                }, animationConfig);
-            };
-            return StackingAxisAdditions;
-        }());
-        /**
-         * Axis with stacking support.
-         * @private
-         * @class
-         */
-        var StackingAxis = /** @class */ (function () {
-                function StackingAxis() {
-                }
-                /* *
-                 *
-                 *  Static Functions
-                 *
-                 * */
-                /**
-                 * Extends axis with stacking support.
-                 * @private
-                 */
-                StackingAxis.compose = function (AxisClass) {
-                    var axisProto = AxisClass.prototype;
-                addEvent(AxisClass, 'init', StackingAxis.onInit);
-                addEvent(AxisClass, 'destroy', StackingAxis.onDestroy);
-            };
-            /**
-             * @private
-             */
-            StackingAxis.onDestroy = function () {
-                var stacking = this.stacking;
-                if (!stacking) {
-                    return;
-                }
-                var stacks = stacking.stacks;
-                // Destroy each stack total
-                objectEach(stacks, function (stack, stackKey) {
-                    destroyObjectProperties(stack);
-                    stacks[stackKey] = null;
-                });
-                if (stacking &&
-                    stacking.stackTotalGroup) {
-                    stacking.stackTotalGroup.destroy();
-                }
-            };
-            /**
-             * @private
-             */
-            StackingAxis.onInit = function () {
-                var axis = this;
-                if (!axis.stacking) {
-                    axis.stacking = new StackingAxisAdditions(axis);
-                }
-            };
-            return StackingAxis;
-        }());
-
-        return StackingAxis;
-    });
-    _registerModule(_modules, 'Mixins/LegendSymbol.js', [_modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (H, U) {
-        /* *
-         *
-         *  (c) 2010-2020 Torstein Honsi
-         *
-         *  License: www.highcharts.com/license
-         *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
-         *
-         * */
-        var merge = U.merge,
-            pick = U.pick;
-        /* eslint-disable valid-jsdoc */
-        /**
-         * Legend symbol mixin.
-         *
-         * @private
-         * @mixin Highcharts.LegendSymbolMixin
-         */
-        var LegendSymbolMixin = H.LegendSymbolMixin = {
-                /**
-                 * Get the series' symbol in the legend
-                 *
-                 * @private
-                 * @function Highcharts.LegendSymbolMixin.drawRectangle
-                 *
-                 * @param {Highcharts.Legend} legend
-                 * The legend object
-                 *
-                 * @param {Highcharts.Point|Highcharts.Series} item
-                 * The series (this) or point
-                 */
-                drawRectangle: function (legend,
-            item) {
-                    var options = legend.options,
-            symbolHeight = legend.symbolHeight,
-            square = options.squareSymbol,
-            symbolWidth = square ? symbolHeight : legend.symbolWidth;
-                item.legendSymbol = this.chart.renderer.rect(square ? (legend.symbolWidth - symbolHeight) / 2 : 0, legend.baseline - symbolHeight + 1, // #3988
-                symbolWidth, symbolHeight, pick(legend.options.symbolRadius, symbolHeight / 2))
-                    .addClass('highcharts-point')
-                    .attr({
-                    zIndex: 3
-                }).add(item.legendGroup);
-            },
-            /**
-             * Get the series' symbol in the legend. This method should be overridable
-             * to create custom symbols through
-             * Highcharts.seriesTypes[type].prototype.drawLegendSymbols.
-             *
-             * @private
-             * @function Highcharts.LegendSymbolMixin.drawLineMarker
-             *
-             * @param {Highcharts.Legend} legend
-             * The legend object.
-             */
-            drawLineMarker: function (legend) {
-                var options = this.options,
-                    markerOptions = options.marker,
-                    radius,
-                    legendSymbol,
-                    symbolWidth = legend.symbolWidth,
-                    symbolHeight = legend.symbolHeight,
-                    generalRadius = symbolHeight / 2,
-                    renderer = this.chart.renderer,
-                    legendItemGroup = this.legendGroup,
-                    verticalCenter = legend.baseline -
-                        Math.round(legend.fontMetrics.b * 0.3),
-                    attr = {};
-                // Draw the line
-                if (!this.chart.styledMode) {
-                    attr = {
-                        'stroke-width': options.lineWidth || 0
-                    };
-                    if (options.dashStyle) {
-                        attr.dashstyle = options.dashStyle;
-                    }
-                }
-                this.legendLine = renderer
-                    .path([
-                    ['M', 0, verticalCenter],
-                    ['L', symbolWidth, verticalCenter]
-                ])
-                    .addClass('highcharts-graph')
-                    .attr(attr)
-                    .add(legendItemGroup);
-                // Draw the marker
-                if (markerOptions && markerOptions.enabled !== false && symbolWidth) {
-                    // Do not allow the marker to be larger than the symbolHeight
-                    radius = Math.min(pick(markerOptions.radius, generalRadius), generalRadius);
-                    // Restrict symbol markers size
-                    if (this.symbol.indexOf('url') === 0) {
-                        markerOptions = merge(markerOptions, {
-                            width: symbolHeight,
-                            height: symbolHeight
-                        });
-                        radius = 0;
-                    }
-                    this.legendSymbol = legendSymbol = renderer.symbol(this.symbol, (symbolWidth / 2) - radius, verticalCenter - radius, 2 * radius, 2 * radius, markerOptions)
-                        .addClass('highcharts-point')
-                        .add(legendItemGroup);
-                    legendSymbol.isMarker = true;
-                }
-            }
-        };
-
-        return LegendSymbolMixin;
-    });
-    _registerModule(_modules, 'Core/Series/CartesianSeries.js', [_modules['Core/Animation/AnimationUtilities.js'], _modules['Core/Series/Series.js'], _modules['Core/Globals.js'], _modules['Mixins/LegendSymbol.js'], _modules['Core/Options.js'], _modules['Core/Series/Point.js'], _modules['Core/Renderer/SVG/SVGElement.js'], _modules['Core/Utilities.js']], function (A, BaseSeries, H, LegendSymbolMixin, O, Point, SVGElement, U) {
-        /* *
-         *
-         *  (c) 2010-2020 Torstein Honsi
-         *
-         *  License: www.highcharts.com/license
-         *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
-         *
-         * */
-        var animObject = A.animObject;
-        var defaultOptions = O.defaultOptions;
-        var addEvent = U.addEvent,
-            arrayMax = U.arrayMax,
-            arrayMin = U.arrayMin,
-            clamp = U.clamp,
-            correctFloat = U.correctFloat,
-            defined = U.defined,
-            erase = U.erase,
-            error = U.error,
-            extend = U.extend,
-            find = U.find,
-            fireEvent = U.fireEvent,
-            getNestedProperty = U.getNestedProperty,
-            isArray = U.isArray,
-            isFunction = U.isFunction,
-            isNumber = U.isNumber,
-            isString = U.isString,
-            merge = U.merge,
-            objectEach = U.objectEach,
-            pick = U.pick,
-            removeEvent = U.removeEvent,
-            splat = U.splat,
-            syncTimeout = U.syncTimeout;
-        /**
-         * This is a placeholder type of the possible series options for
-         * [Highcharts](../highcharts/series), [Highstock](../highstock/series),
-         * [Highmaps](../highmaps/series), and [Gantt](../gantt/series).
-         *
-         * In TypeScript is this dynamically generated to reference all possible types
-         * of series options.
-         *
-         * @ignore-declaration
-         * @typedef {Highcharts.SeriesOptions|Highcharts.Dictionary<*>} Highcharts.SeriesOptionsType
-         */
-        /**
-         * Options for `dataSorting`.
-         *
-         * @interface Highcharts.DataSortingOptionsObject
-         * @since 8.0.0
-         */ /**
-        * Enable or disable data sorting for the series.
-        * @name Highcharts.DataSortingOptionsObject#enabled
-        * @type {boolean|undefined}
-        */ /**
-        * Whether to allow matching points by name in an update.
-        * @name Highcharts.DataSortingOptionsObject#matchByName
-        * @type {boolean|undefined}
-        */ /**
-        * Determines what data value should be used to sort by.
-        * @name Highcharts.DataSortingOptionsObject#sortKey
-        * @type {string|undefined}
-        */
-        /**
-         * Function callback when a series has been animated.
-         *
-         * @callback Highcharts.SeriesAfterAnimateCallbackFunction
-         *
-         * @param {Highcharts.Series} this
-         *        The series where the event occured.
-         *
-         * @param {Highcharts.SeriesAfterAnimateEventObject} event
-         *        Event arguments.
-         */
-        /**
-         * Event information regarding completed animation of a series.
-         *
-         * @interface Highcharts.SeriesAfterAnimateEventObject
-         */ /**
-        * Animated series.
-        * @name Highcharts.SeriesAfterAnimateEventObject#target
-        * @type {Highcharts.Series}
-        */ /**
-        * Event type.
-        * @name Highcharts.SeriesAfterAnimateEventObject#type
-        * @type {"afterAnimate"}
-        */
-        /**
-         * Function callback when the checkbox next to the series' name in the legend is
-         * clicked.
-         *
-         * @callback Highcharts.SeriesCheckboxClickCallbackFunction
-         *
-         * @param {Highcharts.Series} this
-         *        The series where the event occured.
-         *
-         * @param {Highcharts.SeriesCheckboxClickEventObject} event
-         *        Event arguments.
-         */
-        /**
-         * Event information regarding check of a series box.
-         *
-         * @interface Highcharts.SeriesCheckboxClickEventObject
-         */ /**
-        * Whether the box has been checked.
-        * @name Highcharts.SeriesCheckboxClickEventObject#checked
-        * @type {boolean}
-        */ /**
-        * Related series.
-        * @name Highcharts.SeriesCheckboxClickEventObject#item
-        * @type {Highcharts.Series}
-        */ /**
-        * Related series.
-        * @name Highcharts.SeriesCheckboxClickEventObject#target
-        * @type {Highcharts.Series}
-        */ /**
-        * Event type.
-        * @name Highcharts.SeriesCheckboxClickEventObject#type
-        * @type {"checkboxClick"}
-        */
-        /**
-         * Function callback when a series is clicked. Return false to cancel toogle
-         * actions.
-         *
-         * @callback Highcharts.SeriesClickCallbackFunction
-         *
-         * @param {Highcharts.Series} this
-         *        The series where the event occured.
-         *
-         * @param {Highcharts.SeriesClickEventObject} event
-         *        Event arguments.
-         */
-        /**
-         * Common information for a click event on a series.
-         *
-         * @interface Highcharts.SeriesClickEventObject
-         * @extends global.Event
-         */ /**
-        * Nearest point on the graph.
-        * @name Highcharts.SeriesClickEventObject#point
-        * @type {Highcharts.Point}
-        */
-        /**
-         * Gets fired when the series is hidden after chart generation time, either by
-         * clicking the legend item or by calling `.hide()`.
-         *
-         * @callback Highcharts.SeriesHideCallbackFunction
-         *
-         * @param {Highcharts.Series} this
-         *        The series where the event occured.
-         *
-         * @param {global.Event} event
-         *        The event that occured.
-         */
-        /**
-         * The SVG value used for the `stroke-linecap` and `stroke-linejoin` of a line
-         * graph.
-         *
-         * @typedef {"butt"|"round"|"square"|string} Highcharts.SeriesLinecapValue
-         */
-        /**
-         * Gets fired when the legend item belonging to the series is clicked. The
-         * default action is to toggle the visibility of the series. This can be
-         * prevented by returning `false` or calling `event.preventDefault()`.
-         *
-         * @callback Highcharts.SeriesLegendItemClickCallbackFunction
-         *
-         * @param {Highcharts.Series} this
-         *        The series where the event occured.
-         *
-         * @param {Highcharts.SeriesLegendItemClickEventObject} event
-         *        The event that occured.
-         */
-        /**
-         * Information about the event.
-         *
-         * @interface Highcharts.SeriesLegendItemClickEventObject
-         */ /**
-        * Related browser event.
-        * @name Highcharts.SeriesLegendItemClickEventObject#browserEvent
-        * @type {global.PointerEvent}
-        */ /**
-        * Prevent the default action of toggle the visibility of the series.
-        * @name Highcharts.SeriesLegendItemClickEventObject#preventDefault
-        * @type {Function}
-        */ /**
-        * Related series.
-        * @name Highcharts.SeriesCheckboxClickEventObject#target
-        * @type {Highcharts.Series}
-        */ /**
-        * Event type.
-        * @name Highcharts.SeriesCheckboxClickEventObject#type
-        * @type {"checkboxClick"}
-        */
-        /**
-         * Gets fired when the mouse leaves the graph.
-         *
-         * @callback Highcharts.SeriesMouseOutCallbackFunction
-         *
-         * @param {Highcharts.Series} this
-         *        Series where the event occured.
-         *
-         * @param {global.PointerEvent} event
-         *        Event that occured.
-         */
-        /**
-         * Gets fired when the mouse enters the graph.
-         *
-         * @callback Highcharts.SeriesMouseOverCallbackFunction
-         *
-         * @param {Highcharts.Series} this
-         *        Series where the event occured.
-         *
-         * @param {global.PointerEvent} event
-         *        Event that occured.
-         */
-        /**
-         * Translation and scale for the plot area of a series.
-         *
-         * @interface Highcharts.SeriesPlotBoxObject
-         */ /**
-        * @name Highcharts.SeriesPlotBoxObject#scaleX
-        * @type {number}
-        */ /**
-        * @name Highcharts.SeriesPlotBoxObject#scaleY
-        * @type {number}
-        */ /**
-        * @name Highcharts.SeriesPlotBoxObject#translateX
-        * @type {number}
-        */ /**
-        * @name Highcharts.SeriesPlotBoxObject#translateY
-        * @type {number}
-        */
-        /**
-         * Gets fired when the series is shown after chart generation time, either by
-         * clicking the legend item or by calling `.show()`.
-         *
-         * @callback Highcharts.SeriesShowCallbackFunction
-         *
-         * @param {Highcharts.Series} this
-         *        Series where the event occured.
-         *
-         * @param {global.Event} event
-         *        Event that occured.
-         */
-        /**
-         * Possible key values for the series state options.
-         *
-         * @typedef {"hover"|"inactive"|"normal"|"select"} Highcharts.SeriesStateValue
-         */
-        ''; // detach doclets above
-        var seriesTypes = BaseSeries.seriesTypes,
-            win = H.win;
-        /**
-         * This is the base series prototype that all other series types inherit from.
-         * A new series is initialized either through the
-         * [series](https://api.highcharts.com/highcharts/series)
-         * option structure, or after the chart is initialized, through
-         * {@link Highcharts.Chart#addSeries}.
-         *
-         * The object can be accessed in a number of ways. All series and point event
-         * handlers give a reference to the `series` object. The chart object has a
-         * {@link Highcharts.Chart#series|series} property that is a collection of all
-         * the chart's series. The point objects and axis objects also have the same
-         * reference.
-         *
-         * Another way to reference the series programmatically is by `id`. Add an id
-         * in the series configuration options, and get the series object by
-         * {@link Highcharts.Chart#get}.
-         *
-         * Configuration options for the series are given in three levels. Options for
-         * all series in a chart are given in the
-         * [plotOptions.series](https://api.highcharts.com/highcharts/plotOptions.series)
-         * object. Then options for all series of a specific type
-         * are given in the plotOptions of that type, for example `plotOptions.line`.
-         * Next, options for one single series are given in the series array, or as
-         * arguments to `chart.addSeries`.
-         *
-         * The data in the series is stored in various arrays.
-         *
-         * - First, `series.options.data` contains all the original config options for
-         *   each point whether added by options or methods like `series.addPoint`.
-         *
-         * - Next, `series.data` contains those values converted to points, but in case
-         *   the series data length exceeds the `cropThreshold`, or if the data is
-         *   grouped, `series.data` doesn't contain all the points. It only contains the
-         *   points that have been created on demand.
-         *
-         * - Then there's `series.points` that contains all currently visible point
-         *   objects. In case of cropping, the cropped-away points are not part of this
-         *   array. The `series.points` array starts at `series.cropStart` compared to
-         *   `series.data` and `series.options.data`. If however the series data is
-         *   grouped, these can't be correlated one to one.
-         *
-         * - `series.xData` and `series.processedXData` contain clean x values,
-         *   equivalent to `series.data` and `series.points`.
-         *
-         * - `series.yData` and `series.processedYData` contain clean y values,
-         *   equivalent to `series.data` and `series.points`.
-         *
-         * @class
-         * @name Highcharts.Series
-         *
-         * @param {Highcharts.Chart} chart
-         *        The chart instance.
-         *
-         * @param {Highcharts.SeriesOptionsType|object} options
-         *        The series options.
-         */ /**
-        * The line series is the base type and is therefor the series base prototype.
-        *
-        * @private
-        * @class
-        * @name Highcharts.seriesTypes.line
-        *
-        * @augments Highcharts.Series
-        */
-        var CartesianSeries = BaseSeries.seriesType('line', 
-            /**
-             * Series options for specific data and the data itself. In TypeScript you
-             * have to cast the series options to specific series types,
-            to get all
-             * possible options for a series.
-             *
-             * @example
-             * // TypeScript example
-             * Highcharts.chart('container', {
-             *     series: [{
-             *         color: '#06C',
-             *         data: [[0, 1],
-            [2, 3]]
-             *     } as Highcharts.SeriesLineOptions ]
-             * });
-         *
-         * @type      {Array<*>}
-         * @apioption series
-         */
-        /**
-         * An id for the series. This can be used after render time to get a pointer
-         * to the series object through `chart.get()`.
-         *
-         * @sample {highcharts} highcharts/plotoptions/series-id/
-         *         Get series by id
-         *
-         * @type      {string}
-         * @since     1.2.0
-         * @apioption series.id
-         */
-        /**
-         * The index of the series in the chart, affecting the internal index in the
-         * `chart.series` array, the visible Z index as well as the order in the
-         * legend.
-         *
-         * @type      {number}
-         * @since     2.3.0
-         * @apioption series.index
-         */
-        /**
-         * The sequential index of the series in the legend.
-         *
-         * @see [legend.reversed](#legend.reversed),
-         *      [yAxis.reversedStacks](#yAxis.reversedStacks)
-         *
-         * @sample {highcharts|highstock} highcharts/series/legendindex/
-         *         Legend in opposite order
-         *
-         * @type      {number}
-         * @apioption series.legendIndex
-         */
-        /**
-         * The name of the series as shown in the legend, tooltip etc.
-         *
-         * @sample {highcharts} highcharts/series/name/
-         *         Series name
-         * @sample {highmaps} maps/demo/category-map/
-         *         Series name
-         *
-         * @type      {string}
-         * @apioption series.name
-         */
-        /**
-         * This option allows grouping series in a stacked chart. The stack option
-         * can be a string or anything else, as long as the grouped series' stack
-         * options match each other after conversion into a string.
-         *
-         * @sample {highcharts} highcharts/series/stack/
-         *         Stacked and grouped columns
-         *
-         * @type      {number|string}
-         * @since     2.1
-         * @product   highcharts highstock
-         * @apioption series.stack
-         */
-        /**
-         * The type of series, for example `line` or `column`. By default, the
-         * series type is inherited from [chart.type](#chart.type), so unless the
-         * chart is a combination of series types, there is no need to set it on the
-         * series level.
-         *
-         * @sample {highcharts} highcharts/series/type/
-         *         Line and column in the same chart
-         * @sample highcharts/series/type-dynamic/
-         *         Dynamic types with button selector
-         * @sample {highmaps} maps/demo/mapline-mappoint/
-         *         Multiple types in the same map
-         *
-         * @type      {string}
-         * @apioption series.type
-         */
-        /**
-         * When using dual or multiple x axes, this number defines which xAxis the
-         * particular series is connected to. It refers to either the
-         * {@link #xAxis.id|axis id}
-         * or the index of the axis in the xAxis array, with 0 being the first.
-         *
-         * @type      {number|string}
-         * @default   0
-         * @product   highcharts highstock
-         * @apioption series.xAxis
-         */
-        /**
-         * When using dual or multiple y axes, this number defines which yAxis the
-         * particular series is connected to. It refers to either the
-         * {@link #yAxis.id|axis id}
-         * or the index of the axis in the yAxis array, with 0 being the first.
-         *
-         * @sample {highcharts} highcharts/series/yaxis/
-         *         Apply the column series to the secondary Y axis
-         *
-         * @type      {number|string}
-         * @default   0
-         * @product   highcharts highstock
-         * @apioption series.yAxis
-         */
-        /**
-         * Define the visual z index of the series.
-         *
-         * @sample {highcharts} highcharts/plotoptions/series-zindex-default/
-         *         With no z index, the series defined last are on top
-         * @sample {highcharts} highcharts/plotoptions/series-zindex/
-         *         With a z index, the series with the highest z index is on top
-         * @sample {highstock} highcharts/plotoptions/series-zindex-default/
-         *         With no z index, the series defined last are on top
-         * @sample {highstock} highcharts/plotoptions/series-zindex/
-         *         With a z index, the series with the highest z index is on top
-         *
-         * @type      {number}
-         * @product   highcharts highstock
-         * @apioption series.zIndex
-         */
-        void 0, 
-        /**
-         * General options for all series types.
-         *
-         * @optionparent plotOptions.series
-         */
-        {
-            /**
-             * The SVG value used for the `stroke-linecap` and `stroke-linejoin`
-             * of a line graph. Round means that lines are rounded in the ends and
-             * bends.
-             *
-             * @type       {Highcharts.SeriesLinecapValue}
-             * @default    round
-             * @since      3.0.7
-             * @apioption  plotOptions.line.linecap
-             */
-            /**
-             * Pixel width of the graph line.
-             *
-             * @see In styled mode, the line stroke-width can be set with the
-             *      `.highcharts-graph` class name.
-             *
-             * @sample {highcharts} highcharts/plotoptions/series-linewidth-general/
-             *         On all series
-             * @sample {highcharts} highcharts/plotoptions/series-linewidth-specific/
-             *         On one single series
-             *
-             * @product highcharts highstock
-             *
-             * @private
-             */
-            lineWidth: 2,
-            /**
-             * For some series, there is a limit that shuts down initial animation
-             * by default when the total number of points in the chart is too high.
-             * For example, for a column chart and its derivatives, animation does
-             * not run if there is more than 250 points totally. To disable this
-             * cap, set `animationLimit` to `Infinity`.
-             *
-             * @type      {number}
-             * @apioption plotOptions.series.animationLimit
-             */
-            /**
-             * Allow this series' points to be selected by clicking on the graphic
-             * (columns, point markers, pie slices, map areas etc).
-             *
-             * The selected points can be handled by point select and unselect
-             * events, or collectively by the [getSelectedPoints
-             * ](/class-reference/Highcharts.Chart#getSelectedPoints) function.
-             *
-             * And alternative way of selecting points is through dragging.
-             *
-             * @sample {highcharts} highcharts/plotoptions/series-allowpointselect-line/
-             *         Line
-             * @sample {highcharts} highcharts/plotoptions/series-allowpointselect-column/
-             *         Column
-             * @sample {highcharts} highcharts/plotoptions/series-allowpointselect-pie/
-             *         Pie
-             * @sample {highcharts} highcharts/chart/events-selection-points/
-             *         Select a range of points through a drag selection
-             * @sample {highmaps} maps/plotoptions/series-allowpointselect/
-             *         Map area
-             * @sample {highmaps} maps/plotoptions/mapbubble-allowpointselect/
-             *         Map bubble
-             *
-             * @since 1.2.0
-             *
-             * @private
-             */
-            allowPointSelect: false,
-            /**
-             * When true, each point or column edge is rounded to its nearest pixel
-             * in order to render sharp on screen. In some cases, when there are a
-             * lot of densely packed columns, this leads to visible difference
-             * in column widths or distance between columns. In these cases,
-             * setting `crisp` to `false` may look better, even though each column
-             * is rendered blurry.
-             *
-             * @sample {highcharts} highcharts/plotoptions/column-crisp-false/
-             *         Crisp is false
-             *
-             * @since   5.0.10
-             * @product highcharts highstock gantt
-             *
-             * @private
-             */
-            crisp: true,
-            /**
-             * If true, a checkbox is displayed next to the legend item to allow
-             * selecting the series. The state of the checkbox is determined by
-             * the `selected` option.
-             *
-             * @productdesc {highmaps}
-             * Note that if a `colorAxis` is defined, the color axis is represented
-             * in the legend, not the series.
-             *
-             * @sample {highcharts} highcharts/plotoptions/series-showcheckbox-true/
-             *         Show select box
-             *
-             * @since 1.2.0
-             *
-             * @private
-             */
-            showCheckbox: false,
-            /**
-             * Enable or disable the initial animation when a series is displayed.
-             * The animation can also be set as a configuration object. Please
-             * note that this option only applies to the initial animation of the
-             * series itself. For other animations, see [chart.animation](
-             * #chart.animation) and the animation parameter under the API methods.
-             * The following properties are supported:
-             *
-             * - `defer`: The animation delay time in milliseconds.
-             *
-             * - `duration`: The duration of the animation in milliseconds.
-             *
-             * - `easing`: Can be a string reference to an easing function set on
-             *   the `Math` object or a function. See the _Custom easing function_
-             *   demo below.
-             *
-             * Due to poor performance, animation is disabled in old IE browsers
-             * for several chart types.
-             *
-             * @sample {highcharts} highcharts/plotoptions/series-animation-disabled/
-             *         Animation disabled
-             * @sample {highcharts} highcharts/plotoptions/series-animation-slower/
-             *         Slower animation
-             * @sample {highcharts} highcharts/plotoptions/series-animation-easing/
-             *         Custom easing function
-             * @sample {highstock} stock/plotoptions/animation-slower/
-             *         Slower animation
-             * @sample {highstock} stock/plotoptions/animation-easing/
-             *         Custom easing function
-             * @sample {highmaps} maps/plotoptions/series-animation-true/
-             *         Animation enabled on map series
-             * @sample {highmaps} maps/plotoptions/mapbubble-animation-false/
-             *         Disabled on mapbubble series
-             *
-             * @type    {boolean|Partial<Highcharts.AnimationOptionsObject>}
-             * @default {highcharts} true
-             * @default {highstock} true
-             * @default {highmaps} false
-             *
-             * @private
-             */
-            animation: {
-                /** @internal */
-                duration: 1000
-            },
-            /**
-             * @default   0
-             * @type      {number}
-             * @since     8.2.0
-             * @apioption plotOptions.series.animation.defer
-             */
-            /**
-             * An additional class name to apply to the series' graphical elements.
-             * This option does not replace default class names of the graphical
-             * element.
-             *
-             * @type      {string}
-             * @since     5.0.0
-             * @apioption plotOptions.series.className
-             */
-            /**
-             * Disable this option to allow series rendering in the whole plotting
-             * area.
-             *
-             * **Note:** Clipping should be always enabled when
-             * [chart.zoomType](#chart.zoomType) is set
-             *
-             * @sample {highcharts} highcharts/plotoptions/series-clip/
-             *         Disabled clipping
-             *
-             * @default   true
-             * @type      {boolean}
-             * @since     3.0.0
-             * @apioption plotOptions.series.clip
-             */
-            /**
-             * The main color of the series. In line type series it applies to the
-             * line and the point markers unless otherwise specified. In bar type
-             * series it applies to the bars unless a color is specified per point.
-             * The default value is pulled from the `options.colors` array.
-             *
-             * In styled mode, the color can be defined by the
-             * [colorIndex](#plotOptions.series.colorIndex) option. Also, the series
-             * color can be set with the `.highcharts-series`,
-             * `.highcharts-color-{n}`, `.highcharts-{type}-series` or
-             * `.highcharts-series-{n}` class, or individual classes given by the
-             * `className` option.
-             *
-             * @productdesc {highmaps}
-             * In maps, the series color is rarely used, as most choropleth maps use
-             * the color to denote the value of each point. The series color can
-             * however be used in a map with multiple series holding categorized
-             * data.
-             *
-             * @sample {highcharts} highcharts/plotoptions/series-color-general/
-             *         General plot option
-             * @sample {highcharts} highcharts/plotoptions/series-color-specific/
-             *         One specific series
-             * @sample {highcharts} highcharts/plotoptions/series-color-area/
-             *         Area color
-             * @sample {highcharts} highcharts/series/infographic/
-             *         Pattern fill
-             * @sample {highmaps} maps/demo/category-map/
-             *         Category map by multiple series
-             *
-             * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-             * @apioption plotOptions.series.color
-             */
-            /**
-             * Styled mode only. A specific color index to use for the series, so
-             * its graphic representations are given the class name
-             * `highcharts-color-{n}`.
-             *
-             * @type      {number}
-             * @since     5.0.0
-             * @apioption plotOptions.series.colorIndex
-             */
-            /**
-             * Whether to connect a graph line across null points, or render a gap
-             * between the two points on either side of the null.
-             *
-             * @sample {highcharts} highcharts/plotoptions/series-connectnulls-false/
-             *         False by default
-             * @sample {highcharts} highcharts/plotoptions/series-connectnulls-true/
-             *         True
-             *
-             * @type      {boolean}
-             * @default   false
-             * @product   highcharts highstock
-             * @apioption plotOptions.series.connectNulls
-             */
-            /**
-             * You can set the cursor to "pointer" if you have click events attached
-             * to the series, to signal to the user that the points and lines can
-             * be clicked.
-             *
-             * In styled mode, the series cursor can be set with the same classes
-             * as listed under [series.color](#plotOptions.series.color).
-             *
-             * @sample {highcharts} highcharts/plotoptions/series-cursor-line/
-             *         On line graph
-             * @sample {highcharts} highcharts/plotoptions/series-cursor-column/
-             *         On columns
-             * @sample {highcharts} highcharts/plotoptions/series-cursor-scatter/
-             *         On scatter markers
-             * @sample {highstock} stock/plotoptions/cursor/
-             *         Pointer on a line graph
-             * @sample {highmaps} maps/plotoptions/series-allowpointselect/
-             *         Map area
-             * @sample {highmaps} maps/plotoptions/mapbubble-allowpointselect/
-             *         Map bubble
-             *
-             * @type      {string|Highcharts.CursorValue}
-             * @apioption plotOptions.series.cursor
-             */
-            /**
-             * A reserved subspace to store options and values for customized
-             * functionality. Here you can add additional data for your own event
-             * callbacks and formatter callbacks.
-             *
-             * @sample {highcharts} highcharts/point/custom/
-             *         Point and series with custom data
-             *
-             * @type      {Highcharts.Dictionary<*>}
-             * @apioption plotOptions.series.custom
-             */
-            /**
-             * Name of the dash style to use for the graph, or for some series types
-             * the outline of each shape.
-             *
-             * In styled mode, the
-             * [stroke dash-array](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/css/series-dashstyle/)
-             * can be set with the same classes as listed under
-             * [series.color](#plotOptions.series.color).
-             *
-             * @sample {highcharts} highcharts/plotoptions/series-dashstyle-all/
-             *         Possible values demonstrated
-             * @sample {highcharts} highcharts/plotoptions/series-dashstyle/
-             *         Chart suitable for printing in black and white
-             * @sample {highstock} highcharts/plotoptions/series-dashstyle-all/
-             *         Possible values demonstrated
-             * @sample {highmaps} highcharts/plotoptions/series-dashstyle-all/
-             *         Possible values demonstrated
-             * @sample {highmaps} maps/plotoptions/series-dashstyle/
-             *         Dotted borders on a map
-             *
-             * @type      {Highcharts.DashStyleValue}
-             * @default   Solid
-             * @since     2.1
-             * @apioption plotOptions.series.dashStyle
-             */
-            /**
-             * A description of the series to add to the screen reader information
-             * about the series.
-             *
-             * @type      {string}
-             * @since     5.0.0
-             * @requires  modules/accessibility
-             * @apioption plotOptions.series.description
-             */
-            /**
-             * Options for the series data sorting.
-             *
-             * @type      {Highcharts.DataSortingOptionsObject}
-             * @since     8.0.0
-             * @product   highcharts highstock
-             * @apioption plotOptions.series.dataSorting
-             */
-            /**
-             * Enable or disable data sorting for the series. Use [xAxis.reversed](
-             * #xAxis.reversed) to change the sorting order.
-             *
-             * @sample {highcharts} highcharts/datasorting/animation/
-             *         Data sorting in scatter-3d
-             * @sample {highcharts} highcharts/datasorting/labels-animation/
-             *         Axis labels animation
-             * @sample {highcharts} highcharts/datasorting/dependent-sorting/
-             *         Dependent series sorting
-             * @sample {highcharts} highcharts/datasorting/independent-sorting/
-             *         Independent series sorting
-             *
-             * @type      {boolean}
-             * @since     8.0.0
-             * @apioption plotOptions.series.dataSorting.enabled
-             */
-            /**
-             * Whether to allow matching points by name in an update. If this option
-             * is disabled, points will be matched by order.
-             *
-             * @sample {highcharts} highcharts/datasorting/match-by-name/
-             *         Enabled match by name
-             *
-             * @type      {boolean}
-             * @since     8.0.0
-             * @apioption plotOptions.series.dataSorting.matchByName
-             */
-            /**
-             * Determines what data value should be used to sort by.
-             *
-             * @sample {highcharts} highcharts/datasorting/sort-key/
-             *         Sort key as `z` value
-             *
-             * @type      {string}
-             * @since     8.0.0
-             * @default   y
-             * @apioption plotOptions.series.dataSorting.sortKey
-             */
-            /**
-             * Enable or disable the mouse tracking for a specific series. This
-             * includes point tooltips and click events on graphs and points. For
-             * large datasets it improves performance.
-             *
-             * @sample {highcharts} highcharts/plotoptions/series-enablemousetracking-false/
-             *         No mouse tracking
-             * @sample {highmaps} maps/plotoptions/series-enablemousetracking-false/
-             *         No mouse tracking
-             *
-             * @type      {boolean}
-             * @default   true
-             * @apioption plotOptions.series.enableMouseTracking
-             */
-            /**
-             * Whether to use the Y extremes of the total chart width or only the
-             * zoomed area when zooming in on parts of the X axis. By default, the
-             * Y axis adjusts to the min and max of the visible data. Cartesian
-             * series only.
-             *
-             * @type      {boolean}
-             * @default   false
-             * @since     4.1.6
-             * @product   highcharts highstock gantt
-             * @apioption plotOptions.series.getExtremesFromAll
-             */
-            /**
-             * An array specifying which option maps to which key in the data point
-             * array. This makes it convenient to work with unstructured data arrays
-             * from different sources.
-             *
-             * @see [series.data](#series.line.data)
-             *
-             * @sample {highcharts|highstock} highcharts/series/data-keys/
-             *         An extended data array with keys
-             * @sample {highcharts|highstock} highcharts/series/data-nested-keys/
-             *         Nested keys used to access object properties
-             *
-             * @type      {Array<string>}
-             * @since     4.1.6
-             * @apioption plotOptions.series.keys
-             */
-            /**
-             * The line cap used for line ends and line joins on the graph.
-             *
-             * @type       {Highcharts.SeriesLinecapValue}
-             * @default    round
-             * @product    highcharts highstock
-             * @apioption  plotOptions.series.linecap
-             */
-            /**
-             * The [id](#series.id) of another series to link to. Additionally,
-             * the value can be ":previous" to link to the previous series. When
-             * two series are linked, only the first one appears in the legend.
-             * Toggling the visibility of this also toggles the linked series.
-             *
-             * If master series uses data sorting and linked series does not have
-             * its own sorting definition, the linked series will be sorted in the
-             * same order as the master one.
-             *
-             * @sample {highcharts|highstock} highcharts/demo/arearange-line/
-             *         Linked series
-             *
-             * @type      {string}
-             * @since     3.0
-             * @product   highcharts highstock gantt
-             * @apioption plotOptions.series.linkedTo
-             */
-            /**
-             * Options for the corresponding navigator series if `showInNavigator`
-             * is `true` for this series. Available options are the same as any
-             * series, documented at [plotOptions](#plotOptions.series) and
-             * [series](#series).
-             *
-             * These options are merged with options in [navigator.series](
-             * #navigator.series), and will take precedence if the same option is
-             * defined both places.
-             *
-             * @see [navigator.series](#navigator.series)
-             *
-             * @type      {Highcharts.PlotSeriesOptions}
-             * @since     5.0.0
-             * @product   highstock
-             * @apioption plotOptions.series.navigatorOptions
-             */
-            /**
-             * The color for the parts of the graph or points that are below the
-             * [threshold](#plotOptions.series.threshold). Note that `zones` takes
-             * precedence over the negative color. Using `negativeColor` is
-             * equivalent to applying a zone with value of 0.
-             *
-             * @see In styled mode, a negative color is applied by setting this option
-             *      to `true` combined with the `.highcharts-negative` class name.
-             *
-             * @sample {highcharts} highcharts/plotoptions/series-negative-color/
-             *         Spline, area and column
-             * @sample {highcharts} highcharts/plotoptions/arearange-negativecolor/
-             *         Arearange
-             * @sample {highcharts} highcharts/css/series-negative-color/
-             *         Styled mode
-             * @sample {highstock} highcharts/plotoptions/series-negative-color/
-             *         Spline, area and column
-             * @sample {highstock} highcharts/plotoptions/arearange-negativecolor/
-             *         Arearange
-             * @sample {highmaps} highcharts/plotoptions/series-negative-color/
-             *         Spline, area and column
-             * @sample {highmaps} highcharts/plotoptions/arearange-negativecolor/
-             *         Arearange
-             *
-             * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-             * @since     3.0
-             * @apioption plotOptions.series.negativeColor
-             */
-            /**
-             * Same as
-             * [accessibility.pointDescriptionFormatter](#accessibility.pointDescriptionFormatter),
-             * but for an individual series. Overrides the chart wide configuration.
-             *
-             * @type      {Function}
-             * @since     5.0.12
-             * @apioption plotOptions.series.pointDescriptionFormatter
-             */
-            /**
-             * If no x values are given for the points in a series, `pointInterval`
-             * defines the interval of the x values. For example, if a series
-             * contains one value every decade starting from year 0, set
-             * `pointInterval` to `10`. In true `datetime` axes, the `pointInterval`
-             * is set in milliseconds.
-             *
-             * It can be also be combined with `pointIntervalUnit` to draw irregular
-             * time intervals.
-             *
-             * Please note that this options applies to the _series data_, not the
-             * interval of the axis ticks, which is independent.
-             *
-             * @sample {highcharts} highcharts/plotoptions/series-pointstart-datetime/
-             *         Datetime X axis
-             * @sample {highstock} stock/plotoptions/pointinterval-pointstart/
-             *         Using pointStart and pointInterval
-             *
-             * @type      {number}
-             * @default   1
-             * @product   highcharts highstock gantt
-             * @apioption plotOptions.series.pointInterval
-             */
-            /**
-             * On datetime series, this allows for setting the
-             * [pointInterval](#plotOptions.series.pointInterval) to irregular time
-             * units, `day`, `month` and `year`. A day is usually the same as 24
-             * hours, but `pointIntervalUnit` also takes the DST crossover into
-             * consideration when dealing with local time. Combine this option with
-             * `pointInterval` to draw weeks, quarters, 6 months, 10 years etc.
-             *
-             * Please note that this options applies to the _series data_, not the
-             * interval of the axis ticks, which is independent.
-             *
-             * @sample {highcharts} highcharts/plotoptions/series-pointintervalunit/
-             *         One point a month
-             * @sample {highstock} highcharts/plotoptions/series-pointintervalunit/
-             *         One point a month
-             *
-             * @type       {string}
-             * @since      4.1.0
-             * @product    highcharts highstock gantt
-             * @validvalue ["day", "month", "year"]
-             * @apioption  plotOptions.series.pointIntervalUnit
-             */
-            /**
-             * Possible values: `"on"`, `"between"`, `number`.
-             *
-             * In a column chart, when pointPlacement is `"on"`, the point will not
-             * create any padding of the X axis. In a polar column chart this means
-             * that the first column points directly north. If the pointPlacement is
-             * `"between"`, the columns will be laid out between ticks. This is
-             * useful for example for visualising an amount between two points in
-             * time or in a certain sector of a polar chart.
-             *
-             * Since Highcharts 3.0.2, the point placement can also be numeric,
-             * where 0 is on the axis value, -0.5 is between this value and the
-             * previous, and 0.5 is between this value and the next. Unlike the
-             * textual options, numeric point placement options won't affect axis
-             * padding.
-             *
-             * Note that pointPlacement needs a [pointRange](
-             * #plotOptions.series.pointRange) to work. For column series this is
-             * computed, but for line-type series it needs to be set.
-             *
-             * For the `xrange` series type and gantt charts, if the Y axis is a
-             * category axis, the `pointPlacement` applies to the Y axis rather than
-             * the (typically datetime) X axis.
-             *
-             * Defaults to `undefined` in cartesian charts, `"between"` in polar
-             * charts.
-             *
-             * @see [xAxis.tickmarkPlacement](#xAxis.tickmarkPlacement)
-             *
-             * @sample {highcharts|highstock} highcharts/plotoptions/series-pointplacement-between/
-             *         Between in a column chart
-             * @sample {highcharts|highstock} highcharts/plotoptions/series-pointplacement-numeric/
-             *         Numeric placement for custom layout
-             * @sample {highcharts|highstock} maps/plotoptions/heatmap-pointplacement/
-             *         Placement in heatmap
-             *
-             * @type      {string|number}
-             * @since     2.3.0
-             * @product   highcharts highstock gantt
-             * @apioption plotOptions.series.pointPlacement
-             */
-            /**
-             * If no x values are given for the points in a series, pointStart
-             * defines on what value to start. For example, if a series contains one
-             * yearly value starting from 1945, set pointStart to 1945.
-             *
-             * @sample {highcharts} highcharts/plotoptions/series-pointstart-linear/
-             *         Linear
-             * @sample {highcharts} highcharts/plotoptions/series-pointstart-datetime/
-             *         Datetime
-             * @sample {highstock} stock/plotoptions/pointinterval-pointstart/
-             *         Using pointStart and pointInterval
-             *
-             * @type      {number}
-             * @default   0
-             * @product   highcharts highstock gantt
-             * @apioption plotOptions.series.pointStart
-             */
-            /**
-             * Whether to select the series initially. If `showCheckbox` is true,
-             * the checkbox next to the series name in the legend will be checked
-             * for a selected series.
-             *
-             * @sample {highcharts} highcharts/plotoptions/series-selected/
-             *         One out of two series selected
-             *
-             * @type      {boolean}
-             * @default   false
-             * @since     1.2.0
-             * @apioption plotOptions.series.selected
-             */
-            /**
-             * Whether to apply a drop shadow to the graph line. Since 2.3 the
-             * shadow can be an object configuration containing `color`, `offsetX`,
-             * `offsetY`, `opacity` and `width`.
-             *
-             * @sample {highcharts} highcharts/plotoptions/series-shadow/
-             *         Shadow enabled
-             *
-             * @type      {boolean|Highcharts.ShadowOptionsObject}
-             * @default   false
-             * @apioption plotOptions.series.shadow
-             */
-            /**
-             * Whether to display this particular series or series type in the
-             * legend. Standalone series are shown in legend by default, and linked
-             * series are not. Since v7.2.0 it is possible to show series that use
-             * colorAxis by setting this option to `true`.
-             *
-             * @sample {highcharts} highcharts/plotoptions/series-showinlegend/
-             *         One series in the legend, one hidden
-             *
-             * @type      {boolean}
-             * @apioption plotOptions.series.showInLegend
-             */
-            /**
-             * Whether or not to show the series in the navigator. Takes precedence
-             * over [navigator.baseSeries](#navigator.baseSeries) if defined.
-             *
-             * @type      {boolean}
-             * @since     5.0.0
-             * @product   highstock
-             * @apioption plotOptions.series.showInNavigator
-             */
-            /**
-             * If set to `true`, the accessibility module will skip past the points
-             * in this series for keyboard navigation.
-             *
-             * @type      {boolean}
-             * @since     5.0.12
-             * @apioption plotOptions.series.skipKeyboardNavigation
-             */
-            /**
-             * Whether to stack the values of each series on top of each other.
-             * Possible values are `undefined` to disable, `"normal"` to stack by
-             * value or `"percent"`.
-             *
-             * When stacking is enabled, data must be sorted
-             * in ascending X order.
-             *
-             * Some stacking options are related to specific series types. In the
-             * streamgraph series type, the stacking option is set to `"stream"`.
-             * The second one is `"overlap"`, which only applies to waterfall
-             * series.
-             *
-             * @see [yAxis.reversedStacks](#yAxis.reversedStacks)
-             *
-             * @sample {highcharts} highcharts/plotoptions/series-stacking-line/
-             *         Line
-             * @sample {highcharts} highcharts/plotoptions/series-stacking-column/
-             *         Column
-             * @sample {highcharts} highcharts/plotoptions/series-stacking-bar/
-             *         Bar
-             * @sample {highcharts} highcharts/plotoptions/series-stacking-area/
-             *         Area
-             * @sample {highcharts} highcharts/plotoptions/series-stacking-percent-line/
-             *         Line
-             * @sample {highcharts} highcharts/plotoptions/series-stacking-percent-column/
-             *         Column
-             * @sample {highcharts} highcharts/plotoptions/series-stacking-percent-bar/
-             *         Bar
-             * @sample {highcharts} highcharts/plotoptions/series-stacking-percent-area/
-             *         Area
-             * @sample {highcharts} highcharts/plotoptions/series-waterfall-with-normal-stacking
-             *         Waterfall with normal stacking
-             * @sample {highcharts} highcharts/plotoptions/series-waterfall-with-overlap-stacking
-             *         Waterfall with overlap stacking
-             * @sample {highstock} stock/plotoptions/stacking/
-             *         Area
-             *
-             * @type       {string}
-             * @product    highcharts highstock
-             * @validvalue ["normal", "overlap", "percent", "stream"]
-             * @apioption  plotOptions.series.stacking
-             */
-            /**
-             * Whether to apply steps to the line. Possible values are `left`,
-             * `center` and `right`.
-             *
-             * @sample {highcharts} highcharts/plotoptions/line-step/
-             *         Different step line options
-             * @sample {highcharts} highcharts/plotoptions/area-step/
-             *         Stepped, stacked area
-             * @sample {highstock} stock/plotoptions/line-step/
-             *         Step line
-             *
-             * @type       {string}
-             * @since      1.2.5
-             * @product    highcharts highstock
-             * @validvalue ["left", "center", "right"]
-             * @apioption  plotOptions.series.step
-             */
-            /**
-             * The threshold, also called zero level or base level. For line type
-             * series this is only used in conjunction with
-             * [negativeColor](#plotOptions.series.negativeColor).
-             *
-             * @see [softThreshold](#plotOptions.series.softThreshold).
-             *
-             * @type      {number}
-             * @default   0
-             * @since     3.0
-             * @product   highcharts highstock
-             * @apioption plotOptions.series.threshold
-             */
-            /**
-             * Set the initial visibility of the series.
-             *
-             * @sample {highcharts} highcharts/plotoptions/series-visible/
-             *         Two series, one hidden and one visible
-             * @sample {highstock} stock/plotoptions/series-visibility/
-             *         Hidden series
-             *
-             * @type      {boolean}
-             * @default   true
-             * @apioption plotOptions.series.visible
-             */
-            /**
-             * Defines the Axis on which the zones are applied.
-             *
-             * @see [zones](#plotOptions.series.zones)
-             *
-             * @sample {highcharts} highcharts/series/color-zones-zoneaxis-x/
-             *         Zones on the X-Axis
-             * @sample {highstock} highcharts/series/color-zones-zoneaxis-x/
-             *         Zones on the X-Axis
-             *
-             * @type      {string}
-             * @default   y
-             * @since     4.1.0
-             * @product   highcharts highstock
-             * @apioption plotOptions.series.zoneAxis
-             */
-            /**
-             * General event handlers for the series items. These event hooks can
-             * also be attached to the series at run time using the
-             * `Highcharts.addEvent` function.
-             *
-             * @declare Highcharts.SeriesEventsOptionsObject
-             *
-             * @private
-             */
-            events: {},
-            /**
-             * Fires after the series has finished its initial animation, or in case
-             * animation is disabled, immediately as the series is displayed.
-             *
-             * @sample {highcharts} highcharts/plotoptions/series-events-afteranimate/
-             *         Show label after animate
-             * @sample {highstock} highcharts/plotoptions/series-events-afteranimate/
-             *         Show label after animate
-             *
-             * @type      {Highcharts.SeriesAfterAnimateCallbackFunction}
-             * @since     4.0
-             * @product   highcharts highstock gantt
-             * @context   Highcharts.Series
-             * @apioption plotOptions.series.events.afterAnimate
-             */
-            /**
-             * Fires when the checkbox next to the series' name in the legend is
-             * clicked. One parameter, `event`, is passed to the function. The state
-             * of the checkbox is found by `event.checked`. The checked item is
-             * found by `event.item`. Return `false` to prevent the default action
-             * which is to toggle the select state of the series.
-             *
-             * @sample {highcharts} highcharts/plotoptions/series-events-checkboxclick/
-             *         Alert checkbox status
-             *
-             * @type      {Highcharts.SeriesCheckboxClickCallbackFunction}
-             * @since     1.2.0
-             * @context   Highcharts.Series
-             * @apioption plotOptions.series.events.checkboxClick
-             */
-            /**
-             * Fires when the series is clicked. One parameter, `event`, is passed
-             * to the function, containing common event information. Additionally,
-             * `event.point` holds a pointer to the nearest point on the graph.
-             *
-             * @sample {highcharts} highcharts/plotoptions/series-events-click/
-             *         Alert click info
-             * @sample {highstock} stock/plotoptions/series-events-click/
-             *         Alert click info
-             * @sample {highmaps} maps/plotoptions/series-events-click/
-             *         Display click info in subtitle
-             *
-             * @type      {Highcharts.SeriesClickCallbackFunction}
-             * @context   Highcharts.Series
-             * @apioption plotOptions.series.events.click
-             */
-            /**
-             * Fires when the series is hidden after chart generation time, either
-             * by clicking the legend item or by calling `.hide()`.
-             *
-             * @sample {highcharts} highcharts/plotoptions/series-events-hide/
-             *         Alert when the series is hidden by clicking the legend item
-             *
-             * @type      {Highcharts.SeriesHideCallbackFunction}
-             * @since     1.2.0
-             * @context   Highcharts.Series
-             * @apioption plotOptions.series.events.hide
-             */
-            /**
-             * Fires when the legend item belonging to the series is clicked. One
-             * parameter, `event`, is passed to the function. The default action
-             * is to toggle the visibility of the series. This can be prevented
-             * by returning `false` or calling `event.preventDefault()`.
-             *
-             * @sample {highcharts} highcharts/plotoptions/series-events-legenditemclick/
-             *         Confirm hiding and showing
-             *
-             * @type      {Highcharts.SeriesLegendItemClickCallbackFunction}
-             * @context   Highcharts.Series
-             * @apioption plotOptions.series.events.legendItemClick
-             */
-            /**
-             * Fires when the mouse leaves the graph. One parameter, `event`, is
-             * passed to the function, containing common event information. If the
-             * [stickyTracking](#plotOptions.series) option is true, `mouseOut`
-             * doesn't happen before the mouse enters another graph or leaves the
-             * plot area.
-             *
-             * @sample {highcharts} highcharts/plotoptions/series-events-mouseover-sticky/
-             *         With sticky tracking by default
-             * @sample {highcharts} highcharts/plotoptions/series-events-mouseover-no-sticky/
-             *         Without sticky tracking
-             *
-             * @type      {Highcharts.SeriesMouseOutCallbackFunction}
-             * @context   Highcharts.Series
-             * @apioption plotOptions.series.events.mouseOut
-             */
-            /**
-             * Fires when the mouse enters the graph. One parameter, `event`, is
-             * passed to the function, containing common event information.
-             *
-             * @sample {highcharts} highcharts/plotoptions/series-events-mouseover-sticky/
-             *         With sticky tracking by default
-             * @sample {highcharts} highcharts/plotoptions/series-events-mouseover-no-sticky/
-             *         Without sticky tracking
-             *
-             * @type      {Highcharts.SeriesMouseOverCallbackFunction}
-             * @context   Highcharts.Series
-             * @apioption plotOptions.series.events.mouseOver
-             */
-            /**
-             * Fires when the series is shown after chart generation time, either
-             * by clicking the legend item or by calling `.show()`.
-             *
-             * @sample {highcharts} highcharts/plotoptions/series-events-show/
-             *         Alert when the series is shown by clicking the legend item.
-             *
-             * @type      {Highcharts.SeriesShowCallbackFunction}
-             * @since     1.2.0
-             * @context   Highcharts.Series
-             * @apioption plotOptions.series.events.show
-             */
-            /**
-             * Options for the point markers of line-like series. Properties like
-             * `fillColor`, `lineColor` and `lineWidth` define the visual appearance
-             * of the markers. Other series types, like column series, don't have
-             * markers, but have visual options on the series level instead.
-             *
-             * In styled mode, the markers can be styled with the
-             * `.highcharts-point`, `.highcharts-point-hover` and
-             * `.highcharts-point-select` class names.
-             *
-             * @declare Highcharts.PointMarkerOptionsObject
-             *
-             * @private
-             */
-            marker: {
-                /**
-                 * Enable or disable the point marker. If `undefined`, the markers
-                 * are hidden when the data is dense, and shown for more widespread
-                 * data points.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/series-marker-enabled/
-                 *         Disabled markers
-                 * @sample {highcharts} highcharts/plotoptions/series-marker-enabled-false/
-                 *         Disabled in normal state but enabled on hover
-                 * @sample {highstock} stock/plotoptions/series-marker/
-                 *         Enabled markers
-                 *
-                 * @type      {boolean}
-                 * @default   {highcharts} undefined
-                 * @default   {highstock} false
-                 * @apioption plotOptions.series.marker.enabled
-                 */
-                /**
-                 * The threshold for how dense the point markers should be before
-                 * they are hidden, given that `enabled` is not defined. The number
-                 * indicates the horizontal distance between the two closest points
-                 * in the series, as multiples of the `marker.radius`. In other
-                 * words, the default value of 2 means points are hidden if
-                 * overlapping horizontally.
-                 *
-                 * @sample highcharts/plotoptions/series-marker-enabledthreshold
-                 *         A higher threshold
-                 *
-                 * @since 6.0.5
-                 */
-                enabledThreshold: 2,
-                /**
-                 * The fill color of the point marker. When `undefined`, the series'
-                 * or point's color is used.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/series-marker-fillcolor/
-                 *         White fill
-                 *
-                 * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-                 * @apioption plotOptions.series.marker.fillColor
-                 */
-                /**
-                 * Image markers only. Set the image width explicitly. When using
-                 * this option, a `width` must also be set.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/series-marker-width-height/
-                 *         Fixed width and height
-                 * @sample {highstock} highcharts/plotoptions/series-marker-width-height/
-                 *         Fixed width and height
-                 *
-                 * @type      {number}
-                 * @since     4.0.4
-                 * @apioption plotOptions.series.marker.height
-                 */
-                /**
-                 * The color of the point marker's outline. When `undefined`, the
-                 * series' or point's color is used.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/series-marker-fillcolor/
-                 *         Inherit from series color (undefined)
-                 *
-                 * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-                 */
-                lineColor: '#ffffff',
-                /**
-                 * The width of the point marker's outline.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/series-marker-fillcolor/
-                 *         2px blue marker
-                 */
-                lineWidth: 0,
-                /**
-                 * The radius of the point marker.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/series-marker-radius/
-                 *         Bigger markers
-                 *
-                 * @default {highstock} 2
-                 */
-                radius: 4,
-                /**
-                 * A predefined shape or symbol for the marker. When undefined, the
-                 * symbol is pulled from options.symbols. Other possible values are
-                 * `'circle'`, `'square'`,`'diamond'`, `'triangle'` and
-                 * `'triangle-down'`.
-                 *
-                 * Additionally, the URL to a graphic can be given on this form:
-                 * `'url(graphic.png)'`. Note that for the image to be applied to
-                 * exported charts, its URL needs to be accessible by the export
-                 * server.
-                 *
-                 * Custom callbacks for symbol path generation can also be added to
-                 * `Highcharts.SVGRenderer.prototype.symbols`. The callback is then
-                 * used by its method name, as shown in the demo.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/series-marker-symbol/
-                 *         Predefined, graphic and custom markers
-                 * @sample {highstock} highcharts/plotoptions/series-marker-symbol/
-                 *         Predefined, graphic and custom markers
-                 *
-                 * @type      {string}
-                 * @apioption plotOptions.series.marker.symbol
-                 */
-                /**
-                 * Image markers only. Set the image width explicitly. When using
-                 * this option, a `height` must also be set.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/series-marker-width-height/
-                 *         Fixed width and height
-                 * @sample {highstock} highcharts/plotoptions/series-marker-width-height/
-                 *         Fixed width and height
-                 *
-                 * @type      {number}
-                 * @since     4.0.4
-                 * @apioption plotOptions.series.marker.width
-                 */
-                /**
-                 * States for a single point marker.
-                 *
-                 * @declare Highcharts.PointStatesOptionsObject
-                 */
-                states: {
-                    /**
-                     * The normal state of a single point marker. Currently only
-                     * used for setting animation when returning to normal state
-                     * from hover.
-                     *
-                     * @declare Highcharts.PointStatesNormalOptionsObject
-                     */
-                    normal: {
-                        /**
-                         * Animation when returning to normal state after hovering.
-                         *
-                         * @type {boolean|Partial<Highcharts.AnimationOptionsObject>}
-                         */
-                        animation: true
-                    },
-                    /**
-                     * The hover state for a single point marker.
-                     *
-                     * @declare Highcharts.PointStatesHoverOptionsObject
-                     */
-                    hover: {
-                        /**
-                         * Animation when hovering over the marker.
-                         *
-                         * @type {boolean|Partial<Highcharts.AnimationOptionsObject>}
-                         */
-                        animation: {
-                            /** @internal */
-                            duration: 50
-                        },
-                        /**
-                         * Enable or disable the point marker.
-                         *
-                         * @sample {highcharts} highcharts/plotoptions/series-marker-states-hover-enabled/
-                         *         Disabled hover state
-                         */
-                        enabled: true,
-                        /**
-                         * The fill color of the marker in hover state. When
-                         * `undefined`, the series' or point's fillColor for normal
-                         * state is used.
-                         *
-                         * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-                         * @apioption plotOptions.series.marker.states.hover.fillColor
-                         */
-                        /**
-                         * The color of the point marker's outline. When
-                         * `undefined`, the series' or point's lineColor for normal
-                         * state is used.
-                         *
-                         * @sample {highcharts} highcharts/plotoptions/series-marker-states-hover-linecolor/
-                         *         White fill color, black line color
-                         *
-                         * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-                         * @apioption plotOptions.series.marker.states.hover.lineColor
-                         */
-                        /**
-                         * The width of the point marker's outline. When
-                         * `undefined`, the series' or point's lineWidth for normal
-                         * state is used.
-                         *
-                         * @sample {highcharts} highcharts/plotoptions/series-marker-states-hover-linewidth/
-                         *         3px line width
-                         *
-                         * @type      {number}
-                         * @apioption plotOptions.series.marker.states.hover.lineWidth
-                         */
-                        /**
-                         * The radius of the point marker. In hover state, it
-                         * defaults to the normal state's radius + 2 as per the
-                         * [radiusPlus](#plotOptions.series.marker.states.hover.radiusPlus)
-                         * option.
-                         *
-                         * @sample {highcharts} highcharts/plotoptions/series-marker-states-hover-radius/
-                         *         10px radius
-                         *
-                         * @type      {number}
-                         * @apioption plotOptions.series.marker.states.hover.radius
-                         */
-                        /**
-                         * The number of pixels to increase the radius of the
-                         * hovered point.
-                         *
-                         * @sample {highcharts} highcharts/plotoptions/series-states-hover-linewidthplus/
-                         *         5 pixels greater radius on hover
-                         * @sample {highstock} highcharts/plotoptions/series-states-hover-linewidthplus/
-                         *         5 pixels greater radius on hover
-                         *
-                         * @since 4.0.3
-                         */
-                        radiusPlus: 2,
-                        /**
-                         * The additional line width for a hovered point.
-                         *
-                         * @sample {highcharts} highcharts/plotoptions/series-states-hover-linewidthplus/
-                         *         2 pixels wider on hover
-                         * @sample {highstock} highcharts/plotoptions/series-states-hover-linewidthplus/
-                         *         2 pixels wider on hover
-                         *
-                         * @since 4.0.3
-                         */
-                        lineWidthPlus: 1
-                    },
-                    /**
-                     * The appearance of the point marker when selected. In order to
-                     * allow a point to be selected, set the
-                     * `series.allowPointSelect` option to true.
-                     *
-                     * @declare Highcharts.PointStatesSelectOptionsObject
-                     */
-                    select: {
-                        /**
-                         * Enable or disable visible feedback for selection.
-                         *
-                         * @sample {highcharts} highcharts/plotoptions/series-marker-states-select-enabled/
-                         *         Disabled select state
-                         *
-                         * @type      {boolean}
-                         * @default   true
-                         * @apioption plotOptions.series.marker.states.select.enabled
-                         */
-                        /**
-                         * The radius of the point marker. In hover state, it
-                         * defaults to the normal state's radius + 2.
-                         *
-                         * @sample {highcharts} highcharts/plotoptions/series-marker-states-select-radius/
-                         *         10px radius for selected points
-                         *
-                         * @type      {number}
-                         * @apioption plotOptions.series.marker.states.select.radius
-                         */
-                        /**
-                         * The fill color of the point marker.
-                         *
-                         * @sample {highcharts} highcharts/plotoptions/series-marker-states-select-fillcolor/
-                         *         Solid red discs for selected points
-                         *
-                         * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-                         */
-                        fillColor: '#cccccc',
-                        /**
-                         * The color of the point marker's outline. When
-                         * `undefined`, the series' or point's color is used.
-                         *
-                         * @sample {highcharts} highcharts/plotoptions/series-marker-states-select-linecolor/
-                         *         Red line color for selected points
-                         *
-                         * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-                         */
-                        lineColor: '#000000',
-                        /**
-                         * The width of the point marker's outline.
-                         *
-                         * @sample {highcharts} highcharts/plotoptions/series-marker-states-select-linewidth/
-                         *         3px line width for selected points
-                         */
-                        lineWidth: 2
-                    }
-                }
-            },
-            /**
-             * Properties for each single point.
-             *
-             * @declare Highcharts.PlotSeriesPointOptions
-             *
-             * @private
-             */
-            point: {
-                /**
-                 * Fires when a point is clicked. One parameter, `event`, is passed
-                 * to the function, containing common event information.
-                 *
-                 * If the `series.allowPointSelect` option is true, the default
-                 * action for the point's click event is to toggle the point's
-                 * select state. Returning `false` cancels this action.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/series-point-events-click/
-                 *         Click marker to alert values
-                 * @sample {highcharts} highcharts/plotoptions/series-point-events-click-column/
-                 *         Click column
-                 * @sample {highcharts} highcharts/plotoptions/series-point-events-click-url/
-                 *         Go to URL
-                 * @sample {highmaps} maps/plotoptions/series-point-events-click/
-                 *         Click marker to display values
-                 * @sample {highmaps} maps/plotoptions/series-point-events-click-url/
-                 *         Go to URL
-                 *
-                 * @type      {Highcharts.PointClickCallbackFunction}
-                 * @context   Highcharts.Point
-                 * @apioption plotOptions.series.point.events.click
-                 */
-                /**
-                 * Fires when the mouse leaves the area close to the point. One
-                 * parameter, `event`, is passed to the function, containing common
-                 * event information.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/series-point-events-mouseover/
-                 *         Show values in the chart's corner on mouse over
-                 *
-                 * @type      {Highcharts.PointMouseOutCallbackFunction}
-                 * @context   Highcharts.Point
-                 * @apioption plotOptions.series.point.events.mouseOut
-                 */
-                /**
-                 * Fires when the mouse enters the area close to the point. One
-                 * parameter, `event`, is passed to the function, containing common
-                 * event information.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/series-point-events-mouseover/
-                 *         Show values in the chart's corner on mouse over
-                 *
-                 * @type      {Highcharts.PointMouseOverCallbackFunction}
-                 * @context   Highcharts.Point
-                 * @apioption plotOptions.series.point.events.mouseOver
-                 */
-                /**
-                 * Fires when the point is removed using the `.remove()` method. One
-                 * parameter, `event`, is passed to the function. Returning `false`
-                 * cancels the operation.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/series-point-events-remove/
-                 *         Remove point and confirm
-                 *
-                 * @type      {Highcharts.PointRemoveCallbackFunction}
-                 * @since     1.2.0
-                 * @context   Highcharts.Point
-                 * @apioption plotOptions.series.point.events.remove
-                 */
-                /**
-                 * Fires when the point is selected either programmatically or
-                 * following a click on the point. One parameter, `event`, is passed
-                 * to the function. Returning `false` cancels the operation.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/series-point-events-select/
-                 *         Report the last selected point
-                 * @sample {highmaps} maps/plotoptions/series-allowpointselect/
-                 *         Report select and unselect
-                 *
-                 * @type      {Highcharts.PointSelectCallbackFunction}
-                 * @since     1.2.0
-                 * @context   Highcharts.Point
-                 * @apioption plotOptions.series.point.events.select
-                 */
-                /**
-                 * Fires when the point is unselected either programmatically or
-                 * following a click on the point. One parameter, `event`, is passed
-                 * to the function.
-                 *  Returning `false` cancels the operation.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/series-point-events-unselect/
-                 *         Report the last unselected point
-                 * @sample {highmaps} maps/plotoptions/series-allowpointselect/
-                 *         Report select and unselect
-                 *
-                 * @type      {Highcharts.PointUnselectCallbackFunction}
-                 * @since     1.2.0
-                 * @context   Highcharts.Point
-                 * @apioption plotOptions.series.point.events.unselect
-                 */
-                /**
-                 * Fires when the point is updated programmatically through the
-                 * `.update()` method. One parameter, `event`, is passed to the
-                 * function. The new point options can be accessed through
-                 * `event.options`. Returning `false` cancels the operation.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/series-point-events-update/
-                 *         Confirm point updating
-                 *
-                 * @type      {Highcharts.PointUpdateCallbackFunction}
-                 * @since     1.2.0
-                 * @context   Highcharts.Point
-                 * @apioption plotOptions.series.point.events.update
-                 */
-                /**
-                 * Events for each single point.
-                 *
-                 * @declare Highcharts.PointEventsOptionsObject
-                 */
-                events: {}
-            },
-            /**
-             * Options for the series data labels, appearing next to each data
-             * point.
-             *
-             * Since v6.2.0, multiple data labels can be applied to each single
-             * point by defining them as an array of configs.
-             *
-             * In styled mode, the data labels can be styled with the
-             * `.highcharts-data-label-box` and `.highcharts-data-label` class names
-             * ([see example](https://www.highcharts.com/samples/highcharts/css/series-datalabels)).
-             *
-             * @sample {highcharts} highcharts/plotoptions/series-datalabels-enabled
-             *         Data labels enabled
-             * @sample {highcharts} highcharts/plotoptions/series-datalabels-multiple
-             *         Multiple data labels on a bar series
-             * @sample {highcharts} highcharts/css/series-datalabels
-             *         Style mode example
-             *
-             * @type    {*|Array<*>}
-             * @product highcharts highstock highmaps gantt
-             *
-             * @private
-             */
-            dataLabels: {
-                /**
-                 * Enable or disable the initial animation when a series is
-                 * displayed for the `dataLabels`. The animation can also be set as
-                 * a configuration object. Please note that this option only
-                 * applies to the initial animation.
-                 * For other animations, see [chart.animation](#chart.animation)
-                 * and the animation parameter under the API methods.
-                 * The following properties are supported:
-                 *
-                 * - `defer`: The animation delay time in milliseconds.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/animation-defer/
-                 *          Animation defer settings
-                 *
-                 * @type      {boolean|Partial<Highcharts.AnimationOptionsObject>}
-                 * @since     8.2.0
-                 * @apioption plotOptions.series.dataLabels.animation
-                 */
-                animation: {},
-                /**
-                 * The animation delay time in milliseconds.
-                 * Set to `0` renders dataLabel immediately.
-                 * As `undefined` inherits defer time from the [series.animation.defer](#plotOptions.series.animation.defer).
-                 *
-                 * @type      {number}
-                 * @since     8.2.0
-                 * @apioption plotOptions.series.dataLabels.animation.defer
-                 */
-                /**
-                 * The alignment of the data label compared to the point. If
-                 * `right`, the right side of the label should be touching the
-                 * point. For points with an extent, like columns, the alignments
-                 * also dictates how to align it inside the box, as given with the
-                 * [inside](#plotOptions.column.dataLabels.inside)
-                 * option. Can be one of `left`, `center` or `right`.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/series-datalabels-align-left/
-                 *         Left aligned
-                 * @sample {highcharts} highcharts/plotoptions/bar-datalabels-align-inside-bar/
-                 *         Data labels inside the bar
-                 *
-                 * @type {Highcharts.AlignValue|null}
-                 */
-                align: 'center',
-                /**
-                 * Whether to allow data labels to overlap. To make the labels less
-                 * sensitive for overlapping, the
-                 * [dataLabels.padding](#plotOptions.series.dataLabels.padding)
-                 * can be set to 0.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/series-datalabels-allowoverlap-false/
-                 *         Don't allow overlap
-                 *
-                 * @type      {boolean}
-                 * @default   false
-                 * @since     4.1.0
-                 * @apioption plotOptions.series.dataLabels.allowOverlap
-                 */
-                /**
-                 * The background color or gradient for the data label.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/
-                 *         Data labels box options
-                 * @sample {highmaps} maps/plotoptions/series-datalabels-box/
-                 *         Data labels box options
-                 *
-                 * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-                 * @since     2.2.1
-                 * @apioption plotOptions.series.dataLabels.backgroundColor
-                 */
-                /**
-                 * The border color for the data label. Defaults to `undefined`.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/
-                 *         Data labels box options
-                 *
-                 * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-                 * @since     2.2.1
-                 * @apioption plotOptions.series.dataLabels.borderColor
-                 */
-                /**
-                 * The border radius in pixels for the data label.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/
-                 *         Data labels box options
-                 * @sample {highmaps} maps/plotoptions/series-datalabels-box/
-                 *         Data labels box options
-                 *
-                 * @type      {number}
-                 * @default   0
-                 * @since     2.2.1
-                 * @apioption plotOptions.series.dataLabels.borderRadius
-                 */
-                /**
-                 * The border width in pixels for the data label.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/
-                 *         Data labels box options
-                 *
-                 * @type      {number}
-                 * @default   0
-                 * @since     2.2.1
-                 * @apioption plotOptions.series.dataLabels.borderWidth
-                 */
-                /**
-                 * A class name for the data label. Particularly in styled mode,
-                 * this can be used to give each series' or point's data label
-                 * unique styling. In addition to this option, a default color class
-                 * name is added so that we can give the labels a contrast text
-                 * shadow.
-                 *
-                 * @sample {highcharts} highcharts/css/data-label-contrast/
-                 *         Contrast text shadow
-                 * @sample {highcharts} highcharts/css/series-datalabels/
-                 *         Styling by CSS
-                 *
-                 * @type      {string}
-                 * @since     5.0.0
-                 * @apioption plotOptions.series.dataLabels.className
-                 */
-                /**
-                 * The text color for the data labels. Defaults to `undefined`. For
-                 * certain series types, like column or map, the data labels can be
-                 * drawn inside the points. In this case the data label will be
-                 * drawn with maximum contrast by default. Additionally, it will be
-                 * given a `text-outline` style with the opposite color, to further
-                 * increase the contrast. This can be overridden by setting the
-                 * `text-outline` style to `none` in the `dataLabels.style` option.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/series-datalabels-color/
-                 *         Red data labels
-                 * @sample {highmaps} maps/demo/color-axis/
-                 *         White data labels
-                 *
-                 * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-                 * @apioption plotOptions.series.dataLabels.color
-                 */
-                /**
-                 * Whether to hide data labels that are outside the plot area. By
-                 * default, the data label is moved inside the plot area according
-                 * to the
-                 * [overflow](#plotOptions.series.dataLabels.overflow)
-                 * option.
-                 *
-                 * @type      {boolean}
-                 * @default   true
-                 * @since     2.3.3
-                 * @apioption plotOptions.series.dataLabels.crop
-                 */
-                /**
-                 * Whether to defer displaying the data labels until the initial
-                 * series animation has finished. Setting to `false` renders the
-                 * data label immediately. If set to `true` inherits the defer
-                 * time set in [plotOptions.series.animation](#plotOptions.series.animation).
-                 *
-                 * @sample highcharts/plotoptions/animation-defer
-                 *         Set defer time
-                 *
-                 * @since     4.0.0
-                 * @product   highcharts highstock gantt
-                 */
-                defer: true,
-                /**
-                 * Enable or disable the data labels.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/series-datalabels-enabled/
-                 *         Data labels enabled
-                 * @sample {highmaps} maps/demo/color-axis/
-                 *         Data labels enabled
-                 *
-                 * @type      {boolean}
-                 * @default   false
-                 * @apioption plotOptions.series.dataLabels.enabled
-                 */
-                /**
-                 * A declarative filter to control of which data labels to display.
-                 * The declarative filter is designed for use when callback
-                 * functions are not available, like when the chart options require
-                 * a pure JSON structure or for use with graphical editors. For
-                 * programmatic control, use the `formatter` instead, and return
-                 * `undefined` to disable a single data label.
-                 *
-                 * @example
-                 * filter: {
-                 *     property: 'percentage',
-                 *     operator: '>',
-                 *     value: 4
-                 * }
-                 *
-                 * @sample {highcharts} highcharts/demo/pie-monochrome
-                 *         Data labels filtered by percentage
-                 *
-                 * @declare   Highcharts.DataLabelsFilterOptionsObject
-                 * @since     6.0.3
-                 * @apioption plotOptions.series.dataLabels.filter
-                 */
-                /**
-                 * The operator to compare by. Can be one of `>`, `<`, `>=`, `<=`,
-                 * `==`, and `===`.
-                 *
-                 * @type       {string}
-                 * @validvalue [">", "<", ">=", "<=", "==", "==="]
-                 * @apioption  plotOptions.series.dataLabels.filter.operator
-                 */
-                /**
-                 * The point property to filter by. Point options are passed
-                 * directly to properties, additionally there are `y` value,
-                 * `percentage` and others listed under {@link Highcharts.Point}
-                 * members.
-                 *
-                 * @type      {string}
-                 * @apioption plotOptions.series.dataLabels.filter.property
-                 */
-                /**
-                 * The value to compare against.
-                 *
-                 * @type      {number}
-                 * @apioption plotOptions.series.dataLabels.filter.value
-                 */
-                /**
-                 * A
-                 * [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting)
-                 * for the data label. Available variables are the same as for
-                 * `formatter`.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/series-datalabels-format/
-                 *         Add a unit
-                 * @sample {highmaps} maps/plotoptions/series-datalabels-format/
-                 *         Formatted value in the data label
-                 *
-                 * @type      {string}
-                 * @default   y
-                 * @default   point.value
-                 * @since     3.0
-                 * @apioption plotOptions.series.dataLabels.format
-                 */
-                // eslint-disable-next-line valid-jsdoc
-                /**
-                 * Callback JavaScript function to format the data label. Note that
-                 * if a `format` is defined, the format takes precedence and the
-                 * formatter is ignored.
-                 *
-                 * @sample {highmaps} maps/plotoptions/series-datalabels-format/
-                 *         Formatted value
-                 *
-                 * @type {Highcharts.DataLabelsFormatterCallbackFunction}
-                 */
-                formatter: function () {
-                    var numberFormatter = this.series.chart.numberFormatter;
-                    return typeof this.y !== 'number' ? '' : numberFormatter(this.y, -1);
-                },
-                /**
-                 * For points with an extent, like columns or map areas, whether to
-                 * align the data label inside the box or to the actual value point.
-                 * Defaults to `false` in most cases, `true` in stacked columns.
-                 *
-                 * @type      {boolean}
-                 * @since     3.0
-                 * @apioption plotOptions.series.dataLabels.inside
-                 */
-                /**
-                 * Format for points with the value of null. Works analogously to
-                 * [format](#plotOptions.series.dataLabels.format). `nullFormat` can
-                 * be applied only to series which support displaying null points.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/series-datalabels-format/
-                 *         Format data label and tooltip for null point.
-                 *
-                 * @type      {boolean|string}
-                 * @since     7.1.0
-                 * @apioption plotOptions.series.dataLabels.nullFormat
-                 */
-                /**
-                 * Callback JavaScript function that defines formatting for points
-                 * with the value of null. Works analogously to
-                 * [formatter](#plotOptions.series.dataLabels.formatter).
-                 * `nullPointFormatter` can be applied only to series which support
-                 * displaying null points.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/series-datalabels-format/
-                 *         Format data label and tooltip for null point.
-                 *
-                 * @type      {Highcharts.DataLabelsFormatterCallbackFunction}
-                 * @since     7.1.0
-                 * @apioption plotOptions.series.dataLabels.nullFormatter
-                 */
-                /**
-                 * How to handle data labels that flow outside the plot area. The
-                 * default is `"justify"`, which aligns them inside the plot area.
-                 * For columns and bars, this means it will be moved inside the bar.
-                 * To display data labels outside the plot area, set `crop` to
-                 * `false` and `overflow` to `"allow"`.
-                 *
-                 * @type       {Highcharts.DataLabelsOverflowValue}
-                 * @default    justify
-                 * @since      3.0.6
-                 * @apioption  plotOptions.series.dataLabels.overflow
-                 */
-                /**
-                 * When either the `borderWidth` or the `backgroundColor` is set,
-                 * this is the padding within the box.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/
-                 *         Data labels box options
-                 * @sample {highmaps} maps/plotoptions/series-datalabels-box/
-                 *         Data labels box options
-                 *
-                 * @since 2.2.1
-                 */
-                padding: 5,
-                /**
-                 * Aligns data labels relative to points. If `center` alignment is
-                 * not possible, it defaults to `right`.
-                 *
-                 * @type      {Highcharts.AlignValue}
-                 * @default   center
-                 * @apioption plotOptions.series.dataLabels.position
-                 */
-                /**
-                 * Text rotation in degrees. Note that due to a more complex
-                 * structure, backgrounds, borders and padding will be lost on a
-                 * rotated data label.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/series-datalabels-rotation/
-                 *         Vertical labels
-                 *
-                 * @type      {number}
-                 * @default   0
-                 * @apioption plotOptions.series.dataLabels.rotation
-                 */
-                /**
-                 * The shadow of the box. Works best with `borderWidth` or
-                 * `backgroundColor`. Since 2.3 the shadow can be an object
-                 * configuration containing `color`, `offsetX`, `offsetY`, `opacity`
-                 * and `width`.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/
-                 *         Data labels box options
-                 *
-                 * @type      {boolean|Highcharts.ShadowOptionsObject}
-                 * @default   false
-                 * @since     2.2.1
-                 * @apioption plotOptions.series.dataLabels.shadow
-                 */
-                /**
-                 * The name of a symbol to use for the border around the label.
-                 * Symbols are predefined functions on the Renderer object.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/series-datalabels-shape/
-                 *         A callout for annotations
-                 *
-                 * @type      {string}
-                 * @default   square
-                 * @since     4.1.2
-                 * @apioption plotOptions.series.dataLabels.shape
-                 */
-                /**
-                 * Styles for the label. The default `color` setting is
-                 * `"contrast"`, which is a pseudo color that Highcharts picks up
-                 * and applies the maximum contrast to the underlying point item,
-                 * for example the bar in a bar chart.
-                 *
-                 * The `textOutline` is a pseudo property that applies an outline of
-                 * the given width with the given color, which by default is the
-                 * maximum contrast to the text. So a bright text color will result
-                 * in a black text outline for maximum readability on a mixed
-                 * background. In some cases, especially with grayscale text, the
-                 * text outline doesn't work well, in which cases it can be disabled
-                 * by setting it to `"none"`. When `useHTML` is true, the
-                 * `textOutline` will not be picked up. In this, case, the same
-                 * effect can be acheived through the `text-shadow` CSS property.
-                 *
-                 * For some series types, where each point has an extent, like for
-                 * example tree maps, the data label may overflow the point. There
-                 * are two strategies for handling overflow. By default, the text
-                 * will wrap to multiple lines. The other strategy is to set
-                 * `style.textOverflow` to `ellipsis`, which will keep the text on
-                 * one line plus it will break inside long words.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/series-datalabels-style/
-                 *         Bold labels
-                 * @sample {highcharts} highcharts/plotoptions/pie-datalabels-overflow/
-                 *         Long labels truncated with an ellipsis in a pie
-                 * @sample {highcharts} highcharts/plotoptions/pie-datalabels-overflow-wrap/
-                 *         Long labels are wrapped in a pie
-                 * @sample {highmaps} maps/demo/color-axis/
-                 *         Bold labels
-                 *
-                 * @type      {Highcharts.CSSObject}
-                 * @since     4.1.0
-                 * @apioption plotOptions.series.dataLabels.style
-                 */
-                style: {
-                    /** @internal */
-                    fontSize: '11px',
-                    /** @internal */
-                    fontWeight: 'bold',
-                    /** @internal */
-                    color: 'contrast',
-                    /** @internal */
-                    textOutline: '1px contrast'
-                },
-                /**
-                 * Options for a label text which should follow marker's shape.
-                 * Border and background are disabled for a label that follows a
-                 * path.
-                 *
-                 * **Note:** Only SVG-based renderer supports this option. Setting
-                 * `useHTML` to true will disable this option.
-                 *
-                 * @declare   Highcharts.DataLabelsTextPathOptionsObject
-                 * @since     7.1.0
-                 * @apioption plotOptions.series.dataLabels.textPath
-                 */
-                /**
-                 * Presentation attributes for the text path.
-                 *
-                 * @type      {Highcharts.SVGAttributes}
-                 * @since     7.1.0
-                 * @apioption plotOptions.series.dataLabels.textPath.attributes
-                 */
-                /**
-                 * Enable or disable `textPath` option for link's or marker's data
-                 * labels.
-                 *
-                 * @type      {boolean}
-                 * @since     7.1.0
-                 * @apioption plotOptions.series.dataLabels.textPath.enabled
-                 */
-                /**
-                 * Whether to
-                 * [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html)
-                 * to render the labels.
-                 *
-                 * @type      {boolean}
-                 * @default   false
-                 * @apioption plotOptions.series.dataLabels.useHTML
-                 */
-                /**
-                 * The vertical alignment of a data label. Can be one of `top`,
-                 * `middle` or `bottom`. The default value depends on the data, for
-                 * instance in a column chart, the label is above positive values
-                 * and below negative values.
-                 *
-                 * @type  {Highcharts.VerticalAlignValue|null}
-                 * @since 2.3.3
-                 */
-                verticalAlign: 'bottom',
-                /**
-                 * The x position offset of the label relative to the point in
-                 * pixels.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/series-datalabels-rotation/
-                 *         Vertical and positioned
-                 * @sample {highcharts} highcharts/plotoptions/bar-datalabels-align-inside-bar/
-                 *         Data labels inside the bar
-                 */
-                x: 0,
-                /**
-                 * The Z index of the data labels. The default Z index puts it above
-                 * the series. Use a Z index of 2 to display it behind the series.
-                 *
-                 * @type      {number}
-                 * @default   6
-                 * @since     2.3.5
-                 * @apioption plotOptions.series.dataLabels.z
-                 */
-                /**
-                 * The y position offset of the label relative to the point in
-                 * pixels.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/series-datalabels-rotation/
-                 *         Vertical and positioned
-                 */
-                y: 0
+            this.cross.e = e;
+          }
+          fireEvent(this, "afterDrawCrosshair", { e: e, point: point });
+        };
+        /**
+         * Hide the crosshair if visible.
+         *
+         * @function Highcharts.Axis#hideCrosshair
+         */
+        Axis.prototype.hideCrosshair = function () {
+          if (this.cross) {
+            this.cross.hide();
+          }
+          fireEvent(this, "afterHideCrosshair");
+        };
+        /**
+         * Check whether the chart has vertical panning ('y' or 'xy' type).
+         *
+         * @private
+         * @function Highcharts.Axis#hasVerticalPanning
+         * @return {boolean}
+         *
+         */
+        Axis.prototype.hasVerticalPanning = function () {
+          var _a, _b;
+          return /y/.test(
+            ((_b =
+              (_a = this.chart.options.chart) === null || _a === void 0
+                ? void 0
+                : _a.panning) === null || _b === void 0
+              ? void 0
+              : _b.type) || ""
+          );
+        };
+        /**
+         * Check whether the given value is a positive valid axis value.
+         *
+         * @private
+         * @function Highcharts.Axis#validatePositiveValue
+         *
+         * @param {unknown} value
+         * The axis value
+         * @return {boolean}
+         *
+         */
+        Axis.prototype.validatePositiveValue = function (value) {
+          return isNumber(value) && value > 0;
+        };
+        /* *
+         *
+         *  Static Properties
+         *
+         * */
+        /**
+         * The X axis or category axis. Normally this is the horizontal axis,
+         * though if the chart is inverted this is the vertical axis. In case of
+         * multiple axes, the xAxis node is an array of configuration objects.
+         *
+         * See the [Axis class](/class-reference/Highcharts.Axis) for programmatic
+         * access to the axis.
+         *
+         * @productdesc {highmaps}
+         * In Highmaps, the axis is hidden, but it is used behind the scenes to
+         * control features like zooming and panning. Zooming is in effect the same
+         * as setting the extremes of one of the exes.
+         *
+         * @type         {*|Array<*>}
+         * @optionparent xAxis
+         *
+         * @private
+         */
+        Axis.defaultOptions = {
+          /**
+           * When using multiple axis, the ticks of two or more opposite axes
+           * will automatically be aligned by adding ticks to the axis or axes
+           * with the least ticks, as if `tickAmount` were specified.
+           *
+           * This can be prevented by setting `alignTicks` to false. If the grid
+           * lines look messy, it's a good idea to hide them for the secondary
+           * axis by setting `gridLineWidth` to 0.
+           *
+           * If `startOnTick` or `endOnTick` in an Axis options are set to false,
+           * then the `alignTicks ` will be disabled for the Axis.
+           *
+           * Disabled for logarithmic axes.
+           *
+           * @type      {boolean}
+           * @default   true
+           * @product   highcharts highstock gantt
+           * @apioption xAxis.alignTicks
+           */
+          /**
+           * Whether to allow decimals in this axis' ticks. When counting
+           * integers, like persons or hits on a web page, decimals should
+           * be avoided in the labels.
+           *
+           * @see [minTickInterval](#xAxis.minTickInterval)
+           *
+           * @sample {highcharts|highstock} highcharts/yaxis/allowdecimals-true/
+           *         True by default
+           * @sample {highcharts|highstock} highcharts/yaxis/allowdecimals-false/
+           *         False
+           *
+           * @type      {boolean}
+           * @default   true
+           * @since     2.0
+           * @apioption xAxis.allowDecimals
+           */
+          /**
+           * When using an alternate grid color, a band is painted across the
+           * plot area between every other grid line.
+           *
+           * @sample {highcharts} highcharts/yaxis/alternategridcolor/
+           *         Alternate grid color on the Y axis
+           * @sample {highstock} stock/xaxis/alternategridcolor/
+           *         Alternate grid color on the Y axis
+           *
+           * @type      {Highcharts.ColorType}
+           * @apioption xAxis.alternateGridColor
+           */
+          /**
+           * An array defining breaks in the axis, the sections defined will be
+           * left out and all the points shifted closer to each other.
+           *
+           * @productdesc {highcharts}
+           * Requires that the broken-axis.js module is loaded.
+           *
+           * @sample {highcharts} highcharts/axisbreak/break-simple/
+           *         Simple break
+           * @sample {highcharts|highstock} highcharts/axisbreak/break-visualized/
+           *         Advanced with callback
+           * @sample {highstock} stock/demo/intraday-breaks/
+           *         Break on nights and weekends
+           *
+           * @type      {Array<*>}
+           * @since     4.1.0
+           * @product   highcharts highstock gantt
+           * @apioption xAxis.breaks
+           */
+          /**
+           * A number indicating how much space should be left between the start
+           * and the end of the break. The break size is given in axis units,
+           * so for instance on a `datetime` axis, a break size of 3600000 would
+           * indicate the equivalent of an hour.
+           *
+           * @type      {number}
+           * @default   0
+           * @since     4.1.0
+           * @product   highcharts highstock gantt
+           * @apioption xAxis.breaks.breakSize
+           */
+          /**
+           * The point where the break starts.
+           *
+           * @type      {number}
+           * @since     4.1.0
+           * @product   highcharts highstock gantt
+           * @apioption xAxis.breaks.from
+           */
+          /**
+           * Defines an interval after which the break appears again. By default
+           * the breaks do not repeat.
+           *
+           * @type      {number}
+           * @default   0
+           * @since     4.1.0
+           * @product   highcharts highstock gantt
+           * @apioption xAxis.breaks.repeat
+           */
+          /**
+           * The point where the break ends.
+           *
+           * @type      {number}
+           * @since     4.1.0
+           * @product   highcharts highstock gantt
+           * @apioption xAxis.breaks.to
+           */
+          /**
+           * If categories are present for the xAxis, names are used instead of
+           * numbers for that axis.
+           *
+           * Since Highcharts 3.0, categories can also
+           * be extracted by giving each point a [name](#series.data) and setting
+           * axis [type](#xAxis.type) to `category`. However, if you have multiple
+           * series, best practice remains defining the `categories` array.
+           *
+           * Example: `categories: ['Apples', 'Bananas', 'Oranges']`
+           *
+           * @sample {highcharts} highcharts/demo/line-labels/
+           *         With
+           * @sample {highcharts} highcharts/xaxis/categories/
+           *         Without
+           *
+           * @type      {Array<string>}
+           * @product   highcharts gantt
+           * @apioption xAxis.categories
+           */
+          /**
+           * The highest allowed value for automatically computed axis extremes.
+           *
+           * @see [floor](#xAxis.floor)
+           *
+           * @sample {highcharts|highstock} highcharts/yaxis/floor-ceiling/
+           *         Floor and ceiling
+           *
+           * @type       {number}
+           * @since      4.0
+           * @product    highcharts highstock gantt
+           * @apioption  xAxis.ceiling
+           */
+          /**
+           * A class name that opens for styling the axis by CSS, especially in
+           * Highcharts styled mode. The class name is applied to group elements
+           * for the grid, axis elements and labels.
+           *
+           * @sample {highcharts|highstock|highmaps} highcharts/css/axis/
+           *         Multiple axes with separate styling
+           *
+           * @type      {string}
+           * @since     5.0.0
+           * @apioption xAxis.className
+           */
+          /**
+           * Configure a crosshair that follows either the mouse pointer or the
+           * hovered point.
+           *
+           * In styled mode, the crosshairs are styled in the
+           * `.highcharts-crosshair`, `.highcharts-crosshair-thin` or
+           * `.highcharts-xaxis-category` classes.
+           *
+           * @productdesc {highstock}
+           * In Highstock, by default, the crosshair is enabled on the X axis and
+           * disabled on the Y axis.
+           *
+           * @sample {highcharts} highcharts/xaxis/crosshair-both/
+           *         Crosshair on both axes
+           * @sample {highstock} stock/xaxis/crosshairs-xy/
+           *         Crosshair on both axes
+           * @sample {highmaps} highcharts/xaxis/crosshair-both/
+           *         Crosshair on both axes
+           *
+           * @declare   Highcharts.AxisCrosshairOptions
+           * @type      {boolean|*}
+           * @default   false
+           * @since     4.1
+           * @apioption xAxis.crosshair
+           */
+          /**
+           * A class name for the crosshair, especially as a hook for styling.
+           *
+           * @type      {string}
+           * @since     5.0.0
+           * @apioption xAxis.crosshair.className
+           */
+          /**
+           * The color of the crosshair. Defaults to `#cccccc` for numeric and
+           * datetime axes, and `rgba(204,214,235,0.25)` for category axes, where
+           * the crosshair by default highlights the whole category.
+           *
+           * @sample {highcharts|highstock|highmaps} highcharts/xaxis/crosshair-customized/
+           *         Customized crosshairs
+           *
+           * @type      {Highcharts.ColorType}
+           * @default   #cccccc
+           * @since     4.1
+           * @apioption xAxis.crosshair.color
+           */
+          /**
+           * The dash style for the crosshair. See
+           * [plotOptions.series.dashStyle](#plotOptions.series.dashStyle)
+           * for possible values.
+           *
+           * @sample {highcharts|highmaps} highcharts/xaxis/crosshair-dotted/
+           *         Dotted crosshair
+           * @sample {highstock} stock/xaxis/crosshair-dashed/
+           *         Dashed X axis crosshair
+           *
+           * @type      {Highcharts.DashStyleValue}
+           * @default   Solid
+           * @since     4.1
+           * @apioption xAxis.crosshair.dashStyle
+           */
+          /**
+           * A label on the axis next to the crosshair.
+           *
+           * In styled mode, the label is styled with the
+           * `.highcharts-crosshair-label` class.
+           *
+           * @sample {highstock} stock/xaxis/crosshair-label/
+           *         Crosshair labels
+           * @sample {highstock} highcharts/css/crosshair-label/
+           *         Style mode
+           *
+           * @declare   Highcharts.AxisCrosshairLabelOptions
+           * @since     2.1
+           * @product   highstock
+           * @apioption xAxis.crosshair.label
+           */
+          /**
+           * Alignment of the label compared to the axis. Defaults to `"left"` for
+           * right-side axes, `"right"` for left-side axes and `"center"` for
+           * horizontal axes.
+           *
+           * @type      {Highcharts.AlignValue}
+           * @since     2.1
+           * @product   highstock
+           * @apioption xAxis.crosshair.label.align
+           */
+          /**
+           * The background color for the label. Defaults to the related series
+           * color, or `#666666` if that is not available.
+           *
+           * @type      {Highcharts.ColorType}
+           * @since     2.1
+           * @product   highstock
+           * @apioption xAxis.crosshair.label.backgroundColor
+           */
+          /**
+           * The border color for the crosshair label
+           *
+           * @type      {Highcharts.ColorType}
+           * @since     2.1
+           * @product   highstock
+           * @apioption xAxis.crosshair.label.borderColor
+           */
+          /**
+           * The border corner radius of the crosshair label.
+           *
+           * @type      {number}
+           * @default   3
+           * @since     2.1.10
+           * @product   highstock
+           * @apioption xAxis.crosshair.label.borderRadius
+           */
+          /**
+           * The border width for the crosshair label.
+           *
+           * @type      {number}
+           * @default   0
+           * @since     2.1
+           * @product   highstock
+           * @apioption xAxis.crosshair.label.borderWidth
+           */
+          /**
+           * Flag to enable crosshair's label.
+           *
+           * @sample {highstock} stock/xaxis/crosshairs-xy/
+           *         Enabled label for yAxis' crosshair
+           *
+           * @type      {boolean}
+           * @default   false
+           * @since     2.1
+           * @product   highstock
+           * @apioption xAxis.crosshair.label.enabled
+           */
+          /**
+           * A format string for the crosshair label. Defaults to `{value}` for
+           * numeric axes and `{value:%b %d, %Y}` for datetime axes.
+           *
+           * @type      {string}
+           * @since     2.1
+           * @product   highstock
+           * @apioption xAxis.crosshair.label.format
+           */
+          /**
+           * Formatter function for the label text.
+           *
+           * @type      {Highcharts.XAxisCrosshairLabelFormatterCallbackFunction}
+           * @since     2.1
+           * @product   highstock
+           * @apioption xAxis.crosshair.label.formatter
+           */
+          /**
+           * Padding inside the crosshair label.
+           *
+           * @type      {number}
+           * @default   8
+           * @since     2.1
+           * @product   highstock
+           * @apioption xAxis.crosshair.label.padding
+           */
+          /**
+           * The shape to use for the label box.
+           *
+           * @type      {string}
+           * @default   callout
+           * @since     2.1
+           * @product   highstock
+           * @apioption xAxis.crosshair.label.shape
+           */
+          /**
+           * Text styles for the crosshair label.
+           *
+           * @type      {Highcharts.CSSObject}
+           * @default   {"color": "white", "fontWeight": "normal", "fontSize": "11px", "textAlign": "center"}
+           * @since     2.1
+           * @product   highstock
+           * @apioption xAxis.crosshair.label.style
+           */
+          /**
+           * Whether the crosshair should snap to the point or follow the pointer
+           * independent of points.
+           *
+           * @sample {highcharts|highstock} highcharts/xaxis/crosshair-snap-false/
+           *         True by default
+           * @sample {highmaps} maps/demo/latlon-advanced/
+           *         Snap is false
+           *
+           * @type      {boolean}
+           * @default   true
+           * @since     4.1
+           * @apioption xAxis.crosshair.snap
+           */
+          /**
+           * The pixel width of the crosshair. Defaults to 1 for numeric or
+           * datetime axes, and for one category width for category axes.
+           *
+           * @sample {highcharts} highcharts/xaxis/crosshair-customized/
+           *         Customized crosshairs
+           * @sample {highstock} highcharts/xaxis/crosshair-customized/
+           *         Customized crosshairs
+           * @sample {highmaps} highcharts/xaxis/crosshair-customized/
+           *         Customized crosshairs
+           *
+           * @type      {number}
+           * @default   1
+           * @since     4.1
+           * @apioption xAxis.crosshair.width
+           */
+          /**
+           * The Z index of the crosshair. Higher Z indices allow drawing the
+           * crosshair on top of the series or behind the grid lines.
+           *
+           * @type      {number}
+           * @default   2
+           * @since     4.1
+           * @apioption xAxis.crosshair.zIndex
+           */
+          /**
+           * Whether to zoom axis. If `chart.zoomType` is set, the option allows
+           * to disable zooming on an individual axis.
+           *
+           * @sample {highcharts} highcharts/xaxis/zoomenabled/
+           *         Zoom enabled is false
+           *
+           *
+           * @type      {boolean}
+           * @default   enabled
+           * @apioption xAxis.zoomEnabled
+           */
+          /**
+           * For a datetime axis, the scale will automatically adjust to the
+           * appropriate unit. This member gives the default string
+           * representations used for each unit. For intermediate values,
+           * different units may be used, for example the `day` unit can be used
+           * on midnight and `hour` unit be used for intermediate values on the
+           * same axis.
+           *
+           * For an overview of the replacement codes, see
+           * [dateFormat](/class-reference/Highcharts#dateFormat).
+           *
+           * Defaults to:
+           * ```js
+           * {
+           *     millisecond: '%H:%M:%S.%L',
+           *     second: '%H:%M:%S',
+           *     minute: '%H:%M',
+           *     hour: '%H:%M',
+           *     day: '%e. %b',
+           *     week: '%e. %b',
+           *     month: '%b \'%y',
+           *     year: '%Y'
+           * }
+           * ```
+           *
+           * @sample {highcharts} highcharts/xaxis/datetimelabelformats/
+           *         Different day format on X axis
+           * @sample {highstock} stock/xaxis/datetimelabelformats/
+           *         More information in x axis labels
+           *
+           * @declare Highcharts.AxisDateTimeLabelFormatsOptions
+           * @product highcharts highstock gantt
+           */
+          dateTimeLabelFormats: {
+            /**
+             * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject
+             * @type {string|*}
+             */
+            millisecond: {
+              main: "%H:%M:%S.%L",
+              range: false,
             },
             /**
-             * When the series contains less points than the crop threshold, all
-             * points are drawn, even if the points fall outside the visible plot
-             * area at the current zoom. The advantage of drawing all points
-             * (including markers and columns), is that animation is performed on
-             * updates. On the other hand, when the series contains more points than
-             * the crop threshold, the series data is cropped to only contain points
-             * that fall within the plot area. The advantage of cropping away
-             * invisible points is to increase performance on large series.
-             *
-             * @since   2.2
-             * @product highcharts highstock
-             *
-             * @private
+             * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject
+             * @type {string|*}
              */
-            cropThreshold: 300,
+            second: {
+              main: "%H:%M:%S",
+              range: false,
+            },
             /**
-             * Opacity of a series parts: line, fill (e.g. area) and dataLabels.
-             *
-             * @see [states.inactive.opacity](#plotOptions.series.states.inactive.opacity)
-             *
-             * @since 7.1.0
-             *
-             * @private
+             * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject
+             * @type {string|*}
              */
-            opacity: 1,
+            minute: {
+              main: "%H:%M",
+              range: false,
+            },
             /**
-             * The width of each point on the x axis. For example in a column chart
-             * with one value each day, the pointRange would be 1 day (= 24 * 3600
-             * * 1000 milliseconds). This is normally computed automatically, but
-             * this option can be used to override the automatic value.
-             *
-             * @product highstock
-             *
-             * @private
+             * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject
+             * @type {string|*}
              */
-            pointRange: 0,
+            hour: {
+              main: "%H:%M",
+              range: false,
+            },
             /**
-             * When this is true, the series will not cause the Y axis to cross
-             * the zero plane (or [threshold](#plotOptions.series.threshold) option)
-             * unless the data actually crosses the plane.
-             *
-             * For example, if `softThreshold` is `false`, a series of 0, 1, 2,
-             * 3 will make the Y axis show negative values according to the
-             * `minPadding` option. If `softThreshold` is `true`, the Y axis starts
-             * at 0.
-             *
-             * @since   4.1.9
-             * @product highcharts highstock
-             *
-             * @private
+             * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject
+             * @type {string|*}
              */
-            softThreshold: true,
+            day: {
+              main: "%e. %b",
+            },
             /**
-             * @declare Highcharts.SeriesStatesOptionsObject
-             *
-             * @private
+             * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject
+             * @type {string|*}
              */
-            states: {
-                /**
-                 * The normal state of a series, or for point items in column, pie
-                 * and similar series. Currently only used for setting animation
-                 * when returning to normal state from hover.
-                 *
-                 * @declare Highcharts.SeriesStatesNormalOptionsObject
-                 */
-                normal: {
-                    /**
-                     * Animation when returning to normal state after hovering.
-                     *
-                         * @type {boolean|Partial<Highcharts.AnimationOptionsObject>}
-                     */
-                    animation: true
-                },
-                /**
-                 * Options for the hovered series. These settings override the
-                 * normal state options when a series is moused over or touched.
-                 *
-                 * @declare Highcharts.SeriesStatesHoverOptionsObject
-                 */
-                hover: {
-                    /**
-                     * Enable separate styles for the hovered series to visualize
-                     * that the user hovers either the series itself or the legend.
-                     *
-                     * @sample {highcharts} highcharts/plotoptions/series-states-hover-enabled/
-                     *         Line
-                     * @sample {highcharts} highcharts/plotoptions/series-states-hover-enabled-column/
-                     *         Column
-                     * @sample {highcharts} highcharts/plotoptions/series-states-hover-enabled-pie/
-                     *         Pie
-                     *
-                     * @type      {boolean}
-                     * @default   true
-                     * @since     1.2
-                     * @apioption plotOptions.series.states.hover.enabled
-                     */
-                    /**
-                     * Animation setting for hovering the graph in line-type series.
-                     *
-                     * @type {boolean|Partial<Highcharts.AnimationOptionsObject>}
-                     * @since   5.0.8
-                     * @product highcharts highstock
-                     */
-                    animation: {
-                        /**
-                         * The duration of the hover animation in milliseconds. By
-                         * default the hover state animates quickly in, and slowly
-                         * back to normal.
-                         *
-                         * @internal
-                         */
-                        duration: 50
-                    },
-                    /**
-                     * Pixel width of the graph line. By default this property is
-                     * undefined, and the `lineWidthPlus` property dictates how much
-                     * to increase the linewidth from normal state.
-                     *
-                     * @sample {highcharts} highcharts/plotoptions/series-states-hover-linewidth/
-                     *         5px line on hover
-                     *
-                     * @type      {number}
-                     * @product   highcharts highstock
-                     * @apioption plotOptions.series.states.hover.lineWidth
-                     */
-                    /**
-                     * The additional line width for the graph of a hovered series.
-                     *
-                     * @sample {highcharts} highcharts/plotoptions/series-states-hover-linewidthplus/
-                     *         5 pixels wider
-                     * @sample {highstock} highcharts/plotoptions/series-states-hover-linewidthplus/
-                     *         5 pixels wider
-                     *
-                     * @since   4.0.3
-                     * @product highcharts highstock
-                     */
-                    lineWidthPlus: 1,
-                    /**
-                     * In Highcharts 1.0, the appearance of all markers belonging
-                     * to the hovered series. For settings on the hover state of the
-                     * individual point, see
-                     * [marker.states.hover](#plotOptions.series.marker.states.hover).
-                     *
-                     * @deprecated
-                     *
-                     * @extends   plotOptions.series.marker
-                     * @excluding states
-                     * @product   highcharts highstock
-                     */
-                    marker: {
-                    // lineWidth: base + 1,
-                    // radius: base + 1
-                    },
-                    /**
-                     * Options for the halo appearing around the hovered point in
-                     * line-type series as well as outside the hovered slice in pie
-                     * charts. By default the halo is filled by the current point or
-                     * series color with an opacity of 0.25\. The halo can be
-                     * disabled by setting the `halo` option to `null`.
-                     *
-                     * In styled mode, the halo is styled with the
-                     * `.highcharts-halo` class, with colors inherited from
-                     * `.highcharts-color-{n}`.
-                     *
-                     * @sample {highcharts} highcharts/plotoptions/halo/
-                     *         Halo options
-                     * @sample {highstock} highcharts/plotoptions/halo/
-                     *         Halo options
-                     *
-                     * @declare Highcharts.SeriesStatesHoverHaloOptionsObject
-                     * @type    {null|*}
-                     * @since   4.0
-                     * @product highcharts highstock
-                     */
-                    halo: {
-                        /**
-                         * A collection of SVG attributes to override the appearance
-                         * of the halo, for example `fill`, `stroke` and
-                         * `stroke-width`.
-                         *
-                         * @type      {Highcharts.SVGAttributes}
-                         * @since     4.0
-                         * @product   highcharts highstock
-                         * @apioption plotOptions.series.states.hover.halo.attributes
-                         */
-                        /**
-                         * The pixel size of the halo. For point markers this is the
-                         * radius of the halo. For pie slices it is the width of the
-                         * halo outside the slice. For bubbles it defaults to 5 and
-                         * is the width of the halo outside the bubble.
-                         *
-                         * @since   4.0
-                         * @product highcharts highstock
-                         */
-                        size: 10,
-                        /**
-                         * Opacity for the halo unless a specific fill is overridden
-                         * using the `attributes` setting. Note that Highcharts is
-                         * only able to apply opacity to colors of hex or rgb(a)
-                         * formats.
-                         *
-                         * @since   4.0
-                         * @product highcharts highstock
-                         */
-                        opacity: 0.25
-                    }
-                },
-                /**
-                 * Specific options for point in selected states, after being
-                 * selected by
-                 * [allowPointSelect](#plotOptions.series.allowPointSelect)
-                 * or programmatically.
-                 *
-                 * @sample maps/plotoptions/series-allowpointselect/
-                 *         Allow point select demo
-                 *
-                 * @declare   Highcharts.SeriesStatesSelectOptionsObject
-                 * @extends   plotOptions.series.states.hover
-                 * @excluding brightness
-                 */
-                select: {
-                    animation: {
-                        /** @internal */
-                        duration: 0
-                    }
-                },
-                /**
-                 * The opposite state of a hover for series.
-                 *
-                 * @sample highcharts/plotoptions/series-states-inactive-disabled
-                 *         Disabled inactive state
-                 *
-                 * @declare Highcharts.SeriesStatesInactiveOptionsObject
-                 */
-                inactive: {
-                    /**
-                     * Enable or disable the inactive state for a series
-                     *
-                     * @sample highcharts/plotoptions/series-states-inactive-disabled
-                     *         Disabled inactive state
-                     *
-                     * @type {boolean}
-                     * @default true
-                     * @apioption plotOptions.series.states.inactive.enabled
-                     */
-                    /**
-                     * The animation for entering the inactive state.
-                     *
-                     * @type {boolean|Partial<Highcharts.AnimationOptionsObject>}
-                     */
-                    animation: {
-                        /** @internal */
-                        duration: 50
-                    },
-                    /**
-                     * Opacity of series elements (dataLabels, line, area).
-                     *
-                     * @type {number}
-                     */
-                    opacity: 0.2
-                }
+            week: {
+              main: "%e. %b",
             },
             /**
-             * Sticky tracking of mouse events. When true, the `mouseOut` event on a
-             * series isn't triggered until the mouse moves over another series, or
-             * out of the plot area. When false, the `mouseOut` event on a series is
-             * triggered when the mouse leaves the area around the series' graph or
-             * markers. This also implies the tooltip when not shared. When
-             * `stickyTracking` is false and `tooltip.shared` is false, the tooltip
-             * will be hidden when moving the mouse between series. Defaults to true
-             * for line and area type series, but to false for columns, pies etc.
-             *
-             * **Note:** The boost module will force this option because of
-             * technical limitations.
-             *
-             * @sample {highcharts} highcharts/plotoptions/series-stickytracking-true/
-             *         True by default
-             * @sample {highcharts} highcharts/plotoptions/series-stickytracking-false/
-             *         False
-             *
-             * @default {highcharts} true
-             * @default {highstock} true
-             * @default {highmaps} false
-             * @since   2.0
-             *
-             * @private
+             * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject
+             * @type {string|*}
              */
-            stickyTracking: true,
+            month: {
+              main: "%b '%y",
+            },
             /**
-             * A configuration object for the tooltip rendering of each single
-             * series. Properties are inherited from [tooltip](#tooltip), but only
-             * the following properties can be defined on a series level.
-             *
-             * @declare   Highcharts.SeriesTooltipOptionsObject
-             * @since     2.3
-             * @extends   tooltip
-             * @excluding animation, backgroundColor, borderColor, borderRadius,
-             *            borderWidth, className, crosshairs, enabled, formatter,
-             *            headerShape, hideDelay, outside, padding, positioner,
-             *            shadow, shape, shared, snap, split, stickOnContact,
-             *            style, useHTML
-             * @apioption plotOptions.series.tooltip
+             * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject
+             * @type {string|*}
              */
-            /**
-             * When a series contains a data array that is longer than this, only
-             * one dimensional arrays of numbers, or two dimensional arrays with
-             * x and y values are allowed. Also, only the first point is tested,
-             * and the rest are assumed to be the same format. This saves expensive
-             * data checking and indexing in long series. Set it to `0` disable.
+            year: {
+              main: "%Y",
+            },
+          },
+          /**
+           * Whether to force the axis to end on a tick. Use this option with
+           * the `maxPadding` option to control the axis end.
+           *
+           * @productdesc {highstock}
+           * In Highstock, `endOnTick` is always `false` when the navigator
+           * is enabled, to prevent jumpy scrolling.
+           *
+           * @sample {highcharts} highcharts/chart/reflow-true/
+           *         True by default
+           * @sample {highcharts} highcharts/yaxis/endontick/
+           *         False
+           * @sample {highstock} stock/demo/basic-line/
+           *         True by default
+           * @sample {highstock} stock/xaxis/endontick/
+           *         False
+           *
+           * @since 1.2.0
+           */
+          endOnTick: false,
+          /**
+           * Event handlers for the axis.
+           *
+           * @type      {*}
+           * @apioption xAxis.events
+           */
+          /**
+           * An event fired after the breaks have rendered.
+           *
+           * @see [breaks](#xAxis.breaks)
+           *
+           * @sample {highcharts} highcharts/axisbreak/break-event/
+           *         AfterBreak Event
+           *
+           * @type      {Highcharts.AxisEventCallbackFunction}
+           * @since     4.1.0
+           * @product   highcharts gantt
+           * @apioption xAxis.events.afterBreaks
+           */
+          /**
+           * As opposed to the `setExtremes` event, this event fires after the
+           * final min and max values are computed and corrected for `minRange`.
+           *
+           * Fires when the minimum and maximum is set for the axis, either by
+           * calling the `.setExtremes()` method or by selecting an area in the
+           * chart. One parameter, `event`, is passed to the function, containing
+           * common event information.
+           *
+           * The new user set minimum and maximum values can be found by
+           * `event.min` and `event.max`. These reflect the axis minimum and
+           * maximum in axis values. The actual data extremes are found in
+           * `event.dataMin` and `event.dataMax`.
+           *
+           * @type      {Highcharts.AxisSetExtremesEventCallbackFunction}
+           * @since     2.3
+           * @context   Highcharts.Axis
+           * @apioption xAxis.events.afterSetExtremes
+           */
+          /**
+           * An event fired when a break from this axis occurs on a point.
+           *
+           * @see [breaks](#xAxis.breaks)
+           *
+           * @sample {highcharts} highcharts/axisbreak/break-visualized/
+           *         Visualization of a Break
+           *
+           * @type      {Highcharts.AxisPointBreakEventCallbackFunction}
+           * @since     4.1.0
+           * @product   highcharts gantt
+           * @context   Highcharts.Axis
+           * @apioption xAxis.events.pointBreak
+           */
+          /**
+           * An event fired when a point falls inside a break from this axis.
+           *
+           * @type      {Highcharts.AxisPointBreakEventCallbackFunction}
+           * @product   highcharts highstock gantt
+           * @context   Highcharts.Axis
+           * @apioption xAxis.events.pointInBreak
+           */
+          /**
+           * Fires when the minimum and maximum is set for the axis, either by
+           * calling the `.setExtremes()` method or by selecting an area in the
+           * chart. One parameter, `event`, is passed to the function,
+           * containing common event information.
+           *
+           * The new user set minimum and maximum values can be found by
+           * `event.min` and `event.max`. These reflect the axis minimum and
+           * maximum in data values. When an axis is zoomed all the way out from
+           * the "Reset zoom" button, `event.min` and `event.max` are null, and
+           * the new extremes are set based on `this.dataMin` and `this.dataMax`.
+           *
+           * @sample {highstock} stock/xaxis/events-setextremes/
+           *         Log new extremes on x axis
+           *
+           * @type      {Highcharts.AxisSetExtremesEventCallbackFunction}
+           * @since     1.2.0
+           * @context   Highcharts.Axis
+           * @apioption xAxis.events.setExtremes
+           */
+          /**
+           * The lowest allowed value for automatically computed axis extremes.
+           *
+           * @see [ceiling](#yAxis.ceiling)
+           *
+           * @sample {highcharts} highcharts/yaxis/floor-ceiling/
+           *         Floor and ceiling
+           * @sample {highstock} stock/demo/lazy-loading/
+           *         Prevent negative stock price on Y axis
+           *
+           * @type      {number}
+           * @since     4.0
+           * @product   highcharts highstock gantt
+           * @apioption xAxis.floor
+           */
+          /**
+           * The dash or dot style of the grid lines. For possible values, see
+           * [this demonstration](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/series-dashstyle-all/).
+           *
+           * @sample {highcharts} highcharts/yaxis/gridlinedashstyle/
+           *         Long dashes
+           * @sample {highstock} stock/xaxis/gridlinedashstyle/
+           *         Long dashes
+           *
+           * @type      {Highcharts.DashStyleValue}
+           * @default   Solid
+           * @since     1.2
+           * @apioption xAxis.gridLineDashStyle
+           */
+          /**
+           * The Z index of the grid lines.
+           *
+           * @sample {highcharts|highstock} highcharts/xaxis/gridzindex/
+           *         A Z index of 4 renders the grid above the graph
+           *
+           * @type      {number}
+           * @default   1
+           * @product   highcharts highstock gantt
+           * @apioption xAxis.gridZIndex
+           */
+          /**
+           * An id for the axis. This can be used after render time to get
+           * a pointer to the axis object through `chart.get()`.
+           *
+           * @sample {highcharts} highcharts/xaxis/id/
+           *         Get the object
+           * @sample {highstock} stock/xaxis/id/
+           *         Get the object
+           *
+           * @type      {string}
+           * @since     1.2.0
+           * @apioption xAxis.id
+           */
+          /**
+           * The axis labels show the number or category for each tick.
+           *
+           * Since v8.0.0: Labels are animated in categorized x-axis with
+           * updating data if `tickInterval` and `step` is set to 1.
+           *
+           * @productdesc {highmaps}
+           * X and Y axis labels are by default disabled in Highmaps, but the
+           * functionality is inherited from Highcharts and used on `colorAxis`,
+           * and can be enabled on X and Y axes too.
+           */
+          labels: {
+            /**
+             * What part of the string the given position is anchored to.
+             * If `left`, the left side of the string is at the axis position.
+             * Can be one of `"left"`, `"center"` or `"right"`. Defaults to
+             * an intelligent guess based on which side of the chart the axis
+             * is on and the rotation of the label.
+             *
+             * @see [reserveSpace](#xAxis.labels.reserveSpace)
+             *
+             * @sample {highcharts} highcharts/xaxis/labels-align-left/
+             *         Left
+             * @sample {highcharts} highcharts/xaxis/labels-align-right/
+             *         Right
+             * @sample {highcharts} highcharts/xaxis/labels-reservespace-true/
+             *         Left-aligned labels on a vertical category axis
              *
-             * Note:
-             * In boost mode turbo threshold is forced. Only array of numbers or
-             * two dimensional arrays are allowed.
+             * @type       {Highcharts.AlignValue}
+             * @apioption  xAxis.labels.align
+             */
+            /**
+             * For horizontal axes, the allowed degrees of label rotation
+             * to prevent overlapping labels. If there is enough space,
+             * labels are not rotated. As the chart gets narrower, it
+             * will start rotating the labels -45 degrees, then remove
+             * every second label and try again with rotations 0 and -45 etc.
+             * Set it to `false` to disable rotation, which will
+             * cause the labels to word-wrap if possible.
              *
-             * @since   2.2
-             * @product highcharts highstock gantt
+             * @sample {highcharts|highstock} highcharts/xaxis/labels-autorotation-default/
+             *         Default auto rotation of 0 or -45
+             * @sample {highcharts|highstock} highcharts/xaxis/labels-autorotation-0-90/
+             *         Custom graded auto rotation
              *
-             * @private
+             * @type      {Array<number>|false}
+             * @default   [-45]
+             * @since     4.1.0
+             * @product   highcharts highstock gantt
+             * @apioption xAxis.labels.autoRotation
              */
-            turboThreshold: 1000,
             /**
-             * An array defining zones within a series. Zones can be applied to the
-             * X axis, Y axis or Z axis for bubbles, according to the `zoneAxis`
-             * option. The zone definitions have to be in ascending order regarding
-             * to the value.
+             * When each category width is more than this many pixels, we don't
+             * apply auto rotation. Instead, we lay out the axis label with word
+             * wrap. A lower limit makes sense when the label contains multiple
+             * short words that don't extend the available horizontal space for
+             * each label.
              *
-             * In styled mode, the color zones are styled with the
-             * `.highcharts-zone-{n}` class, or custom classed from the `className`
-             * option
-             * ([view live demo](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/css/color-zones/)).
+             * @sample {highcharts} highcharts/xaxis/labels-autorotationlimit/
+             *         Lower limit
              *
-             * @see [zoneAxis](#plotOptions.series.zoneAxis)
-             *
-             * @sample {highcharts} highcharts/series/color-zones-simple/
-             *         Color zones
-             * @sample {highstock} highcharts/series/color-zones-simple/
-             *         Color zones
+             * @type      {number}
+             * @default   80
+             * @since     4.1.5
+             * @product   highcharts gantt
+             * @apioption xAxis.labels.autoRotationLimit
+             */
+            /**
+             * Polar charts only. The label's pixel distance from the perimeter
+             * of the plot area.
              *
-             * @declare   Highcharts.SeriesZonesOptionsObject
-             * @type      {Array<*>}
-             * @since     4.1.0
-             * @product   highcharts highstock
-             * @apioption plotOptions.series.zones
+             * @type      {number}
+             * @default   15
+             * @product   highcharts gantt
+             * @apioption xAxis.labels.distance
              */
             /**
-             * Styled mode only. A custom class name for the zone.
+             * Enable or disable the axis labels.
              *
-             * @sample highcharts/css/color-zones/
-             *         Zones styled by class name
+             * @sample {highcharts} highcharts/xaxis/labels-enabled/
+             *         X axis labels disabled
+             * @sample {highstock} stock/xaxis/labels-enabled/
+             *         X axis labels disabled
              *
-             * @type      {string}
-             * @since     5.0.0
-             * @apioption plotOptions.series.zones.className
+             * @default {highcharts|highstock|gantt} true
+             * @default {highmaps} false
              */
+            enabled: true,
             /**
-             * Defines the color of the series.
+             * A [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting)
+             * for the axis label.
              *
-             * @see [series color](#plotOptions.series.color)
+             * @sample {highcharts|highstock} highcharts/yaxis/labels-format/
+             *         Add units to Y axis label
              *
-             * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-             * @since     4.1.0
-             * @product   highcharts highstock
-             * @apioption plotOptions.series.zones.color
+             * @type      {string}
+             * @default   {value}
+             * @since     3.0
+             * @apioption xAxis.labels.format
              */
             /**
-             * A name for the dash style to use for the graph.
+             * Callback JavaScript function to format the label. The value
+             * is given by `this.value`. Additional properties for `this` are
+             * `axis`, `chart`, `isFirst` and `isLast`. The value of the default
+             * label formatter can be retrieved by calling
+             * `this.axis.defaultLabelFormatter.call(this)` within the function.
              *
-             * @see [plotOptions.series.dashStyle](#plotOptions.series.dashStyle)
+             * Defaults to:
+             * ```js
+             * function() {
+             *     return this.value;
+             * }
+             * ```
              *
-             * @sample {highcharts|highstock} highcharts/series/color-zones-dashstyle-dot/
-             *         Dashed line indicates prognosis
+             * @sample {highcharts} highcharts/xaxis/labels-formatter-linked/
+             *         Linked category names
+             * @sample {highcharts} highcharts/xaxis/labels-formatter-extended/
+             *         Modified numeric labels
+             * @sample {highstock} stock/xaxis/labels-formatter/
+             *         Added units on Y axis
              *
-             * @type      {Highcharts.DashStyleValue}
-             * @since     4.1.0
-             * @product   highcharts highstock
-             * @apioption plotOptions.series.zones.dashStyle
+             * @type      {Highcharts.AxisLabelsFormatterCallbackFunction}
+             * @apioption xAxis.labels.formatter
              */
             /**
-             * Defines the fill color for the series (in area type series)
+             * The number of pixels to indent the labels per level in a treegrid
+             * axis.
              *
-             * @see [fillColor](#plotOptions.area.fillColor)
+             * @sample gantt/treegrid-axis/demo
+             *         Indentation 10px by default.
+             * @sample gantt/treegrid-axis/indentation-0px
+             *         Indentation set to 0px.
              *
-             * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-             * @since     4.1.0
-             * @product   highcharts highstock
-             * @apioption plotOptions.series.zones.fillColor
+             * @product gantt
              */
+            indentation: 10,
             /**
-             * The value up to where the zone extends, if undefined the zones
-             * stretches to the last value in the series.
+             * Horizontal axis only. When `staggerLines` is not set,
+             * `maxStaggerLines` defines how many lines the axis is allowed to
+             * add to automatically avoid overlapping X labels. Set to `1` to
+             * disable overlap detection.
              *
+             * @deprecated
              * @type      {number}
-             * @since     4.1.0
-             * @product   highcharts highstock
-             * @apioption plotOptions.series.zones.value
+             * @default   5
+             * @since     1.3.3
+             * @apioption xAxis.labels.maxStaggerLines
              */
             /**
-             * When using dual or multiple color axes, this number defines which
-             * colorAxis the particular series is connected to. It refers to
-             * either the
-             * {@link #colorAxis.id|axis id}
-             * or the index of the axis in the colorAxis array, with 0 being the
-             * first. Set this option to false to prevent a series from connecting
-             * to the default color axis.
-             *
-             * Since v7.2.0 the option can also be an axis id or an axis index
-             * instead of a boolean flag.
-             *
-             * @sample highcharts/coloraxis/coloraxis-with-pie/
-             *         Color axis with pie series
-             * @sample highcharts/coloraxis/multiple-coloraxis/
-             *         Multiple color axis
-             *
-             * @type      {number|string|boolean}
-             * @default   0
-             * @product   highcharts highstock highmaps
-             * @apioption plotOptions.series.colorAxis
+             * How to handle overflowing labels on horizontal axis. If set to
+             * `"allow"`, it will not be aligned at all. By default it
+             * `"justify"` labels inside the chart area. If there is room to
+             * move it, it will be aligned to the edge, else it will be removed.
+             *
+             * @type       {string}
+             * @default    justify
+             * @since      2.2.5
+             * @validvalue ["allow", "justify"]
+             * @apioption  xAxis.labels.overflow
              */
             /**
-             * Determines what data value should be used to calculate point color
-             * if `colorAxis` is used. Requires to set `min` and `max` if some
-             * custom point property is used or if approximation for data grouping
-             * is set to `'sum'`.
-             *
-             * @sample highcharts/coloraxis/custom-color-key/
-             *         Custom color key
-             * @sample highcharts/coloraxis/changed-default-color-key/
-             *         Changed default color key
+             * The pixel padding for axis labels, to ensure white space between
+             * them.
              *
-             * @type      {string}
-             * @default   y
-             * @since     7.2.0
-             * @product   highcharts highstock highmaps
-             * @apioption plotOptions.series.colorKey
+             * @type      {number}
+             * @default   5
+             * @product   highcharts gantt
+             * @apioption xAxis.labels.padding
              */
             /**
-             * Determines whether the series should look for the nearest point
-             * in both dimensions or just the x-dimension when hovering the series.
-             * Defaults to `'xy'` for scatter series and `'x'` for most other
-             * series. If the data has duplicate x-values, it is recommended to
-             * set this to `'xy'` to allow hovering over all points.
+             * Whether to reserve space for the labels. By default, space is
+             * reserved for the labels in these cases:
              *
-             * Applies only to series types using nearest neighbor search (not
-             * direct hover) for tooltip.
+             * * On all horizontal axes.
+             * * On vertical axes if `label.align` is `right` on a left-side
+             * axis or `left` on a right-side axis.
+             * * On vertical axes if `label.align` is `center`.
              *
-             * @sample {highcharts} highcharts/series/findnearestpointby/
-             *         Different hover behaviors
-             * @sample {highstock} highcharts/series/findnearestpointby/
-             *         Different hover behaviors
-             * @sample {highmaps} highcharts/series/findnearestpointby/
-             *         Different hover behaviors
+             * This can be turned off when for example the labels are rendered
+             * inside the plot area instead of outside.
              *
-             * @since      5.0.10
-             * @validvalue ["x", "xy"]
+             * @see [labels.align](#xAxis.labels.align)
              *
-             * @private
+             * @sample {highcharts} highcharts/xaxis/labels-reservespace/
+             *         No reserved space, labels inside plot
+             * @sample {highcharts} highcharts/xaxis/labels-reservespace-true/
+             *         Left-aligned labels on a vertical category axis
+             *
+             * @type      {boolean}
+             * @since     4.1.10
+             * @product   highcharts gantt
+             * @apioption xAxis.labels.reserveSpace
              */
-            findNearestPointBy: 'x'
-        }, 
-        /* eslint-disable no-invalid-this, valid-jsdoc */
-        /** @lends Highcharts.Series.prototype */
-        {
-            axisTypes: ['xAxis', 'yAxis'],
-            coll: 'series',
-            colorCounter: 0,
-            cropShoulder: 1,
-            directTouch: false,
-            isCartesian: true,
-            // each point's x and y values are stored in this.xData and this.yData
-            parallelArrays: ['x', 'y'],
-            pointClass: Point,
-            requireSorting: true,
-            sorted: true,
-            init: function (chart, options) {
-                fireEvent(this, 'init', { options: options });
-                var series = this,
-                    events,
-                    chartSeries = chart.series,
-                    lastSeries;
-                // A lookup over those events that are added by _options_ (not
-                // programmatically). These are updated through Series.update()
-                // (#10861).
-                this.eventOptions = this.eventOptions || {};
-                // The 'eventsToUnbind' property moved from prototype into the
-                // Series init to avoid reference to the same array between
-                // the different series and charts. #12959, #13937
-                this.eventsToUnbind = [];
-                /**
-                 * Read only. The chart that the series belongs to.
-                 *
-                 * @name Highcharts.Series#chart
-                 * @type {Highcharts.Chart}
-                 */
-                series.chart = chart;
-                /**
-                 * Read only. The series' type, like "line", "area", "column" etc.
-                 * The type in the series options anc can be altered using
-                 * {@link Series#update}.
-                 *
-                 * @name Highcharts.Series#type
-                 * @type {string}
-                 */
-                /**
-                 * Read only. The series' current options. To update, use
-                 * {@link Series#update}.
-                 *
-                 * @name Highcharts.Series#options
-                 * @type {Highcharts.SeriesOptionsType}
-                 */
-                series.options = options = series.setOptions(options);
-                series.linkedSeries = [];
-                // bind the axes
-                series.bindAxes();
-                // set some variables
-                extend(series, {
-                    /**
-                     * The series name as given in the options. Defaults to
-                     * "Series {n}".
-                     *
-                     * @name Highcharts.Series#name
-                     * @type {string}
-                     */
-                    name: options.name,
-                    state: '',
-                    /**
-                     * Read only. The series' visibility state as set by {@link
-                     * Series#show}, {@link Series#hide}, or in the initial
-                     * configuration.
-                     *
-                     * @name Highcharts.Series#visible
-                     * @type {boolean}
-                     */
-                    visible: options.visible !== false,
-                    /**
-                     * Read only. The series' selected state as set by {@link
-                     * Highcharts.Series#select}.
-                     *
-                     * @name Highcharts.Series#selected
-                     * @type {boolean}
-                     */
-                    selected: options.selected === true // false by default
-                });
-                // Register event listeners
-                events = options.events;
-                objectEach(events, function (event, eventType) {
-                    if (isFunction(event)) {
-                        // If event does not exist, or is changed by Series.update
-                        if (series.eventOptions[eventType] !== event) {
-                            // Remove existing if set by option
-                            if (isFunction(series.eventOptions[eventType])) {
-                                removeEvent(series, eventType, series.eventOptions[eventType]);
-                            }
-                            series.eventOptions[eventType] = event;
-                            addEvent(series, eventType, event);
-                        }
-                    }
-                });
-                if ((events && events.click) ||
-                    (options.point &&
-                        options.point.events &&
-                        options.point.events.click) ||
-                    options.allowPointSelect) {
-                    chart.runTrackerClick = true;
-                }
-                series.getColor();
-                series.getSymbol();
-                // Initialize the parallel data arrays
-                series.parallelArrays.forEach(function (key) {
-                    if (!series[key + 'Data']) {
-                        series[key + 'Data'] = [];
-                    }
-                });
-                // Mark cartesian
-                if (series.isCartesian) {
-                    chart.hasCartesianSeries = true;
-                }
-                // Get the index and register the series in the chart. The index is
-                // one more than the current latest series index (#5960).
-                if (chartSeries.length) {
-                    lastSeries = chartSeries[chartSeries.length - 1];
-                }
-                series._i = pick(lastSeries && lastSeries._i, -1) + 1;
-                series.opacity = series.options.opacity;
-                // Insert the series and re-order all series above the insertion
-                // point.
-                chart.orderSeries(this.insert(chartSeries));
-                // Set options for series with sorting and set data later.
-                if (options.dataSorting && options.dataSorting.enabled) {
-                    series.setDataSortingOptions();
-                }
-                else if (!series.points && !series.data) {
-                    series.setData(options.data, false);
-                }
-                fireEvent(this, 'afterInit');
-            },
             /**
-             * Check whether the series item is itself or inherits from a certain
-             * series type.
+             * Rotation of the labels in degrees.
              *
-             * @function Highcharts.Series#is
-             * @param {string} type The type of series to check for, can be either
-             *        featured or custom series types. For example `column`, `pie`,
-             *        `ohlc` etc.
+             * @sample {highcharts} highcharts/xaxis/labels-rotation/
+             *         X axis labels rotated 90°
              *
-             * @return {boolean}
-             *        True if this item is or inherits from the given type.
+             * @type      {number}
+             * @default   0
+             * @apioption xAxis.labels.rotation
              */
-            is: function (type) {
-                return seriesTypes[type] && this instanceof seriesTypes[type];
-            },
             /**
-             * Insert the series in a collection with other series, either the chart
-             * series or yAxis series, in the correct order according to the index
-             * option. Used internally when adding series.
+             * Horizontal axes only. The number of lines to spread the labels
+             * over to make room or tighter labels.
              *
-             * @private
-             * @function Highcharts.Series#insert
-             * @param {Array<Highcharts.Series>} collection
-             *        A collection of series, like `chart.series` or `xAxis.series`.
-             * @return {number}
-             *         The index of the series in the collection.
-             */
-            insert: function (collection) {
-                var indexOption = this.options.index,
-                    i;
-                // Insert by index option
-                if (isNumber(indexOption)) {
-                    i = collection.length;
-                    while (i--) {
-                        // Loop down until the interted element has higher index
-                        if (indexOption >=
-                            pick(collection[i].options.index, collection[i]._i)) {
-                            collection.splice(i + 1, 0, this);
-                            break;
-                        }
-                    }
-                    if (i === -1) {
-                        collection.unshift(this);
-                    }
-                    i = i + 1;
-                    // Or just push it to the end
-                }
-                else {
-                    collection.push(this);
-                }
-                return pick(i, collection.length - 1);
-            },
-            /**
-             * Set the xAxis and yAxis properties of cartesian series, and register
-             * the series in the `axis.series` array.
+             * @sample {highcharts} highcharts/xaxis/labels-staggerlines/
+             *         Show labels over two lines
+             * @sample {highstock} stock/xaxis/labels-staggerlines/
+             *         Show labels over two lines
              *
-             * @private
-             * @function Highcharts.Series#bindAxes
-             * @return {void}
-             * @exception 18
+             * @type      {number}
+             * @since     2.1
+             * @apioption xAxis.labels.staggerLines
              */
-            bindAxes: function () {
-                var series = this,
-                    seriesOptions = series.options,
-                    chart = series.chart,
-                    axisOptions;
-                fireEvent(this, 'bindAxes', null, function () {
-                    // repeat for xAxis and yAxis
-                    (series.axisTypes || []).forEach(function (AXIS) {
-                        // loop through the chart's axis objects
-                        chart[AXIS].forEach(function (axis) {
-                            axisOptions = axis.options;
-                            // apply if the series xAxis or yAxis option mathches
-                            // the number of the axis, or if undefined, use the
-                            // first axis
-                            if (seriesOptions[AXIS] ===
-                                axisOptions.index ||
-                                (typeof seriesOptions[AXIS] !==
-                                    'undefined' &&
-                                    seriesOptions[AXIS] === axisOptions.id) ||
-                                (typeof seriesOptions[AXIS] ===
-                                    'undefined' &&
-                                    axisOptions.index === 0)) {
-                                // register this series in the axis.series lookup
-                                series.insert(axis.series);
-                                // set this series.xAxis or series.yAxis reference
-                                /**
-                                 * Read only. The unique xAxis object associated
-                                 * with the series.
-                                 *
-                                 * @name Highcharts.Series#xAxis
-                                 * @type {Highcharts.Axis}
-                                 */
-                                /**
-                                 * Read only. The unique yAxis object associated
-                                 * with the series.
-                                 *
-                                 * @name Highcharts.Series#yAxis
-                                 * @type {Highcharts.Axis}
-                                 */
-                                series[AXIS] = axis;
-                                // mark dirty for redraw
-                                axis.isDirty = true;
-                            }
-                        });
-                        // The series needs an X and an Y axis
-                        if (!series[AXIS] &&
-                            series.optionalAxis !== AXIS) {
-                            error(18, true, chart);
-                        }
-                    });
-                });
-                fireEvent(this, 'afterBindAxes');
-            },
             /**
-             * For simple series types like line and column, the data values are
-             * held in arrays like xData and yData for quick lookup to find extremes
-             * and more. For multidimensional series like bubble and map, this can
-             * be extended with arrays like zData and valueData by adding to the
-             * `series.parallelArrays` array.
+             * To show only every _n_'th label on the axis, set the step to _n_.
+             * Setting the step to 2 shows every other label.
              *
-             * @private
-             * @function Highcharts.Series#updateParallelArrays
-             * @param {Highcharts.Point} point
-             * @param {number|string} i
-             * @return {void}
-             */
-            updateParallelArrays: function (point, i) {
-                var series = point.series,
-                    args = arguments,
-                    fn = isNumber(i) ?
-                        // Insert the value in the given position
-                        function (key) {
-                            var val = key === 'y' && series.toYData ?
-                                series.toYData(point) :
-                                point[key];
-                        series[key + 'Data'][i] = val;
-                    } :
-                    // Apply the method specified in i with the following
-                    // arguments as arguments
-                    function (key) {
-                        Array.prototype[i].apply(series[key + 'Data'], Array.prototype.slice.call(args, 2));
-                    };
-                series.parallelArrays.forEach(fn);
-            },
-            /**
-             * Define hasData functions for series. These return true if there
-             * are data points on this series within the plot area.
+             * By default, the step is calculated automatically to avoid
+             * overlap. To prevent this, set it to 1\. This usually only
+             * happens on a category axis, and is often a sign that you have
+             * chosen the wrong axis type.
              *
-             * @private
-             * @function Highcharts.Series#hasData
-             * @return {boolean}
-             */
-            hasData: function () {
-                return ((this.visible &&
-                    typeof this.dataMax !== 'undefined' &&
-                    typeof this.dataMin !== 'undefined') || ( // #3703
-                this.visible &&
-                    this.yData &&
-                    this.yData.length > 0) // #9758
-                );
-            },
-            /**
-             * Return an auto incremented x value based on the pointStart and
-             * pointInterval options. This is only used if an x value is not given
-             * for the point that calls autoIncrement.
+             * Read more at
+             * [Axis docs](https://www.highcharts.com/docs/chart-concepts/axes)
+             * => What axis should I use?
              *
-             * @private
-             * @function Highcharts.Series#autoIncrement
-             * @return {number}
-             */
-            autoIncrement: function () {
-                var options = this.options,
-                    xIncrement = this.xIncrement,
-                    date,
-                    pointInterval,
-                    pointIntervalUnit = options.pointIntervalUnit,
-                    time = this.chart.time;
-                xIncrement = pick(xIncrement, options.pointStart, 0);
-                this.pointInterval = pointInterval = pick(this.pointInterval, options.pointInterval, 1);
-                // Added code for pointInterval strings
-                if (pointIntervalUnit) {
-                    date = new time.Date(xIncrement);
-                    if (pointIntervalUnit === 'day') {
-                        time.set('Date', date, time.get('Date', date) + pointInterval);
-                    }
-                    else if (pointIntervalUnit === 'month') {
-                        time.set('Month', date, time.get('Month', date) + pointInterval);
-                    }
-                    else if (pointIntervalUnit === 'year') {
-                        time.set('FullYear', date, time.get('FullYear', date) + pointInterval);
-                    }
-                    pointInterval = date.getTime() - xIncrement;
-                }
-                this.xIncrement = xIncrement + pointInterval;
-                return xIncrement;
-            },
-            /**
-             * Internal function to set properties for series if data sorting is
-             * enabled.
+             * @sample {highcharts} highcharts/xaxis/labels-step/
+             *         Showing only every other axis label on a categorized
+             *         x-axis
+             * @sample {highcharts} highcharts/xaxis/labels-step-auto/
+             *         Auto steps on a category axis
              *
-             * @private
-             * @function Highcharts.Series#setDataSortingOptions
-             * @return {void}
-             */
-            setDataSortingOptions: function () {
-                var options = this.options;
-                extend(this, {
-                    requireSorting: false,
-                    sorted: false,
-                    enabledDataSorting: true,
-                    allowDG: false
-                });
-                // To allow unsorted data for column series.
-                if (!defined(options.pointRange)) {
-                    options.pointRange = 1;
-                }
-            },
-            /**
-             * Set the series options by merging from the options tree. Called
-             * internally on initializing and updating series. This function will
-             * not redraw the series. For API usage, use {@link Series#update}.
-             * @private
-             * @function Highcharts.Series#setOptions
-             * @param {Highcharts.SeriesOptionsType} itemOptions
-             *        The series options.
-             * @return {Highcharts.SeriesOptionsType}
-             * @fires Highcharts.Series#event:afterSetOptions
+             * @type      {number}
+             * @since     2.1
+             * @apioption xAxis.labels.step
              */
-            setOptions: function (itemOptions) {
-                var chart = this.chart,
-                    chartOptions = chart.options,
-                    plotOptions = chartOptions.plotOptions,
-                    userOptions = chart.userOptions || {},
-                    seriesUserOptions = merge(itemOptions),
-                    options,
-                    zones,
-                    zone,
-                    styledMode = chart.styledMode,
-                    e = {
-                        plotOptions: plotOptions,
-                        userOptions: seriesUserOptions
-                    };
-                fireEvent(this, 'setOptions', e);
-                // These may be modified by the event
-                var typeOptions = e.plotOptions[this.type],
-                    userPlotOptions = (userOptions.plotOptions || {});
-                // use copy to prevent undetected changes (#9762)
-                /**
-                 * Contains series options by the user without defaults.
-                 * @name Highcharts.Series#userOptions
-                 * @type {Highcharts.SeriesOptionsType}
-                 */
-                this.userOptions = e.userOptions;
-                options = merge(typeOptions, plotOptions.series, 
-                // #3881, chart instance plotOptions[type] should trump
-                // plotOptions.series
-                userOptions.plotOptions &&
-                    userOptions.plotOptions[this.type], seriesUserOptions);
-                // The tooltip options are merged between global and series specific
-                // options. Importance order asscendingly:
-                // globals: (1)tooltip, (2)plotOptions.series,
-                // (3)plotOptions[this.type]
-                // init userOptions with possible later updates: 4-6 like 1-3 and
-                // (7)this series options
-                this.tooltipOptions = merge(defaultOptions.tooltip, // 1
-                defaultOptions.plotOptions.series &&
-                    defaultOptions.plotOptions.series.tooltip, // 2
-                defaultOptions.plotOptions[this.type].tooltip, // 3
-                chartOptions.tooltip.userOptions, // 4
-                plotOptions.series &&
-                    plotOptions.series.tooltip, // 5
-                plotOptions[this.type].tooltip, // 6
-                seriesUserOptions.tooltip // 7
-                );
-                // When shared tooltip, stickyTracking is true by default,
-                // unless user says otherwise.
-                this.stickyTracking = pick(seriesUserOptions.stickyTracking, userPlotOptions[this.type] &&
-                    userPlotOptions[this.type].stickyTracking, userPlotOptions.series && userPlotOptions.series.stickyTracking, (this.tooltipOptions.shared && !this.noSharedTooltip ?
-                    true :
-                    options.stickyTracking));
-                // Delete marker object if not allowed (#1125)
-                if (typeOptions.marker === null) {
-                    delete options.marker;
-                }
-                // Handle color zones
-                this.zoneAxis = options.zoneAxis;
-                zones = this.zones = (options.zones || []).slice();
-                if ((options.negativeColor || options.negativeFillColor) &&
-                    !options.zones) {
-                    zone = {
-                        value: options[this.zoneAxis + 'Threshold'] ||
-                            options.threshold ||
-                            0,
-                        className: 'highcharts-negative'
-                    };
-                    if (!styledMode) {
-                        zone.color = options.negativeColor;
-                        zone.fillColor = options.negativeFillColor;
-                    }
-                    zones.push(zone);
-                }
-                if (zones.length) { // Push one extra zone for the rest
-                    if (defined(zones[zones.length - 1].value)) {
-                        zones.push(styledMode ? {} : {
-                            color: this.color,
-                            fillColor: this.fillColor
-                        });
-                    }
-                }
-                fireEvent(this, 'afterSetOptions', { options: options });
-                return options;
-            },
             /**
-             * Return series name in "Series {Number}" format or the one defined by
-             * a user. This method can be simply overridden as series name format
-             * can vary (e.g. technical indicators).
+             * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html)
+             * to render the labels.
              *
-             * @function Highcharts.Series#getName
-             * @return {string}
-             *         The series name.
+             * @type      {boolean}
+             * @default   false
+             * @apioption xAxis.labels.useHTML
              */
-            getName: function () {
-                // #4119
-                return pick(this.options.name, 'Series ' + (this.index + 1));
-            },
             /**
-             * @private
-             * @function Highcharts.Series#getCyclic
-             * @param {string} prop
-             * @param {*} [value]
-             * @param {Highcharts.Dictionary<any>} [defaults]
-             * @return {void}
+             * The x position offset of all labels relative to the tick
+             * positions on the axis.
+             *
+             * @sample {highcharts} highcharts/xaxis/labels-x/
+             *         Y axis labels placed on grid lines
              */
-            getCyclic: function (prop, value, defaults) {
-                var i, chart = this.chart, userOptions = this.userOptions, indexName = prop + 'Index', counterName = prop + 'Counter', len = defaults ? defaults.length : pick(chart.options.chart[prop + 'Count'], chart[prop + 'Count']), setting;
-                if (!value) {
-                    // Pick up either the colorIndex option, or the _colorIndex
-                    // after Series.update()
-                    setting = pick(userOptions[indexName], userOptions['_' + indexName]);
-                    if (defined(setting)) { // after Series.update()
-                        i = setting;
-                    }
-                    else {
-                        // #6138
-                        if (!chart.series.length) {
-                            chart[counterName] = 0;
-                        }
-                        userOptions['_' + indexName] = i =
-                            chart[counterName] % len;
-                        chart[counterName] += 1;
-                    }
-                    if (defaults) {
-                        value = defaults[i];
-                    }
-                }
-                // Set the colorIndex
-                if (typeof i !== 'undefined') {
-                    this[indexName] = i;
-                }
-                this[prop] = value;
-            },
+            x: 0,
             /**
-             * Get the series' color based on either the options or pulled from
-             * global options.
+             * The y position offset of all labels relative to the tick
+             * positions on the axis. The default makes it adapt to the font
+             * size of the bottom axis.
              *
-             * @private
-             * @function Highcharts.Series#getColor
-             * @return {void}
+             * @sample {highcharts} highcharts/xaxis/labels-x/
+             *         Y axis labels placed on grid lines
+             *
+             * @type      {number}
+             * @apioption xAxis.labels.y
              */
-            getColor: function () {
-                if (this.chart.styledMode) {
-                    this.getCyclic('color');
-                }
-                else if (this.options.colorByPoint) {
-                    // #4359, selected slice got series.color even when colorByPoint
-                    // was set.
-                    this.options.color = null;
-                }
-                else {
-                    this.getCyclic('color', this.options.color ||
-                        defaultOptions.plotOptions[this.type].color, this.chart.options.colors);
-                }
-            },
             /**
-             * Get all points' instances created for this series.
+             * The Z index for the axis labels.
              *
-             * @private
-             * @function Highcharts.Series#getPointsCollection
-             * @return {Array<Highcharts.Point>}
+             * @type      {number}
+             * @default   7
+             * @apioption xAxis.labels.zIndex
              */
-            getPointsCollection: function () {
-                return (this.hasGroupedData ? this.points : this.data) || [];
-            },
             /**
-             * Get the series' symbol based on either the options or pulled from
-             * global options.
+             * CSS styles for the label. Use `whiteSpace: 'nowrap'` to prevent
+             * wrapping of category labels. Use `textOverflow: 'none'` to
+             * prevent ellipsis (dots).
              *
-             * @private
-             * @function Highcharts.Series#getSymbol
-             * @return {void}
+             * In styled mode, the labels are styled with the
+             * `.highcharts-axis-labels` class.
+             *
+             * @sample {highcharts} highcharts/xaxis/labels-style/
+             *         Red X axis labels
+             *
+             * @type      {Highcharts.CSSObject}
              */
-            getSymbol: function () {
-                var seriesMarkerOption = this.options.marker;
-                this.getCyclic('symbol', seriesMarkerOption.symbol, this.chart.options.symbols);
+            style: {
+              /** @internal */
+              color: "#666666",
+              /** @internal */
+              cursor: "default",
+              /** @internal */
+              fontSize: "11px",
             },
-            /**
-             * Finds the index of an existing point that matches the given point
-             * options.
+          },
+          /**
+           * The left position as the horizontal axis. If it's a number, it is
+           * interpreted as pixel position relative to the chart.
+           *
+           * Since Highcharts v5.0.13: If it's a percentage string, it is
+           * interpreted as percentages of the plot width, offset from plot area
+           * left.
+           *
+           * @type      {number|string}
+           * @product   highcharts highstock
+           * @apioption xAxis.left
+           */
+          /**
+           * The top position as the vertical axis. If it's a number, it is
+           * interpreted as pixel position relative to the chart.
+           *
+           * Since Highcharts 2: If it's a percentage string, it is interpreted
+           * as percentages of the plot height, offset from plot area top.
+           *
+           * @type      {number|string}
+           * @product   highcharts highstock
+           * @apioption xAxis.top
+           */
+          /**
+           * Index of another axis that this axis is linked to. When an axis is
+           * linked to a master axis, it will take the same extremes as
+           * the master, but as assigned by min or max or by setExtremes.
+           * It can be used to show additional info, or to ease reading the
+           * chart by duplicating the scales.
+           *
+           * @sample {highcharts} highcharts/xaxis/linkedto/
+           *         Different string formats of the same date
+           * @sample {highcharts} highcharts/yaxis/linkedto/
+           *         Y values on both sides
+           *
+           * @type      {number}
+           * @since     2.0.2
+           * @product   highcharts highstock gantt
+           * @apioption xAxis.linkedTo
+           */
+          /**
+           * The maximum value of the axis. If `null`, the max value is
+           * automatically calculated.
+           *
+           * If the [endOnTick](#yAxis.endOnTick) option is true, the `max` value
+           * might be rounded up.
+           *
+           * If a [tickAmount](#yAxis.tickAmount) is set, the axis may be extended
+           * beyond the set max in order to reach the given number of ticks. The
+           * same may happen in a chart with multiple axes, determined by [chart.
+           * alignTicks](#chart), where a `tickAmount` is applied internally.
+           *
+           * @sample {highcharts} highcharts/yaxis/max-200/
+           *         Y axis max of 200
+           * @sample {highcharts} highcharts/yaxis/max-logarithmic/
+           *         Y axis max on logarithmic axis
+           * @sample {highstock} stock/xaxis/min-max/
+           *         Fixed min and max on X axis
+           * @sample {highmaps} maps/axis/min-max/
+           *         Pre-zoomed to a specific area
+           *
+           * @type      {number|null}
+           * @apioption xAxis.max
+           */
+          /**
+           * Padding of the max value relative to the length of the axis. A
+           * padding of 0.05 will make a 100px axis 5px longer. This is useful
+           * when you don't want the highest data value to appear on the edge
+           * of the plot area. When the axis' `max` option is set or a max extreme
+           * is set using `axis.setExtremes()`, the maxPadding will be ignored.
+           *
+           * @sample {highcharts} highcharts/yaxis/maxpadding/
+           *         Max padding of 0.25 on y axis
+           * @sample {highstock} stock/xaxis/minpadding-maxpadding/
+           *         Greater min- and maxPadding
+           * @sample {highmaps} maps/chart/plotbackgroundcolor-gradient/
+           *         Add some padding
+           *
+           * @default   {highcharts} 0.01
+           * @default   {highstock|highmaps} 0
+           * @since     1.2.0
+           */
+          maxPadding: 0.01,
+          /**
+           * Deprecated. Use `minRange` instead.
+           *
+           * @deprecated
+           * @type      {number}
+           * @product   highcharts highstock
+           * @apioption xAxis.maxZoom
+           */
+          /**
+           * The minimum value of the axis. If `null` the min value is
+           * automatically calculated.
+           *
+           * If the [startOnTick](#yAxis.startOnTick) option is true (default),
+           * the `min` value might be rounded down.
+           *
+           * The automatically calculated minimum value is also affected by
+           * [floor](#yAxis.floor), [softMin](#yAxis.softMin),
+           * [minPadding](#yAxis.minPadding), [minRange](#yAxis.minRange)
+           * as well as [series.threshold](#plotOptions.series.threshold)
+           * and [series.softThreshold](#plotOptions.series.softThreshold).
+           *
+           * @sample {highcharts} highcharts/yaxis/min-startontick-false/
+           *         -50 with startOnTick to false
+           * @sample {highcharts} highcharts/yaxis/min-startontick-true/
+           *         -50 with startOnTick true by default
+           * @sample {highstock} stock/xaxis/min-max/
+           *         Set min and max on X axis
+           * @sample {highmaps} maps/axis/min-max/
+           *         Pre-zoomed to a specific area
+           *
+           * @type      {number|null}
+           * @apioption xAxis.min
+           */
+          /**
+           * The dash or dot style of the minor grid lines. For possible values,
+           * see [this demonstration](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/series-dashstyle-all/).
+           *
+           * @sample {highcharts} highcharts/yaxis/minorgridlinedashstyle/
+           *         Long dashes on minor grid lines
+           * @sample {highstock} stock/xaxis/minorgridlinedashstyle/
+           *         Long dashes on minor grid lines
+           *
+           * @type      {Highcharts.DashStyleValue}
+           * @default   Solid
+           * @since     1.2
+           * @apioption xAxis.minorGridLineDashStyle
+           */
+          /**
+           * Specific tick interval in axis units for the minor ticks. On a linear
+           * axis, if `"auto"`, the minor tick interval is calculated as a fifth
+           * of the tickInterval. If `null` or `undefined`, minor ticks are not
+           * shown.
+           *
+           * On logarithmic axes, the unit is the power of the value. For example,
+           * setting the minorTickInterval to 1 puts one tick on each of 0.1, 1,
+           * 10, 100 etc. Setting the minorTickInterval to 0.1 produces 9 ticks
+           * between 1 and 10, 10 and 100 etc.
+           *
+           * If user settings dictate minor ticks to become too dense, they don't
+           * make sense, and will be ignored to prevent performance problems.
+           *
+           * @sample {highcharts} highcharts/yaxis/minortickinterval-null/
+           *         Null by default
+           * @sample {highcharts} highcharts/yaxis/minortickinterval-5/
+           *         5 units
+           * @sample {highcharts} highcharts/yaxis/minortickinterval-log-auto/
+           *         "auto"
+           * @sample {highcharts} highcharts/yaxis/minortickinterval-log/
+           *         0.1
+           * @sample {highstock} stock/demo/basic-line/
+           *         Null by default
+           * @sample {highstock} stock/xaxis/minortickinterval-auto/
+           *         "auto"
+           *
+           * @type      {number|string|null}
+           * @apioption xAxis.minorTickInterval
+           */
+          /**
+           * The pixel length of the minor tick marks.
+           *
+           * @sample {highcharts} highcharts/yaxis/minorticklength/
+           *         10px on Y axis
+           * @sample {highstock} stock/xaxis/minorticks/
+           *         10px on Y axis
+           */
+          minorTickLength: 2,
+          /**
+           * The position of the minor tick marks relative to the axis line.
+           *  Can be one of `inside` and `outside`.
+           *
+           * @sample {highcharts} highcharts/yaxis/minortickposition-outside/
+           *         Outside by default
+           * @sample {highcharts} highcharts/yaxis/minortickposition-inside/
+           *         Inside
+           * @sample {highstock} stock/xaxis/minorticks/
+           *         Inside
+           *
+           * @validvalue ["inside", "outside"]
+           */
+          minorTickPosition: "outside",
+          /**
+           * Enable or disable minor ticks. Unless
+           * [minorTickInterval](#xAxis.minorTickInterval) is set, the tick
+           * interval is calculated as a fifth of the `tickInterval`.
+           *
+           * On a logarithmic axis, minor ticks are laid out based on a best
+           * guess, attempting to enter approximately 5 minor ticks between
+           * each major tick.
+           *
+           * Prior to v6.0.0, ticks were unabled in auto layout by setting
+           * `minorTickInterval` to `"auto"`.
+           *
+           * @productdesc {highcharts}
+           * On axes using [categories](#xAxis.categories), minor ticks are not
+           * supported.
+           *
+           * @sample {highcharts} highcharts/yaxis/minorticks-true/
+           *         Enabled on linear Y axis
+           *
+           * @type      {boolean}
+           * @default   false
+           * @since     6.0.0
+           * @apioption xAxis.minorTicks
+           */
+          /**
+           * The pixel width of the minor tick mark.
+           *
+           * @sample {highcharts} highcharts/yaxis/minortickwidth/
+           *         3px width
+           * @sample {highstock} stock/xaxis/minorticks/
+           *         1px width
+           *
+           * @type      {number}
+           * @default   0
+           * @apioption xAxis.minorTickWidth
+           */
+          /**
+           * Padding of the min value relative to the length of the axis. A
+           * padding of 0.05 will make a 100px axis 5px longer. This is useful
+           * when you don't want the lowest data value to appear on the edge
+           * of the plot area. When the axis' `min` option is set or a min extreme
+           * is set using `axis.setExtremes()`, the minPadding will be ignored.
+           *
+           * @sample {highcharts} highcharts/yaxis/minpadding/
+           *         Min padding of 0.2
+           * @sample {highstock} stock/xaxis/minpadding-maxpadding/
+           *         Greater min- and maxPadding
+           * @sample {highmaps} maps/chart/plotbackgroundcolor-gradient/
+           *         Add some padding
+           *
+           * @default    {highcharts} 0.01
+           * @default    {highstock|highmaps} 0
+           * @since      1.2.0
+           * @product    highcharts highstock gantt
+           */
+          minPadding: 0.01,
+          /**
+           * The minimum range to display on this axis. The entire axis will not
+           * be allowed to span over a smaller interval than this. For example,
+           * for a datetime axis the main unit is milliseconds. If minRange is
+           * set to 3600000, you can't zoom in more than to one hour.
+           *
+           * The default minRange for the x axis is five times the smallest
+           * interval between any of the data points.
+           *
+           * On a logarithmic axis, the unit for the minimum range is the power.
+           * So a minRange of 1 means that the axis can be zoomed to 10-100,
+           * 100-1000, 1000-10000 etc.
+           *
+           * **Note**: The `minPadding`, `maxPadding`, `startOnTick` and
+           * `endOnTick` settings also affect how the extremes of the axis
+           * are computed.
+           *
+           * @sample {highcharts} highcharts/xaxis/minrange/
+           *         Minimum range of 5
+           * @sample {highstock} stock/xaxis/minrange/
+           *         Max zoom of 6 months overrides user selections
+           * @sample {highmaps} maps/axis/minrange/
+           *         Minimum range of 1000
+           *
+           * @type      {number}
+           * @apioption xAxis.minRange
+           */
+          /**
+           * The minimum tick interval allowed in axis values. For example on
+           * zooming in on an axis with daily data, this can be used to prevent
+           * the axis from showing hours. Defaults to the closest distance between
+           * two points on the axis.
+           *
+           * @type      {number}
+           * @since     2.3.0
+           * @apioption xAxis.minTickInterval
+           */
+          /**
+           * The distance in pixels from the plot area to the axis line.
+           * A positive offset moves the axis with it's line, labels and ticks
+           * away from the plot area. This is typically used when two or more
+           * axes are displayed on the same side of the plot. With multiple
+           * axes the offset is dynamically adjusted to avoid collision, this
+           * can be overridden by setting offset explicitly.
+           *
+           * @sample {highcharts} highcharts/yaxis/offset/
+           *         Y axis offset of 70
+           * @sample {highcharts} highcharts/yaxis/offset-centered/
+           *         Axes positioned in the center of the plot
+           * @sample {highstock} stock/xaxis/offset/
+           *         Y axis offset by 70 px
+           *
+           * @type      {number}
+           * @default   0
+           * @apioption xAxis.offset
+           */
+          /**
+           * Whether to display the axis on the opposite side of the normal. The
+           * normal is on the left side for vertical axes and bottom for
+           * horizontal, so the opposite sides will be right and top respectively.
+           * This is typically used with dual or multiple axes.
+           *
+           * @sample {highcharts} highcharts/yaxis/opposite/
+           *         Secondary Y axis opposite
+           * @sample {highstock} stock/xaxis/opposite/
+           *         Y axis on left side
+           *
+           * @type      {boolean}
+           * @default   {highcharts|highstock|highmaps} false
+           * @default   {gantt} true
+           * @apioption xAxis.opposite
+           */
+          /**
+           * In an ordinal axis, the points are equally spaced in the chart
+           * regardless of the actual time or x distance between them. This means
+           * that missing data periods (e.g. nights or weekends for a stock chart)
+           * will not take up space in the chart.
+           * Having `ordinal: false` will show any gaps created by the `gapSize`
+           * setting proportionate to their duration.
+           *
+           * In stock charts the X axis is ordinal by default, unless
+           * the boost module is used and at least one of the series' data length
+           * exceeds the [boostThreshold](#series.line.boostThreshold).
+           *
+           * @sample {highstock} stock/xaxis/ordinal-true/
+           *         True by default
+           * @sample {highstock} stock/xaxis/ordinal-false/
+           *         False
+           *
+           * @type      {boolean}
+           * @default   true
+           * @since     1.1
+           * @product   highstock
+           * @apioption xAxis.ordinal
+           */
+          /**
+           * Additional range on the right side of the xAxis. Works similar to
+           * `xAxis.maxPadding`, but value is set in milliseconds. Can be set for
+           * both main `xAxis` and the navigator's `xAxis`.
+           *
+           * @sample {highstock} stock/xaxis/overscroll/
+           *         One minute overscroll with live data
+           *
+           * @type      {number}
+           * @default   0
+           * @since     6.0.0
+           * @product   highstock
+           * @apioption xAxis.overscroll
+           */
+          /**
+           * Refers to the index in the [panes](#panes) array. Used for circular
+           * gauges and polar charts. When the option is not set then first pane
+           * will be used.
+           *
+           * @sample highcharts/demo/gauge-vu-meter
+           *         Two gauges with different center
+           *
+           * @type      {number}
+           * @product   highcharts
+           * @apioption xAxis.pane
+           */
+          /**
+           * The zoomed range to display when only defining one or none of `min`
+           * or `max`. For example, to show the latest month, a range of one month
+           * can be set.
+           *
+           * @sample {highstock} stock/xaxis/range/
+           *         Setting a zoomed range when the rangeSelector is disabled
+           *
+           * @type      {number}
+           * @product   highstock
+           * @apioption xAxis.range
+           */
+          /**
+           * Whether to reverse the axis so that the highest number is closest
+           * to the origin. If the chart is inverted, the x axis is reversed by
+           * default.
+           *
+           * @sample {highcharts} highcharts/yaxis/reversed/
+           *         Reversed Y axis
+           * @sample {highstock} stock/xaxis/reversed/
+           *         Reversed Y axis
+           *
+           * @type      {boolean}
+           * @default   false
+           * @apioption xAxis.reversed
+           */
+          // reversed: false,
+          /**
+           * This option determines how stacks should be ordered within a group.
+           * For example reversed xAxis also reverses stacks, so first series
+           * comes last in a group. To keep order like for non-reversed xAxis
+           * enable this option.
+           *
+           * @sample {highcharts} highcharts/xaxis/reversedstacks/
+           *         Reversed stacks comparison
+           * @sample {highstock} highcharts/xaxis/reversedstacks/
+           *         Reversed stacks comparison
+           *
+           * @type      {boolean}
+           * @default   false
+           * @since     6.1.1
+           * @product   highcharts highstock
+           * @apioption xAxis.reversedStacks
+           */
+          /**
+           * An optional scrollbar to display on the X axis in response to
+           * limiting the minimum and maximum of the axis values.
+           *
+           * In styled mode, all the presentational options for the scrollbar are
+           * replaced by the classes `.highcharts-scrollbar-thumb`,
+           * `.highcharts-scrollbar-arrow`, `.highcharts-scrollbar-button`,
+           * `.highcharts-scrollbar-rifles` and `.highcharts-scrollbar-track`.
+           *
+           * @sample {highstock} stock/yaxis/heatmap-scrollbars/
+           *         Heatmap with both scrollbars
+           *
+           * @extends   scrollbar
+           * @since     4.2.6
+           * @product   highstock
+           * @apioption xAxis.scrollbar
+           */
+          /**
+           * Whether to show the axis line and title when the axis has no data.
+           *
+           * @sample {highcharts} highcharts/yaxis/showempty/
+           *         When clicking the legend to hide series, one axis preserves
+           *         line and title, the other doesn't
+           * @sample {highstock} highcharts/yaxis/showempty/
+           *         When clicking the legend to hide series, one axis preserves
+           *         line and title, the other doesn't
+           *
+           * @since     1.1
+           */
+          showEmpty: true,
+          /**
+           * Whether to show the first tick label.
+           *
+           * @sample {highcharts} highcharts/xaxis/showfirstlabel-false/
+           *         Set to false on X axis
+           * @sample {highstock} stock/xaxis/showfirstlabel/
+           *         Labels below plot lines on Y axis
+           *
+           * @type      {boolean}
+           * @default   true
+           * @apioption xAxis.showFirstLabel
+           */
+          /**
+           * Whether to show the last tick label. Defaults to `true` on cartesian
+           * charts, and `false` on polar charts.
+           *
+           * @sample {highcharts} highcharts/xaxis/showlastlabel-true/
+           *         Set to true on X axis
+           * @sample {highstock} stock/xaxis/showfirstlabel/
+           *         Labels below plot lines on Y axis
+           *
+           * @type      {boolean}
+           * @default   true
+           * @product   highcharts highstock gantt
+           * @apioption xAxis.showLastLabel
+           */
+          /**
+           * A soft maximum for the axis. If the series data maximum is less than
+           * this, the axis will stay at this maximum, but if the series data
+           * maximum is higher, the axis will flex to show all data.
+           *
+           * @sample highcharts/yaxis/softmin-softmax/
+           *         Soft min and max
+           *
+           * @type      {number}
+           * @since     5.0.1
+           * @product   highcharts highstock gantt
+           * @apioption xAxis.softMax
+           */
+          /**
+           * A soft minimum for the axis. If the series data minimum is greater
+           * than this, the axis will stay at this minimum, but if the series
+           * data minimum is lower, the axis will flex to show all data.
+           *
+           * @sample highcharts/yaxis/softmin-softmax/
+           *         Soft min and max
+           *
+           * @type      {number}
+           * @since     5.0.1
+           * @product   highcharts highstock gantt
+           * @apioption xAxis.softMin
+           */
+          /**
+           * For datetime axes, this decides where to put the tick between weeks.
+           *  0 = Sunday, 1 = Monday.
+           *
+           * @sample {highcharts} highcharts/xaxis/startofweek-monday/
+           *         Monday by default
+           * @sample {highcharts} highcharts/xaxis/startofweek-sunday/
+           *         Sunday
+           * @sample {highstock} stock/xaxis/startofweek-1
+           *         Monday by default
+           * @sample {highstock} stock/xaxis/startofweek-0
+           *         Sunday
+           *
+           * @product highcharts highstock gantt
+           */
+          startOfWeek: 1,
+          /**
+           * Whether to force the axis to start on a tick. Use this option with
+           * the `minPadding` option to control the axis start.
+           *
+           * @productdesc {highstock}
+           * In Highstock, `startOnTick` is always `false` when the navigator
+           * is enabled, to prevent jumpy scrolling.
+           *
+           * @sample {highcharts} highcharts/xaxis/startontick-false/
+           *         False by default
+           * @sample {highcharts} highcharts/xaxis/startontick-true/
+           *         True
+           *
+           * @since 1.2.0
+           */
+          startOnTick: false,
+          /**
+           * The amount of ticks to draw on the axis. This opens up for aligning
+           * the ticks of multiple charts or panes within a chart. This option
+           * overrides the `tickPixelInterval` option.
+           *
+           * This option only has an effect on linear axes. Datetime, logarithmic
+           * or category axes are not affected.
+           *
+           * @sample {highcharts} highcharts/yaxis/tickamount/
+           *         8 ticks on Y axis
+           * @sample {highstock} highcharts/yaxis/tickamount/
+           *         8 ticks on Y axis
+           *
+           * @type      {number}
+           * @since     4.1.0
+           * @product   highcharts highstock gantt
+           * @apioption xAxis.tickAmount
+           */
+          /**
+           * The interval of the tick marks in axis units. When `undefined`, the
+           * tick interval is computed to approximately follow the
+           * [tickPixelInterval](#xAxis.tickPixelInterval) on linear and datetime
+           * axes. On categorized axes, a `undefined` tickInterval will default to
+           * 1, one category. Note that datetime axes are based on milliseconds,
+           * so for example an interval of one day is expressed as
+           * `24 * 3600 * 1000`.
+           *
+           * On logarithmic axes, the tickInterval is based on powers, so a
+           * tickInterval of 1 means one tick on each of 0.1, 1, 10, 100 etc. A
+           * tickInterval of 2 means a tick of 0.1, 10, 1000 etc. A tickInterval
+           * of 0.2 puts a tick on 0.1, 0.2, 0.4, 0.6, 0.8, 1, 2, 4, 6, 8, 10, 20,
+           * 40 etc.
+           *
+           *
+           * If the tickInterval is too dense for labels to be drawn, Highcharts
+           * may remove ticks.
+           *
+           * If the chart has multiple axes, the [alignTicks](#chart.alignTicks)
+           * option may interfere with the `tickInterval` setting.
+           *
+           * @see [tickPixelInterval](#xAxis.tickPixelInterval)
+           * @see [tickPositions](#xAxis.tickPositions)
+           * @see [tickPositioner](#xAxis.tickPositioner)
+           *
+           * @sample {highcharts} highcharts/xaxis/tickinterval-5/
+           *         Tick interval of 5 on a linear axis
+           * @sample {highstock} stock/xaxis/tickinterval/
+           *         Tick interval of 0.01 on Y axis
+           *
+           * @type      {number}
+           * @apioption xAxis.tickInterval
+           */
+          /**
+           * The pixel length of the main tick marks.
+           *
+           * @sample {highcharts} highcharts/xaxis/ticklength/
+           *         20 px tick length on the X axis
+           * @sample {highstock} stock/xaxis/ticks/
+           *         Formatted ticks on X axis
+           */
+          tickLength: 10,
+          /**
+           * If tickInterval is `null` this option sets the approximate pixel
+           * interval of the tick marks. Not applicable to categorized axis.
+           *
+           * The tick interval is also influenced by the [minTickInterval](
+           * #xAxis.minTickInterval) option, that, by default prevents ticks from
+           * being denser than the data points.
+           *
+           * @see [tickInterval](#xAxis.tickInterval)
+           * @see [tickPositioner](#xAxis.tickPositioner)
+           * @see [tickPositions](#xAxis.tickPositions)
+           *
+           * @sample {highcharts} highcharts/xaxis/tickpixelinterval-50/
+           *         50 px on X axis
+           * @sample {highstock} stock/xaxis/tickpixelinterval/
+           *         200 px on X axis
+           */
+          tickPixelInterval: 100,
+          /**
+           * For categorized axes only. If `on` the tick mark is placed in the
+           * center of the category, if `between` the tick mark is placed between
+           * categories. The default is `between` if the `tickInterval` is 1, else
+           * `on`.
+           *
+           * @sample {highcharts} highcharts/xaxis/tickmarkplacement-between/
+           *         "between" by default
+           * @sample {highcharts} highcharts/xaxis/tickmarkplacement-on/
+           *         "on"
+           *
+           * @product    highcharts gantt
+           * @validvalue ["on", "between"]
+           */
+          tickmarkPlacement: "between",
+          /**
+           * The position of the major tick marks relative to the axis line.
+           * Can be one of `inside` and `outside`.
+           *
+           * @sample {highcharts} highcharts/xaxis/tickposition-outside/
+           *         "outside" by default
+           * @sample {highcharts} highcharts/xaxis/tickposition-inside/
+           *         "inside"
+           * @sample {highstock} stock/xaxis/ticks/
+           *         Formatted ticks on X axis
+           *
+           * @validvalue ["inside", "outside"]
+           */
+          tickPosition: "outside",
+          /**
+           * A callback function returning array defining where the ticks are
+           * laid out on the axis. This overrides the default behaviour of
+           * [tickPixelInterval](#xAxis.tickPixelInterval) and [tickInterval](
+           * #xAxis.tickInterval). The automatic tick positions are accessible
+           * through `this.tickPositions` and can be modified by the callback.
+           *
+           * @see [tickPositions](#xAxis.tickPositions)
+           *
+           * @sample {highcharts} highcharts/xaxis/tickpositions-tickpositioner/
+           *         Demo of tickPositions and tickPositioner
+           * @sample {highstock} highcharts/xaxis/tickpositions-tickpositioner/
+           *         Demo of tickPositions and tickPositioner
+           *
+           * @type      {Highcharts.AxisTickPositionerCallbackFunction}
+           * @apioption xAxis.tickPositioner
+           */
+          /**
+           * An array defining where the ticks are laid out on the axis. This
+           * overrides the default behaviour of [tickPixelInterval](
+           * #xAxis.tickPixelInterval) and [tickInterval](#xAxis.tickInterval).
+           *
+           * @see [tickPositioner](#xAxis.tickPositioner)
+           *
+           * @sample {highcharts} highcharts/xaxis/tickpositions-tickpositioner/
+           *         Demo of tickPositions and tickPositioner
+           * @sample {highstock} highcharts/xaxis/tickpositions-tickpositioner/
+           *         Demo of tickPositions and tickPositioner
+           *
+           * @type      {Array<number>}
+           * @apioption xAxis.tickPositions
+           */
+          /**
+           * The pixel width of the major tick marks. Defaults to 0 on category
+           * axes, otherwise 1.
+           *
+           * In styled mode, the stroke width is given in the `.highcharts-tick`
+           * class, but in order for the element to be generated on category axes,
+           * the option must be explicitly set to 1.
+           *
+           * @sample {highcharts} highcharts/xaxis/tickwidth/
+           *         10 px width
+           * @sample {highcharts} highcharts/css/axis-grid/
+           *         Styled mode
+           * @sample {highstock} stock/xaxis/ticks/
+           *         Formatted ticks on X axis
+           * @sample {highstock} highcharts/css/axis-grid/
+           *         Styled mode
+           *
+           * @type      {undefined|number}
+           * @default   {highstock} 1
+           * @default   {highmaps} 0
+           * @apioption xAxis.tickWidth
+           */
+          /**
+           * The axis title, showing next to the axis line.
+           *
+           * @productdesc {highmaps}
+           * In Highmaps, the axis is hidden by default, but adding an axis title
+           * is still possible. X axis and Y axis titles will appear at the bottom
+           * and left by default.
+           */
+          title: {
+            /**
+             * Deprecated. Set the `text` to `null` to disable the title.
              *
-             * @private
-             * @function Highcharts.Series#findPointIndex
-             * @param    {Highcharts.PointOptionsObject} optionsObject
-             *           The options of the point.
-             * @param    {number} fromIndex
-             *           The index to start searching from, used for optimizing
-             *           series with required sorting.
-             * @returns  {number|undefined}
-             *           Returns the index of a matching point, or undefined if no
-             *           match is found.
+             * @deprecated
+             * @type      {boolean}
+             * @product   highcharts
+             * @apioption xAxis.title.enabled
              */
-            findPointIndex: function (optionsObject, fromIndex) {
-                var id = optionsObject.id,
-                    x = optionsObject.x,
-                    oldData = this.points,
-                    matchingPoint,
-                    matchedById,
-                    pointIndex,
-                    matchKey,
-                    dataSorting = this.options.dataSorting;
-                if (id) {
-                    matchingPoint = this.chart.get(id);
-                }
-                else if (this.linkedParent || this.enabledDataSorting) {
-                    matchKey = (dataSorting && dataSorting.matchByName) ?
-                        'name' : 'index';
-                    matchingPoint = find(oldData, function (oldPoint) {
-                        return !oldPoint.touched && oldPoint[matchKey] ===
-                            optionsObject[matchKey];
-                    });
-                    // Add unmatched point as a new point
-                    if (!matchingPoint) {
-                        return void 0;
-                    }
-                }
-                if (matchingPoint) {
-                    pointIndex = matchingPoint && matchingPoint.index;
-                    if (typeof pointIndex !== 'undefined') {
-                        matchedById = true;
-                    }
-                }
-                // Search for the same X in the existing data set
-                if (typeof pointIndex === 'undefined' && isNumber(x)) {
-                    pointIndex = this.xData.indexOf(x, fromIndex);
-                }
-                // Reduce pointIndex if data is cropped
-                if (pointIndex !== -1 &&
-                    typeof pointIndex !== 'undefined' &&
-                    this.cropped) {
-                    pointIndex = (pointIndex >= this.cropStart) ?
-                        pointIndex - this.cropStart : pointIndex;
-                }
-                if (!matchedById &&
-                    oldData[pointIndex] && oldData[pointIndex].touched) {
-                    pointIndex = void 0;
-                }
-                return pointIndex;
-            },
             /**
-             * @private
-             * @borrows LegendSymbolMixin.drawLineMarker as Highcharts.Series#drawLegendSymbol
+             * The pixel distance between the axis labels or line and the title.
+             * Defaults to 0 for horizontal axes, 10 for vertical
+             *
+             * @sample {highcharts} highcharts/xaxis/title-margin/
+             *         Y axis title margin of 60
+             *
+             * @type      {number}
+             * @apioption xAxis.title.margin
              */
-            drawLegendSymbol: LegendSymbolMixin.drawLineMarker,
             /**
-             * Internal function called from setData. If the point count is the same
-             * as is was, or if there are overlapping X values, just run
-             * Point.update which is cheaper, allows animation, and keeps references
-             * to points. This also allows adding or removing points if the X-es
-             * don't match.
+             * The distance of the axis title from the axis line. By default,
+             * this distance is computed from the offset width of the labels,
+             * the labels' distance from the axis and the title's margin.
+             * However when the offset option is set, it overrides all this.
              *
-             * @private
-             * @function Highcharts.Series#updateData
+             * @sample {highcharts} highcharts/yaxis/title-offset/
+             *         Place the axis title on top of the axis
+             * @sample {highstock} highcharts/yaxis/title-offset/
+             *         Place the axis title on top of the Y axis
              *
-             * @param {Array<Highcharts.PointOptionsType>} data
+             * @type      {number}
+             * @since     2.2.0
+             * @apioption xAxis.title.offset
+             */
+            /**
+             * Whether to reserve space for the title when laying out the axis.
              *
-             * @return {boolean}
+             * @type      {boolean}
+             * @default   true
+             * @since     5.0.11
+             * @product   highcharts highstock gantt
+             * @apioption xAxis.title.reserveSpace
              */
-            updateData: function (data, animation) {
-                var options = this.options,
-                    dataSorting = options.dataSorting,
-                    oldData = this.points,
-                    pointsToAdd = [],
-                    hasUpdatedByKey,
-                    i,
-                    point,
-                    lastIndex,
-                    requireSorting = this.requireSorting,
-                    equalLength = data.length === oldData.length,
-                    succeeded = true;
-                this.xIncrement = null;
-                // Iterate the new data
-                data.forEach(function (pointOptions, i) {
-                    var id,
-                        x,
-                        pointIndex,
-                        optionsObject = (defined(pointOptions) &&
-                            this.pointClass.prototype.optionsToObject.call({ series: this },
-                        pointOptions)) || {};
-                    // Get the x of the new data point
-                    x = optionsObject.x;
-                    id = optionsObject.id;
-                    if (id || isNumber(x)) {
-                        pointIndex = this.findPointIndex(optionsObject, lastIndex);
-                        // Matching X not found
-                        // or used already due to ununique x values (#8995),
-                        // add point (but later)
-                        if (pointIndex === -1 ||
-                            typeof pointIndex === 'undefined') {
-                            pointsToAdd.push(pointOptions);
-                            // Matching X found, update
-                        }
-                        else if (oldData[pointIndex] &&
-                            pointOptions !== options.data[pointIndex]) {
-                            oldData[pointIndex].update(pointOptions, false, null, false);
-                            // Mark it touched, below we will remove all points that
-                            // are not touched.
-                            oldData[pointIndex].touched = true;
-                            // Speed optimize by only searching after last known
-                            // index. Performs ~20% bettor on large data sets.
-                            if (requireSorting) {
-                                lastIndex = pointIndex + 1;
-                            }
-                            // Point exists, no changes, don't remove it
-                        }
-                        else if (oldData[pointIndex]) {
-                            oldData[pointIndex].touched = true;
-                        }
-                        // If the length is equal and some of the nodes had a
-                        // match in the same position, we don't want to remove
-                        // non-matches.
-                        if (!equalLength ||
-                            i !== pointIndex ||
-                            (dataSorting && dataSorting.enabled) ||
-                            this.hasDerivedData) {
-                            hasUpdatedByKey = true;
-                        }
-                    }
-                    else {
-                        // Gather all points that are not matched
-                        pointsToAdd.push(pointOptions);
-                    }
-                }, this);
-                // Remove points that don't exist in the updated data set
-                if (hasUpdatedByKey) {
-                    i = oldData.length;
-                    while (i--) {
-                        point = oldData[i];
-                        if (point && !point.touched && point.remove) {
-                            point.remove(false, animation);
-                        }
-                    }
-                    // If we did not find keys (ids or x-values), and the length is the
-                    // same, update one-to-one
-                }
-                else if (equalLength && (!dataSorting || !dataSorting.enabled)) {
-                    data.forEach(function (point, i) {
-                        // .update doesn't exist on a linked, hidden series (#3709)
-                        // (#10187)
-                        if (oldData[i].update && point !== oldData[i].y) {
-                            oldData[i].update(point, false, null, false);
-                        }
-                    });
-                    // Don't add new points since those configs are used above
-                    pointsToAdd.length = 0;
-                    // Did not succeed in updating data
-                }
-                else {
-                    succeeded = false;
-                }
-                oldData.forEach(function (point) {
-                    if (point) {
-                        point.touched = false;
-                    }
-                });
-                if (!succeeded) {
-                    return false;
-                }
-                // Add new points
-                pointsToAdd.forEach(function (point) {
-                    this.addPoint(point, false, null, null, false);
-                }, this);
-                if (this.xIncrement === null &&
-                    this.xData &&
-                    this.xData.length) {
-                    this.xIncrement = arrayMax(this.xData);
-                    this.autoIncrement();
-                }
-                return true;
-            },
             /**
-             * Apply a new set of data to the series and optionally redraw it. The
-             * new data array is passed by reference (except in case of
-             * `updatePoints`), and may later be mutated when updating the chart
-             * data.
-             *
-             * Note the difference in behaviour when setting the same amount of
-             * points, or a different amount of points, as handled by the
-             * `updatePoints` parameter.
-             *
-             * @sample highcharts/members/series-setdata/
-             *         Set new data from a button
-             * @sample highcharts/members/series-setdata-pie/
-             *         Set data in a pie
-             * @sample stock/members/series-setdata/
-             *         Set new data in Highstock
-             * @sample maps/members/series-setdata/
-             *         Set new data in Highmaps
-             *
-             * @function Highcharts.Series#setData
-             *
-             * @param {Array<Highcharts.PointOptionsType>} data
-             *        Takes an array of data in the same format as described under
-             *        `series.{type}.data` for the given series type, for example a
-             *        line series would take data in the form described under
-             *        [series.line.data](https://api.highcharts.com/highcharts/series.line.data).
-             *
-             * @param {boolean} [redraw=true]
-             *        Whether to redraw the chart after the series is altered. If
-             *        doing more operations on the chart, it is a good idea to set
-             *        redraw to false and call {@link Chart#redraw} after.
-             *
-             * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation]
-             *        When the updated data is the same length as the existing data,
-             *        points will be updated by default, and animation visualizes
-             *        how the points are changed. Set false to disable animation, or
-             *        a configuration object to set duration or easing.
-             *
-             * @param {boolean} [updatePoints=true]
-             *        When this is true, points will be updated instead of replaced
-             *        whenever possible. This occurs a) when the updated data is the
-             *        same length as the existing data, b) when points are matched
-             *        by their id's, or c) when points can be matched by X values.
-             *        This allows updating with animation and performs better. In
-             *        this case, the original array is not passed by reference. Set
-             *        `false` to prevent.
-             *
-             * @return {void}
+             * The rotation of the text in degrees. 0 is horizontal, 270 is
+             * vertical reading from bottom to top.
+             *
+             * @sample {highcharts} highcharts/yaxis/title-offset/
+             *         Horizontal
+             *
+             * @type      {number}
+             * @default   0
+             * @apioption xAxis.title.rotation
              */
-            setData: function (data, redraw, animation, updatePoints) {
-                var series = this,
-                    oldData = series.points,
-                    oldDataLength = (oldData && oldData.length) || 0,
-                    dataLength,
-                    options = series.options,
-                    chart = series.chart,
-                    dataSorting = options.dataSorting,
-                    firstPoint = null,
-                    xAxis = series.xAxis,
-                    i,
-                    turboThreshold = options.turboThreshold,
-                    pt,
-                    xData = this.xData,
-                    yData = this.yData,
-                    pointArrayMap = series.pointArrayMap,
-                    valueCount = pointArrayMap && pointArrayMap.length,
-                    keys = options.keys,
-                    indexOfX = 0,
-                    indexOfY = 1,
-                    updatedData;
-                data = data || [];
-                dataLength = data.length;
-                redraw = pick(redraw, true);
-                if (dataSorting && dataSorting.enabled) {
-                    data = this.sortData(data);
-                }
-                // First try to run Point.update which is cheaper, allows animation,
-                // and keeps references to points.
-                if (updatePoints !== false &&
-                    dataLength &&
-                    oldDataLength &&
-                    !series.cropped &&
-                    !series.hasGroupedData &&
-                    series.visible &&
-                    // Soft updating has no benefit in boost, and causes JS error
-                    // (#8355)
-                    !series.isSeriesBoosting) {
-                    updatedData = this.updateData(data, animation);
-                }
-                if (!updatedData) {
-                    // Reset properties
-                    series.xIncrement = null;
-                    series.colorCounter = 0; // for series with colorByPoint (#1547)
-                    // Update parallel arrays
-                    this.parallelArrays.forEach(function (key) {
-                        series[key + 'Data'].length = 0;
-                    });
-                    // In turbo mode, only one- or twodimensional arrays of numbers
-                    // are allowed. The first value is tested, and we assume that
-                    // all the rest are defined the same way. Although the 'for'
-                    // loops are similar, they are repeated inside each if-else
-                    // conditional for max performance.
-                    if (turboThreshold && dataLength > turboThreshold) {
-                        firstPoint = series.getFirstValidPoint(data);
-                        if (isNumber(firstPoint)) { // assume all points are numbers
-                            for (i = 0; i < dataLength; i++) {
-                                xData[i] = this.autoIncrement();
-                                yData[i] = data[i];
-                            }
-                            // Assume all points are arrays when first point is
-                        }
-                        else if (isArray(firstPoint)) {
-                            if (valueCount) { // [x, low, high] or [x, o, h, l, c]
-                                for (i = 0; i < dataLength; i++) {
-                                    pt = data[i];
-                                    xData[i] = pt[0];
-                                    yData[i] =
-                                        pt.slice(1, valueCount + 1);
-                                }
-                            }
-                            else { // [x, y]
-                                if (keys) {
-                                    indexOfX = keys.indexOf('x');
-                                    indexOfY = keys.indexOf('y');
-                                    indexOfX = indexOfX >= 0 ? indexOfX : 0;
-                                    indexOfY = indexOfY >= 0 ? indexOfY : 1;
-                                }
-                                for (i = 0; i < dataLength; i++) {
-                                    pt = data[i];
-                                    xData[i] = pt[indexOfX];
-                                    yData[i] = pt[indexOfY];
-                                }
-                            }
-                        }
-                        else {
-                            // Highcharts expects configs to be numbers or arrays in
-                            // turbo mode
-                            error(12, false, chart);
-                        }
-                    }
-                    else {
-                        for (i = 0; i < dataLength; i++) {
-                            // stray commas in oldIE:
-                            if (typeof data[i] !== 'undefined') {
-                                pt = { series: series };
-                                series.pointClass.prototype.applyOptions.apply(pt, [data[i]]);
-                                series.updateParallelArrays(pt, i);
-                            }
-                        }
-                    }
-                    // Forgetting to cast strings to numbers is a common caveat when
-                    // handling CSV or JSON
-                    if (yData && isString(yData[0])) {
-                        error(14, true, chart);
-                    }
-                    series.data = [];
-                    series.options.data = series.userOptions.data = data;
-                    // destroy old points
-                    i = oldDataLength;
-                    while (i--) {
-                        if (oldData[i] && oldData[i].destroy) {
-                            oldData[i].destroy();
-                        }
-                    }
-                    // reset minRange (#878)
-                    if (xAxis) {
-                        xAxis.minRange = xAxis.userMinRange;
-                    }
-                    // redraw
-                    series.isDirty = chart.isDirtyBox = true;
-                    series.isDirtyData = !!oldData;
-                    animation = false;
-                }
-                // Typically for pie series, points need to be processed and
-                // generated prior to rendering the legend
-                if (options.legendType === 'point') {
-                    this.processData();
-                    this.generatePoints();
-                }
-                if (redraw) {
-                    chart.redraw(animation);
-                }
-            },
             /**
-             * Internal function to sort series data
+             * The actual text of the axis title. It can contain basic HTML tags
+             * like `b`, `i` and `span` with style.
              *
-             * @private
-             * @function Highcharts.Series#sortData
-             * @param {Array<Highcharts.PointOptionsType>} data
-             *        Force data grouping.
-             * @return {Array<Highcharts.PointOptionsObject>}
+             * @sample {highcharts} highcharts/xaxis/title-text/
+             *         Custom HTML
+             * @sample {highstock} stock/xaxis/title-text/
+             *         Titles for both axes
+             *
+             * @type      {string|null}
+             * @apioption xAxis.title.text
              */
-            sortData: function (data) {
-                var series = this,
-                    options = series.options,
-                    dataSorting = options.dataSorting,
-                    sortKey = dataSorting.sortKey || 'y',
-                    sortedData,
-                    getPointOptionsObject = function (series,
-                    pointOptions) {
-                        return (defined(pointOptions) &&
-                            series.pointClass.prototype.optionsToObject.call({
-                                series: series
-                            },
-                    pointOptions)) || {};
-                };
-                data.forEach(function (pointOptions, i) {
-                    data[i] = getPointOptionsObject(series, pointOptions);
-                    data[i].index = i;
-                }, this);
-                // Sorting
-                sortedData = data.concat().sort(function (a, b) {
-                    var aValue = getNestedProperty(sortKey,
-                        a);
-                    var bValue = getNestedProperty(sortKey,
-                        b);
-                    return bValue < aValue ? -1 : bValue > aValue ? 1 : 0;
-                });
-                // Set x value depending on the position in the array
-                sortedData.forEach(function (point, i) {
-                    point.x = i;
-                }, this);
-                // Set the same x for linked series points if they don't have their
-                // own sorting
-                if (series.linkedSeries) {
-                    series.linkedSeries.forEach(function (linkedSeries) {
-                        var options = linkedSeries.options,
-                            seriesData = options.data;
-                        if ((!options.dataSorting ||
-                            !options.dataSorting.enabled) &&
-                            seriesData) {
-                            seriesData.forEach(function (pointOptions, i) {
-                                seriesData[i] = getPointOptionsObject(linkedSeries, pointOptions);
-                                if (data[i]) {
-                                    seriesData[i].x = data[i].x;
-                                    seriesData[i].index = i;
-                                }
-                            });
-                            linkedSeries.setData(seriesData, false);
-                        }
-                    });
-                }
-                return data;
-            },
             /**
-             * Internal function to process the data by cropping away unused data
-             * points if the series is longer than the crop threshold. This saves
-             * computing time for large series.
+             * Alignment of the text, can be `"left"`, `"right"` or `"center"`.
+             * Default alignment depends on the
+             * [title.align](xAxis.title.align):
              *
-             * @private
-             * @function Highcharts.Series#getProcessedData
-             * @param {boolean} [forceExtremesFromAll]
-             *        Force getting extremes of a total series data range.
-             * @return {Highcharts.SeriesProcessedDataObject}
+             * Horizontal axes:
+             * - for `align` = `"low"`, `textAlign` is set to `left`
+             * - for `align` = `"middle"`, `textAlign` is set to `center`
+             * - for `align` = `"high"`, `textAlign` is set to `right`
+             *
+             * Vertical axes:
+             * - for `align` = `"low"` and `opposite` = `true`, `textAlign` is
+             *   set to `right`
+             * - for `align` = `"low"` and `opposite` = `false`, `textAlign` is
+             *   set to `left`
+             * - for `align` = `"middle"`, `textAlign` is set to `center`
+             * - for `align` = `"high"` and `opposite` = `true` `textAlign` is
+             *   set to `left`
+             * - for `align` = `"high"` and `opposite` = `false` `textAlign` is
+             *   set to `right`
+             *
+             * @type      {Highcharts.AlignValue}
+             * @apioption xAxis.title.textAlign
              */
-            getProcessedData: function (forceExtremesFromAll) {
-                var series = this, 
-                    // copied during slice operation:
-                    processedXData = series.xData,
-                    processedYData = series.yData,
-                    dataLength = processedXData.length,
-                    croppedData,
-                    cropStart = 0,
-                    cropped,
-                    distance,
-                    closestPointRange,
-                    xAxis = series.xAxis,
-                    i, // loop variable
-                    options = series.options,
-                    cropThreshold = options.cropThreshold,
-                    getExtremesFromAll = forceExtremesFromAll ||
-                        series.getExtremesFromAll ||
-                        options.getExtremesFromAll, // #4599
-                    isCartesian = series.isCartesian,
-                    xExtremes,
-                    val2lin = xAxis && xAxis.val2lin,
-                    isLog = !!(xAxis && xAxis.logarithmic),
-                    throwOnUnsorted = series.requireSorting,
-                    min,
-                    max;
-                if (xAxis) {
-                    // corrected for log axis (#3053)
-                    xExtremes = xAxis.getExtremes();
-                    min = xExtremes.min;
-                    max = xExtremes.max;
-                }
-                // optionally filter out points outside the plot area
-                if (isCartesian &&
-                    series.sorted &&
-                    !getExtremesFromAll &&
-                    (!cropThreshold ||
-                        dataLength > cropThreshold ||
-                        series.forceCrop)) {
-                    // it's outside current extremes
-                    if (processedXData[dataLength - 1] < min ||
-                        processedXData[0] > max) {
-                        processedXData = [];
-                        processedYData = [];
-                        // only crop if it's actually spilling out
-                    }
-                    else if (series.yData && (processedXData[0] < min ||
-                        processedXData[dataLength - 1] > max)) {
-                        croppedData = this.cropData(series.xData, series.yData, min, max);
-                        processedXData = croppedData.xData;
-                        processedYData = croppedData.yData;
-                        cropStart = croppedData.start;
-                        cropped = true;
-                    }
-                }
-                // Find the closest distance between processed points
-                i = processedXData.length || 1;
-                while (--i) {
-                    distance = (isLog ?
-                        (val2lin(processedXData[i]) -
-                            val2lin(processedXData[i - 1])) :
-                        (processedXData[i] -
-                            processedXData[i - 1]));
-                    if (distance > 0 &&
-                        (typeof closestPointRange === 'undefined' ||
-                            distance < closestPointRange)) {
-                        closestPointRange = distance;
-                        // Unsorted data is not supported by the line tooltip, as well
-                        // as data grouping and navigation in Stock charts (#725) and
-                        // width calculation of columns (#1900)
-                    }
-                    else if (distance < 0 && throwOnUnsorted) {
-                        error(15, false, series.chart);
-                        throwOnUnsorted = false; // Only once
-                    }
-                }
-                return {
-                    xData: processedXData,
-                    yData: processedYData,
-                    cropped: cropped,
-                    cropStart: cropStart,
-                    closestPointRange: closestPointRange
-                };
-            },
             /**
-             * Internal function to apply processed data.
-             * In Highstock, this function is extended to provide data grouping.
+             * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html)
+             * to render the axis title.
              *
-             * @private
-             * @function Highcharts.Series#processData
-             * @param {boolean} [force]
-             *        Force data grouping.
-             * @return {boolean|undefined}
+             * @type      {boolean}
+             * @default   false
+             * @product   highcharts highstock gantt
+             * @apioption xAxis.title.useHTML
              */
-            processData: function (force) {
-                var series = this,
-                    xAxis = series.xAxis,
-                    processedData;
-                // If the series data or axes haven't changed, don't go through
-                // this. Return false to pass the message on to override methods
-                // like in data grouping.
-                if (series.isCartesian &&
-                    !series.isDirty &&
-                    !xAxis.isDirty &&
-                    !series.yAxis.isDirty &&
-                    !force) {
-                    return false;
-                }
-                processedData = series.getProcessedData();
-                // Record the properties
-                series.cropped = processedData.cropped; // undefined or true
-                series.cropStart = processedData.cropStart;
-                series.processedXData = processedData.xData;
-                series.processedYData = processedData.yData;
-                series.closestPointRange =
-                    series.basePointRange = processedData.closestPointRange;
-            },
             /**
-             * Iterate over xData and crop values between min and max. Returns
-             * object containing crop start/end cropped xData with corresponding
-             * part of yData, dataMin and dataMax within the cropped range.
+             * Horizontal pixel offset of the title position.
              *
-             * @private
-             * @function Highcharts.Series#cropData
-             * @param {Array<number>} xData
-             * @param {Array<number>} yData
-             * @param {number} min
-             * @param {number} max
-             * @param {number} [cropShoulder]
-             * @return {Highcharts.SeriesCropDataObject}
+             * @type      {number}
+             * @default   0
+             * @since     4.1.6
+             * @product   highcharts highstock gantt
+             * @apioption xAxis.title.x
              */
-            cropData: function (xData, yData, min, max, cropShoulder) {
-                var dataLength = xData.length,
-                    cropStart = 0,
-                    cropEnd = dataLength,
-                    i,
-                    j;
-                // line-type series need one point outside
-                cropShoulder = pick(cropShoulder, this.cropShoulder);
-                // iterate up to find slice start
-                for (i = 0; i < dataLength; i++) {
-                    if (xData[i] >= min) {
-                        cropStart = Math.max(0, i - cropShoulder);
-                        break;
-                    }
-                }
-                // proceed to find slice end
-                for (j = i; j < dataLength; j++) {
-                    if (xData[j] > max) {
-                        cropEnd = j + cropShoulder;
-                        break;
-                    }
-                }
-                return {
-                    xData: xData.slice(cropStart, cropEnd),
-                    yData: yData.slice(cropStart, cropEnd),
-                    start: cropStart,
-                    end: cropEnd
-                };
-            },
             /**
-             * Generate the data point after the data has been processed by cropping
-             * away unused points and optionally grouped in Highcharts Stock.
+             * Vertical pixel offset of the title position.
              *
-             * @private
-             * @function Highcharts.Series#generatePoints
+             * @type      {number}
+             * @product   highcharts highstock gantt
+             * @apioption xAxis.title.y
              */
-            generatePoints: function () {
-                var series = this,
-                    options = series.options,
-                    dataOptions = options.data,
-                    data = series.data,
-                    dataLength,
-                    processedXData = series.processedXData,
-                    processedYData = series.processedYData,
-                    PointClass = series.pointClass,
-                    processedDataLength = processedXData.length,
-                    cropStart = series.cropStart || 0,
-                    cursor,
-                    hasGroupedData = series.hasGroupedData,
-                    keys = options.keys,
-                    point,
-                    points = [],
-                    i;
-                if (!data && !hasGroupedData) {
-                    var arr = [];
-                    arr.length = dataOptions.length;
-                    data = series.data = arr;
-                }
-                if (keys && hasGroupedData) {
-                    // grouped data has already applied keys (#6590)
-                    series.options.keys = false;
-                }
-                for (i = 0; i < processedDataLength; i++) {
-                    cursor = cropStart + i;
-                    if (!hasGroupedData) {
-                        point = data[cursor];
-                        // #970:
-                        if (!point &&
-                            typeof dataOptions[cursor] !== 'undefined') {
-                            data[cursor] = point = (new PointClass()).init(series, dataOptions[cursor], processedXData[i]);
-                        }
-                    }
-                    else {
-                        // splat the y data in case of ohlc data array
-                        point = (new PointClass()).init(series, [processedXData[i]].concat(splat(processedYData[i])));
-                        /**
-                         * Highstock only. If a point object is created by data
-                         * grouping, it doesn't reflect actual points in the raw
-                         * data. In this case, the `dataGroup` property holds
-                         * information that points back to the raw data.
-                         *
-                         * - `dataGroup.start` is the index of the first raw data
-                         *   point in the group.
-                         *
-                         * - `dataGroup.length` is the amount of points in the
-                         *   group.
-                         *
-                         * @product highstock
-                         *
-                         * @name Highcharts.Point#dataGroup
-                         * @type {Highcharts.DataGroupingInfoObject|undefined}
-                         */
-                        point.dataGroup = series.groupMap[i];
-                        if (point.dataGroup.options) {
-                            point.options = point.dataGroup.options;
-                            extend(point, point.dataGroup.options);
-                            // Collision of props and options (#9770)
-                            delete point.dataLabels;
-                        }
-                    }
-                    if (point) { // #6279
-                        /**
-                         * Contains the point's index in the `Series.points` array.
-                         *
-                         * @name Highcharts.Point#index
-                         * @type {number}
-                         * @readonly
-                         */
-                        point.index = cursor; // For faster access in Point.update
-                        points[i] = point;
-                    }
-                }
-                // restore keys options (#6590)
-                series.options.keys = keys;
-                // Hide cropped-away points - this only runs when the number of
-                // points is above cropThreshold, or when swithching view from
-                // non-grouped data to grouped data (#637)
-                if (data &&
-                    (processedDataLength !== (dataLength = data.length) ||
-                        hasGroupedData)) {
-                    for (i = 0; i < dataLength; i++) {
-                        // when has grouped data, clear all points
-                        if (i === cropStart && !hasGroupedData) {
-                            i += processedDataLength;
-                        }
-                        if (data[i]) {
-                            data[i].destroyElements();
-                            data[i].plotX = void 0; // #1003
-                        }
-                    }
-                }
-                /**
-                 * Read only. An array containing those values converted to points.
-                 * In case the series data length exceeds the `cropThreshold`, or if
-                 * the data is grouped, `series.data` doesn't contain all the
-                 * points. Also, in case a series is hidden, the `data` array may be
-                 * empty. To access raw values, `series.options.data` will always be
-                 * up to date. `Series.data` only contains the points that have been
-                 * created on demand. To modify the data, use
-                 * {@link Highcharts.Series#setData} or
-                 * {@link Highcharts.Point#update}.
-                 *
-                 * @see Series.points
-                 *
-                 * @name Highcharts.Series#data
-                 * @type {Array<Highcharts.Point>}
-                 */
-                series.data = data;
-                /**
-                 * An array containing all currently visible point objects. In case
-                 * of cropping, the cropped-away points are not part of this array.
-                 * The `series.points` array starts at `series.cropStart` compared
-                 * to `series.data` and `series.options.data`. If however the series
-                 * data is grouped, these can't be correlated one to one. To modify
-                 * the data, use {@link Highcharts.Series#setData} or
-                 * {@link Highcharts.Point#update}.
-                 *
-                 * @name Highcharts.Series#points
-                 * @type {Array<Highcharts.Point>}
-                 */
-                series.points = points;
-                fireEvent(this, 'afterGeneratePoints');
-            },
             /**
-             * Get current X extremes for the visible data.
+             * Alignment of the title relative to the axis values. Possible
+             * values are "low", "middle" or "high".
              *
-             * @private
-             * @function Highcharts.Series#getXExtremes
+             * @sample {highcharts} highcharts/xaxis/title-align-low/
+             *         "low"
+             * @sample {highcharts} highcharts/xaxis/title-align-center/
+             *         "middle" by default
+             * @sample {highcharts} highcharts/xaxis/title-align-high/
+             *         "high"
+             * @sample {highcharts} highcharts/yaxis/title-offset/
+             *         Place the Y axis title on top of the axis
+             * @sample {highstock} stock/xaxis/title-align/
+             *         Aligned to "high" value
              *
-             * @param {Array<number>} xData
-             *        The data to inspect. Defaults to the current data within the
-             *        visible range.
-             * @return {Highcharts.RangeObject}
+             * @type {Highcharts.AxisTitleAlignValue}
              */
-            getXExtremes: function (xData) {
-                return {
-                    min: arrayMin(xData),
-                    max: arrayMax(xData)
-                };
-            },
+            align: "middle",
             /**
-             * Calculate Y extremes for the visible data. The result is returned
-             * as an object with `dataMin` and `dataMax` properties.
+             * CSS styles for the title. If the title text is longer than the
+             * axis length, it will wrap to multiple lines by default. This can
+             * be customized by setting `textOverflow: 'ellipsis'`, by
+             * setting a specific `width` or by setting `whiteSpace: 'nowrap'`.
              *
-             * @private
-             * @function Highcharts.Series#getExtremes
-             * @param {Array<number>} [yData]
-             *        The data to inspect. Defaults to the current data within the
-             *        visible range.
-             * @param {boolean} [forceExtremesFromAll]
-             *        Force getting extremes of a total series data range.
-             * @return {Highcharts.DataExtremesObject}
+             * In styled mode, the stroke width is given in the
+             * `.highcharts-axis-title` class.
+             *
+             * @sample {highcharts} highcharts/xaxis/title-style/
+             *         Red
+             * @sample {highcharts} highcharts/css/axis/
+             *         Styled mode
+             *
+             * @type    {Highcharts.CSSObject}
              */
-            getExtremes: function (yData, forceExtremesFromAll) {
-                var xAxis = this.xAxis,
-                    yAxis = this.yAxis,
-                    xData = this.processedXData || this.xData,
-                    yDataLength,
-                    activeYData = [],
-                    activeCounter = 0, 
-                    // #2117, need to compensate for log X axis
-                    xExtremes,
-                    xMin = 0,
-                    xMax = 0,
-                    validValue,
-                    withinRange, 
-                    // Handle X outside the viewed area. This does not work with
-                    // non-sorted data like scatter (#7639).
-                    shoulder = this.requireSorting ? this.cropShoulder : 0,
-                    positiveValuesOnly = yAxis ? yAxis.positiveValuesOnly : false,
-                    x,
-                    y,
-                    i,
-                    j;
-                yData = yData || this.stackedYData || this.processedYData || [];
-                yDataLength = yData.length;
-                if (xAxis) {
-                    xExtremes = xAxis.getExtremes();
-                    xMin = xExtremes.min;
-                    xMax = xExtremes.max;
-                }
-                for (i = 0; i < yDataLength; i++) {
-                    x = xData[i];
-                    y = yData[i];
-                    // For points within the visible range, including the first
-                    // point outside the visible range (#7061), consider y extremes.
-                    validValue = ((isNumber(y) || isArray(y)) &&
-                        ((y.length || y > 0) || !positiveValuesOnly));
-                    withinRange = (forceExtremesFromAll ||
-                        this.getExtremesFromAll ||
-                        this.options.getExtremesFromAll ||
-                        this.cropped ||
-                        !xAxis || // for colorAxis support
-                        ((xData[i + shoulder] || x) >= xMin &&
-                            (xData[i - shoulder] || x) <= xMax));
-                    if (validValue && withinRange) {
-                        j = y.length;
-                        if (j) { // array, like ohlc or range data
-                            while (j--) {
-                                if (isNumber(y[j])) { // #7380, #11513
-                                    activeYData[activeCounter++] = y[j];
-                                }
-                            }
-                        }
-                        else {
-                            activeYData[activeCounter++] = y;
-                        }
-                    }
-                }
-                var dataExtremes = {
-                        dataMin: arrayMin(activeYData),
-                        dataMax: arrayMax(activeYData)
-                    };
-                fireEvent(this, 'afterGetExtremes', { dataExtremes: dataExtremes });
-                return dataExtremes;
+            style: {
+              /** @internal */
+              color: "#666666",
             },
+          },
+          /**
+           * The type of axis. Can be one of `linear`, `logarithmic`, `datetime`
+           * or `category`. In a datetime axis, the numbers are given in
+           * milliseconds, and tick marks are placed on appropriate values like
+           * full hours or days. In a category axis, the
+           * [point names](#series.line.data.name) of the chart's series are used
+           * for categories, if not a [categories](#xAxis.categories) array is
+           * defined.
+           *
+           * @sample {highcharts} highcharts/xaxis/type-linear/
+           *         Linear
+           * @sample {highcharts} highcharts/yaxis/type-log/
+           *         Logarithmic
+           * @sample {highcharts} highcharts/yaxis/type-log-minorgrid/
+           *         Logarithmic with minor grid lines
+           * @sample {highcharts} highcharts/xaxis/type-log-both/
+           *         Logarithmic on two axes
+           * @sample {highcharts} highcharts/yaxis/type-log-negative/
+           *         Logarithmic with extension to emulate negative values
+           *
+           * @type    {Highcharts.AxisTypeValue}
+           * @product highcharts gantt
+           */
+          type: "linear",
+          /**
+           * If there are multiple axes on the same side of the chart, the pixel
+           * margin between the axes. Defaults to 0 on vertical axes, 15 on
+           * horizontal axes.
+           *
+           * @type      {number}
+           * @since     7.0.3
+           * @apioption xAxis.margin
+           */
+          /**
+           * Applies only when the axis `type` is `category`. When `uniqueNames`
+           * is true, points are placed on the X axis according to their names.
+           * If the same point name is repeated in the same or another series,
+           * the point is placed on the same X position as other points of the
+           * same name. When `uniqueNames` is false, the points are laid out in
+           * increasing X positions regardless of their names, and the X axis
+           * category will take the name of the last point in each position.
+           *
+           * @sample {highcharts} highcharts/xaxis/uniquenames-true/
+           *         True by default
+           * @sample {highcharts} highcharts/xaxis/uniquenames-false/
+           *         False
+           *
+           * @type      {boolean}
+           * @default   true
+           * @since     4.2.7
+           * @product   highcharts gantt
+           * @apioption xAxis.uniqueNames
+           */
+          /**
+           * Datetime axis only. An array determining what time intervals the
+           * ticks are allowed to fall on. Each array item is an array where the
+           * first value is the time unit and the second value another array of
+           * allowed multiples.
+           *
+           * Defaults to:
+           * ```js
+           * units: [[
+           *     'millisecond', // unit name
+           *     [1, 2, 5, 10, 20, 25, 50, 100, 200, 500] // allowed multiples
+           * ], [
+           *     'second',
+           *     [1, 2, 5, 10, 15, 30]
+           * ], [
+           *     'minute',
+           *     [1, 2, 5, 10, 15, 30]
+           * ], [
+           *     'hour',
+           *     [1, 2, 3, 4, 6, 8, 12]
+           * ], [
+           *     'day',
+           *     [1]
+           * ], [
+           *     'week',
+           *     [1]
+           * ], [
+           *     'month',
+           *     [1, 3, 6]
+           * ], [
+           *     'year',
+           *     null
+           * ]]
+           * ```
+           *
+           * @type      {Array<Array<string,(Array<number>|null)>>}
+           * @product   highcharts highstock gantt
+           * @apioption xAxis.units
+           */
+          /**
+           * Whether axis, including axis title, line, ticks and labels, should
+           * be visible.
+           *
+           * @type      {boolean}
+           * @default   true
+           * @since     4.1.9
+           * @product   highcharts highstock gantt
+           * @apioption xAxis.visible
+           */
+          /**
+           * Color of the minor, secondary grid lines.
+           *
+           * In styled mode, the stroke width is given in the
+           * `.highcharts-minor-grid-line` class.
+           *
+           * @sample {highcharts} highcharts/yaxis/minorgridlinecolor/
+           *         Bright grey lines from Y axis
+           * @sample {highcharts|highstock} highcharts/css/axis-grid/
+           *         Styled mode
+           * @sample {highstock} stock/xaxis/minorgridlinecolor/
+           *         Bright grey lines from Y axis
+           *
+           * @type    {Highcharts.ColorType}
+           * @default #f2f2f2
+           */
+          minorGridLineColor: "#f2f2f2",
+          /**
+           * Width of the minor, secondary grid lines.
+           *
+           * In styled mode, the stroke width is given in the
+           * `.highcharts-grid-line` class.
+           *
+           * @sample {highcharts} highcharts/yaxis/minorgridlinewidth/
+           *         2px lines from Y axis
+           * @sample {highcharts|highstock} highcharts/css/axis-grid/
+           *         Styled mode
+           * @sample {highstock} stock/xaxis/minorgridlinewidth/
+           *         2px lines from Y axis
+           */
+          minorGridLineWidth: 1,
+          /**
+           * Color for the minor tick marks.
+           *
+           * @sample {highcharts} highcharts/yaxis/minortickcolor/
+           *         Black tick marks on Y axis
+           * @sample {highstock} stock/xaxis/minorticks/
+           *         Black tick marks on Y axis
+           *
+           * @type    {Highcharts.ColorType}
+           * @default #999999
+           */
+          minorTickColor: "#999999",
+          /**
+           * The color of the line marking the axis itself.
+           *
+           * In styled mode, the line stroke is given in the
+           * `.highcharts-axis-line` or `.highcharts-xaxis-line` class.
+           *
+           * @productdesc {highmaps}
+           * In Highmaps, the axis line is hidden by default, because the axis is
+           * not visible by default.
+           *
+           * @sample {highcharts} highcharts/yaxis/linecolor/
+           *         A red line on Y axis
+           * @sample {highcharts|highstock} highcharts/css/axis/
+           *         Axes in styled mode
+           * @sample {highstock} stock/xaxis/linecolor/
+           *         A red line on X axis
+           *
+           * @type    {Highcharts.ColorType}
+           * @default #ccd6eb
+           */
+          lineColor: "#ccd6eb",
+          /**
+           * The width of the line marking the axis itself.
+           *
+           * In styled mode, the stroke width is given in the
+           * `.highcharts-axis-line` or `.highcharts-xaxis-line` class.
+           *
+           * @sample {highcharts} highcharts/yaxis/linecolor/
+           *         A 1px line on Y axis
+           * @sample {highcharts|highstock} highcharts/css/axis/
+           *         Axes in styled mode
+           * @sample {highstock} stock/xaxis/linewidth/
+           *         A 2px line on X axis
+           *
+           * @default {highcharts|highstock} 1
+           * @default {highmaps} 0
+           */
+          lineWidth: 1,
+          /**
+           * Color of the grid lines extending the ticks across the plot area.
+           *
+           * In styled mode, the stroke is given in the `.highcharts-grid-line`
+           * class.
+           *
+           * @productdesc {highmaps}
+           * In Highmaps, the grid lines are hidden by default.
+           *
+           * @sample {highcharts} highcharts/yaxis/gridlinecolor/
+           *         Green lines
+           * @sample {highcharts|highstock} highcharts/css/axis-grid/
+           *         Styled mode
+           * @sample {highstock} stock/xaxis/gridlinecolor/
+           *         Green lines
+           *
+           * @type    {Highcharts.ColorType}
+           * @default #e6e6e6
+           */
+          gridLineColor: "#e6e6e6",
+          // gridLineDashStyle: 'solid',
+          /**
+           * The width of the grid lines extending the ticks across the plot area.
+           *
+           * In styled mode, the stroke width is given in the
+           * `.highcharts-grid-line` class.
+           *
+           * @sample {highcharts} highcharts/yaxis/gridlinewidth/
+           *         2px lines
+           * @sample {highcharts|highstock} highcharts/css/axis-grid/
+           *         Styled mode
+           * @sample {highstock} stock/xaxis/gridlinewidth/
+           *         2px lines
+           *
+           * @type      {number}
+           * @default   0
+           * @apioption xAxis.gridLineWidth
+           */
+          // gridLineWidth: 0,
+          /**
+           * The height as the vertical axis. If it's a number, it is
+           * interpreted as pixels.
+           *
+           * Since Highcharts 2: If it's a percentage string, it is interpreted
+           * as percentages of the total plot height.
+           *
+           * @type      {number|string}
+           * @product   highcharts highstock
+           * @apioption xAxis.height
+           */
+          /**
+           * The width as the horizontal axis. If it's a number, it is interpreted
+           * as pixels.
+           *
+           * Since Highcharts v5.0.13: If it's a percentage string, it is
+           * interpreted as percentages of the total plot width.
+           *
+           * @type      {number|string}
+           * @product   highcharts highstock
+           * @apioption xAxis.width
+           */
+          /**
+           * Color for the main tick marks.
+           *
+           * In styled mode, the stroke is given in the `.highcharts-tick`
+           * class.
+           *
+           * @sample {highcharts} highcharts/xaxis/tickcolor/
+           *         Red ticks on X axis
+           * @sample {highcharts|highstock} highcharts/css/axis-grid/
+           *         Styled mode
+           * @sample {highstock} stock/xaxis/ticks/
+           *         Formatted ticks on X axis
+           *
+           * @type    {Highcharts.ColorType}
+           * @default #ccd6eb
+           */
+          tickColor: "#ccd6eb",
+          // tickWidth: 1
+        };
+        /**
+         * The Y axis or value axis. Normally this is the vertical axis,
+         * though if the chart is inverted this is the horizontal axis.
+         * In case of multiple axes, the yAxis node is an array of
+         * configuration objects.
+         *
+         * See [the Axis object](/class-reference/Highcharts.Axis) for programmatic
+         * access to the axis.
+         *
+         * @type         {*|Array<*>}
+         * @extends      xAxis
+         * @excluding    currentDateIndicator,ordinal,overscroll
+         * @optionparent yAxis
+         *
+         * @private
+         */
+        Axis.defaultYAxisOptions = {
+          /**
+           * The type of axis. Can be one of `linear`, `logarithmic`, `datetime`,
+           * `category` or `treegrid`. Defaults to `treegrid` for Gantt charts,
+           * `linear` for other chart types.
+           *
+           * In a datetime axis, the numbers are given in milliseconds, and tick
+           * marks are placed on appropriate values, like full hours or days. In a
+           * category or treegrid axis, the [point names](#series.line.data.name)
+           * of the chart's series are used for categories, if a
+           * [categories](#xAxis.categories) array is not defined.
+           *
+           * @sample {highcharts} highcharts/yaxis/type-log-minorgrid/
+           *         Logarithmic with minor grid lines
+           * @sample {highcharts} highcharts/yaxis/type-log-negative/
+           *         Logarithmic with extension to emulate negative values
+           * @sample {gantt} gantt/treegrid-axis/demo
+           *         Treegrid axis
+           *
+           * @type      {Highcharts.AxisTypeValue}
+           * @default   {highcharts} linear
+           * @default   {gantt} treegrid
+           * @product   highcharts gantt
+           * @apioption yAxis.type
+           */
+          /**
+           * The height of the Y axis. If it's a number, it is interpreted as
+           * pixels.
+           *
+           * Since Highcharts 2: If it's a percentage string, it is interpreted as
+           * percentages of the total plot height.
+           *
+           * @see [yAxis.top](#yAxis.top)
+           *
+           * @sample {highstock} stock/demo/candlestick-and-volume/
+           *         Percentage height panes
+           *
+           * @type      {number|string}
+           * @product   highcharts highstock
+           * @apioption yAxis.height
+           */
+          /**
+           * Solid gauge only. Unless [stops](#yAxis.stops) are set, the color
+           * to represent the maximum value of the Y axis.
+           *
+           * @sample {highcharts} highcharts/yaxis/mincolor-maxcolor/
+           *         Min and max colors
+           *
+           * @type      {Highcharts.ColorType}
+           * @default   #003399
+           * @since     4.0
+           * @product   highcharts
+           * @apioption yAxis.maxColor
+           */
+          /**
+           * Solid gauge only. Unless [stops](#yAxis.stops) are set, the color
+           * to represent the minimum value of the Y axis.
+           *
+           * @sample {highcharts} highcharts/yaxis/mincolor-maxcolor/
+           *         Min and max color
+           *
+           * @type      {Highcharts.ColorType}
+           * @default   #e6ebf5
+           * @since     4.0
+           * @product   highcharts
+           * @apioption yAxis.minColor
+           */
+          /**
+           * Whether to reverse the axis so that the highest number is closest
+           * to the origin.
+           *
+           * @sample {highcharts} highcharts/yaxis/reversed/
+           *         Reversed Y axis
+           * @sample {highstock} stock/xaxis/reversed/
+           *         Reversed Y axis
+           *
+           * @type      {boolean}
+           * @default   {highcharts} false
+           * @default   {highstock} false
+           * @default   {highmaps} true
+           * @default   {gantt} true
+           * @apioption yAxis.reversed
+           */
+          /**
+           * If `true`, the first series in a stack will be drawn on top in a
+           * positive, non-reversed Y axis. If `false`, the first series is in
+           * the base of the stack.
+           *
+           * @sample {highcharts} highcharts/yaxis/reversedstacks-false/
+           *         Non-reversed stacks
+           * @sample {highstock} highcharts/yaxis/reversedstacks-false/
+           *         Non-reversed stacks
+           *
+           * @type      {boolean}
+           * @default   true
+           * @since     3.0.10
+           * @product   highcharts highstock
+           * @apioption yAxis.reversedStacks
+           */
+          /**
+           * Solid gauge series only. Color stops for the solid gauge. Use this
+           * in cases where a linear gradient between a `minColor` and `maxColor`
+           * is not sufficient. The stops is an array of tuples, where the first
+           * item is a float between 0 and 1 assigning the relative position in
+           * the gradient, and the second item is the color.
+           *
+           * For solid gauges, the Y axis also inherits the concept of
+           * [data classes](https://api.highcharts.com/highmaps#colorAxis.dataClasses)
+           * from the Highmaps color axis.
+           *
+           * @see [minColor](#yAxis.minColor)
+           * @see [maxColor](#yAxis.maxColor)
+           *
+           * @sample {highcharts} highcharts/demo/gauge-solid/
+           *         True by default
+           *
+           * @type      {Array<Array<number,Highcharts.ColorType>>}
+           * @since     4.0
+           * @product   highcharts
+           * @apioption yAxis.stops
+           */
+          /**
+           * The pixel width of the major tick marks.
+           *
+           * @sample {highcharts} highcharts/xaxis/tickwidth/ 10 px width
+           * @sample {highstock} stock/xaxis/ticks/ Formatted ticks on X axis
+           *
+           * @type      {number}
+           * @default   0
+           * @product   highcharts highstock gantt
+           * @apioption yAxis.tickWidth
+           */
+          /**
+           * Whether to force the axis to end on a tick. Use this option with
+           * the `maxPadding` option to control the axis end.
+           *
+           * This option is always disabled, when panning type is
+           * either `y` or `xy`.
+           *
+           * @see [type](#chart.panning.type)
+           *
+           *
+           * @sample {highcharts} highcharts/chart/reflow-true/
+           *         True by default
+           * @sample {highcharts} highcharts/yaxis/endontick/
+           *         False
+           * @sample {highstock} stock/demo/basic-line/
+           *         True by default
+           * @sample {highstock} stock/xaxis/endontick/
+           *         False for Y axis
+           *
+           * @since 1.2.0
+           */
+          endOnTick: true,
+          /**
+           * Padding of the max value relative to the length of the axis. A
+           * padding of 0.05 will make a 100px axis 5px longer. This is useful
+           * when you don't want the highest data value to appear on the edge
+           * of the plot area. When the axis' `max` option is set or a max extreme
+           * is set using `axis.setExtremes()`, the maxPadding will be ignored.
+           *
+           * Also the `softThreshold` option takes precedence over `maxPadding`,
+           * so if the data is tangent to the threshold, `maxPadding` may not
+           * apply unless `softThreshold` is set to false.
+           *
+           * @sample {highcharts} highcharts/yaxis/maxpadding-02/
+           *         Max padding of 0.2
+           * @sample {highstock} stock/xaxis/minpadding-maxpadding/
+           *         Greater min- and maxPadding
+           *
+           * @since   1.2.0
+           * @product highcharts highstock gantt
+           */
+          maxPadding: 0.05,
+          /**
+           * Padding of the min value relative to the length of the axis. A
+           * padding of 0.05 will make a 100px axis 5px longer. This is useful
+           * when you don't want the lowest data value to appear on the edge
+           * of the plot area. When the axis' `min` option is set or a max extreme
+           * is set using `axis.setExtremes()`, the maxPadding will be ignored.
+           *
+           * Also the `softThreshold` option takes precedence over `minPadding`,
+           * so if the data is tangent to the threshold, `minPadding` may not
+           * apply unless `softThreshold` is set to false.
+           *
+           * @sample {highcharts} highcharts/yaxis/minpadding/
+           *         Min padding of 0.2
+           * @sample {highstock} stock/xaxis/minpadding-maxpadding/
+           *         Greater min- and maxPadding
+           *
+           * @since   1.2.0
+           * @product highcharts highstock gantt
+           */
+          minPadding: 0.05,
+          /**
+           * @productdesc {highstock}
+           * In Highstock 1.x, the Y axis was placed on the left side by default.
+           *
+           * @sample {highcharts} highcharts/yaxis/opposite/
+           *         Secondary Y axis opposite
+           * @sample {highstock} stock/xaxis/opposite/
+           *         Y axis on left side
+           *
+           * @type      {boolean}
+           * @default   {highstock} true
+           * @default   {highcharts} false
+           * @product   highstock highcharts gantt
+           * @apioption yAxis.opposite
+           */
+          /**
+           * @see [tickInterval](#xAxis.tickInterval)
+           * @see [tickPositioner](#xAxis.tickPositioner)
+           * @see [tickPositions](#xAxis.tickPositions)
+           */
+          tickPixelInterval: 72,
+          showLastLabel: true,
+          /**
+           * @extends xAxis.labels
+           */
+          labels: {
+            /**
+             * Angular gauges and solid gauges only.
+             * The label's pixel distance from the perimeter of the plot area.
+             *
+             * Since v7.1.2: If it's a percentage string, it is interpreted the
+             * same as [series.radius](#plotOptions.gauge.radius), so label can be
+             * aligned under the gauge's shape.
+             *
+             * @sample {highcharts} highcharts/yaxis/labels-distance/
+             *         Labels centered under the arc
+             *
+             * @type      {number|string}
+             * @default   -25
+             * @product   highcharts
+             * @apioption yAxis.labels.distance
+             */
             /**
-             * Set the current data extremes as `dataMin` and `dataMax` on the
-             * Series item. Use this only when the series properties should be
-             * updated.
+             * The y position offset of all labels relative to the tick
+             * positions on the axis. For polar and radial axis consider the use
+             * of the [distance](#yAxis.labels.distance) option.
              *
-             * @private
-             * @function Highcharts.Series#applyExtremes
-             * @return {void}
+             * @sample {highcharts} highcharts/xaxis/labels-x/
+             *         Y axis labels placed on grid lines
+             *
+             * @type      {number}
+             * @default   {highcharts} 3
+             * @default   {highstock} -2
+             * @default   {highmaps} 3
+             * @apioption yAxis.labels.y
              */
-            applyExtremes: function () {
-                var dataExtremes = this.getExtremes();
-                /**
-                 * Contains the minimum value of the series' data point. Some series
-                 * types like `networkgraph` do not support this property as they
-                 * lack a `y`-value.
-                 * @name Highcharts.Series#dataMin
-                 * @type {number|undefined}
-                 * @readonly
-                 */
-                this.dataMin = dataExtremes.dataMin;
-                /**
-                 * Contains the maximum value of the series' data point. Some series
-                 * types like `networkgraph` do not support this property as they
-                 * lack a `y`-value.
-                 * @name Highcharts.Series#dataMax
-                 * @type {number|undefined}
-                 * @readonly
-                 */
-                this.dataMax = dataExtremes.dataMax;
-                return dataExtremes;
-            },
             /**
-             * Find and return the first non null point in the data
+             * What part of the string the given position is anchored to. Can
+             * be one of `"left"`, `"center"` or `"right"`. The exact position
+             * also depends on the `labels.x` setting.
              *
-             * @private
-             * @function Highcharts.Series.getFirstValidPoint
-             * @param {Array<Highcharts.PointOptionsType>} data
-             *        Array of options for points
+             * Angular gauges and solid gauges defaults to `"center"`.
+             * Solid gauges with two labels have additional option `"auto"`
+             * for automatic horizontal and vertical alignment.
+             *
+             * @see [yAxis.labels.distance](#yAxis.labels.distance)
+             *
+             * @sample {highcharts} highcharts/yaxis/labels-align-left/
+             *         Left
+             * @sample {highcharts} highcharts/series-solidgauge/labels-auto-aligned/
+             *         Solid gauge labels auto aligned
              *
-             * @return {Highcharts.PointOptionsType}
+             * @type       {Highcharts.AlignValue}
+             * @default    {highcharts|highmaps} right
+             * @default    {highstock} left
+             * @apioption  yAxis.labels.align
+             */
+            /**
+             * The x position offset of all labels relative to the tick
+             * positions on the axis. Defaults to -15 for left axis, 15 for
+             * right axis.
+             *
+             * @sample {highcharts} highcharts/xaxis/labels-x/
+             *         Y axis labels placed on grid lines
+             */
+            x: -8,
+          },
+          /**
+           * @productdesc {highmaps}
+           * In Highmaps, the axis line is hidden by default, because the axis is
+           * not visible by default.
+           *
+           * @type      {Highcharts.ColorType}
+           * @apioption yAxis.lineColor
+           */
+          /**
+           * @sample {highcharts} highcharts/yaxis/max-200/
+           *         Y axis max of 200
+           * @sample {highcharts} highcharts/yaxis/max-logarithmic/
+           *         Y axis max on logarithmic axis
+           * @sample {highstock} stock/yaxis/min-max/
+           *         Fixed min and max on Y axis
+           * @sample {highmaps} maps/axis/min-max/
+           *         Pre-zoomed to a specific area
+           *
+           * @apioption yAxis.max
+           */
+          /**
+           * @sample {highcharts} highcharts/yaxis/min-startontick-false/
+           *         -50 with startOnTick to false
+           * @sample {highcharts} highcharts/yaxis/min-startontick-true/
+           *         -50 with startOnTick true by default
+           * @sample {highstock} stock/yaxis/min-max/
+           *         Fixed min and max on Y axis
+           * @sample {highmaps} maps/axis/min-max/
+           *         Pre-zoomed to a specific area
+           *
+           * @apioption yAxis.min
+           */
+          /**
+           * An optional scrollbar to display on the Y axis in response to
+           * limiting the minimum an maximum of the axis values.
+           *
+           * In styled mode, all the presentational options for the scrollbar
+           * are replaced by the classes `.highcharts-scrollbar-thumb`,
+           * `.highcharts-scrollbar-arrow`, `.highcharts-scrollbar-button`,
+           * `.highcharts-scrollbar-rifles` and `.highcharts-scrollbar-track`.
+           *
+           * @sample {highstock} stock/yaxis/scrollbar/
+           *         Scrollbar on the Y axis
+           *
+           * @extends   scrollbar
+           * @since     4.2.6
+           * @product   highstock
+           * @excluding height
+           * @apioption yAxis.scrollbar
+           */
+          /**
+           * Enable the scrollbar on the Y axis.
+           *
+           * @sample {highstock} stock/yaxis/scrollbar/
+           *         Enabled on Y axis
+           *
+           * @type      {boolean}
+           * @default   false
+           * @since     4.2.6
+           * @product   highstock
+           * @apioption yAxis.scrollbar.enabled
+           */
+          /**
+           * Pixel margin between the scrollbar and the axis elements.
+           *
+           * @type      {number}
+           * @default   10
+           * @since     4.2.6
+           * @product   highstock
+           * @apioption yAxis.scrollbar.margin
+           */
+          /**
+           * Whether to show the scrollbar when it is fully zoomed out at max
+           * range. Setting it to `false` on the Y axis makes the scrollbar stay
+           * hidden until the user zooms in, like common in browsers.
+           *
+           * @type      {boolean}
+           * @default   true
+           * @since     4.2.6
+           * @product   highstock
+           * @apioption yAxis.scrollbar.showFull
+           */
+          /**
+           * The width of a vertical scrollbar or height of a horizontal
+           * scrollbar. Defaults to 20 on touch devices.
+           *
+           * @type      {number}
+           * @default   14
+           * @since     4.2.6
+           * @product   highstock
+           * @apioption yAxis.scrollbar.size
+           */
+          /**
+           * Z index of the scrollbar elements.
+           *
+           * @type      {number}
+           * @default   3
+           * @since     4.2.6
+           * @product   highstock
+           * @apioption yAxis.scrollbar.zIndex
+           */
+          /**
+           * A soft maximum for the axis. If the series data maximum is less
+           * than this, the axis will stay at this maximum, but if the series
+           * data maximum is higher, the axis will flex to show all data.
+           *
+           * **Note**: The [series.softThreshold](
+           * #plotOptions.series.softThreshold) option takes precedence over this
+           * option.
+           *
+           * @sample highcharts/yaxis/softmin-softmax/
+           *         Soft min and max
+           *
+           * @type      {number}
+           * @since     5.0.1
+           * @product   highcharts highstock gantt
+           * @apioption yAxis.softMax
+           */
+          /**
+           * A soft minimum for the axis. If the series data minimum is greater
+           * than this, the axis will stay at this minimum, but if the series
+           * data minimum is lower, the axis will flex to show all data.
+           *
+           * **Note**: The [series.softThreshold](
+           * #plotOptions.series.softThreshold) option takes precedence over this
+           * option.
+           *
+           * @sample highcharts/yaxis/softmin-softmax/
+           *         Soft min and max
+           *
+           * @type      {number}
+           * @since     5.0.1
+           * @product   highcharts highstock gantt
+           * @apioption yAxis.softMin
+           */
+          /**
+           * Defines the horizontal alignment of the stack total label. Can be one
+           * of `"left"`, `"center"` or `"right"`. The default value is calculated
+           * at runtime and depends on orientation and whether the stack is
+           * positive or negative.
+           *
+           * @sample {highcharts} highcharts/yaxis/stacklabels-align-left/
+           *         Aligned to the left
+           * @sample {highcharts} highcharts/yaxis/stacklabels-align-center/
+           *         Aligned in center
+           * @sample {highcharts} highcharts/yaxis/stacklabels-align-right/
+           *         Aligned to the right
+           *
+           * @type      {Highcharts.AlignValue}
+           * @since     2.1.5
+           * @product   highcharts
+           * @apioption yAxis.stackLabels.align
+           */
+          /**
+           * A format string for the data label. Available variables are the same
+           * as for `formatter`.
+           *
+           * @type      {string}
+           * @default   {total}
+           * @since     3.0.2
+           * @product   highcharts highstock
+           * @apioption yAxis.stackLabels.format
+           */
+          /**
+           * Rotation of the labels in degrees.
+           *
+           * @sample {highcharts} highcharts/yaxis/stacklabels-rotation/
+           *         Labels rotated 45°
+           *
+           * @type      {number}
+           * @default   0
+           * @since     2.1.5
+           * @product   highcharts
+           * @apioption yAxis.stackLabels.rotation
+           */
+          /**
+           * The text alignment for the label. While `align` determines where the
+           * texts anchor point is placed with regards to the stack, `textAlign`
+           * determines how the text is aligned against its anchor point. Possible
+           * values are `"left"`, `"center"` and `"right"`. The default value is
+           * calculated at runtime and depends on orientation and whether the
+           * stack is positive or negative.
+           *
+           * @sample {highcharts} highcharts/yaxis/stacklabels-textalign-left/
+           *         Label in center position but text-aligned left
+           *
+           * @type      {Highcharts.AlignValue}
+           * @since     2.1.5
+           * @product   highcharts
+           * @apioption yAxis.stackLabels.textAlign
+           */
+          /**
+           * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html)
+           * to render the labels.
+           *
+           * @type      {boolean}
+           * @default   false
+           * @since     3.0
+           * @product   highcharts highstock
+           * @apioption yAxis.stackLabels.useHTML
+           */
+          /**
+           * Defines the vertical alignment of the stack total label. Can be one
+           * of `"top"`, `"middle"` or `"bottom"`. The default value is calculated
+           * at runtime and depends on orientation and whether the stack is
+           * positive or negative.
+           *
+           * @sample {highcharts} highcharts/yaxis/stacklabels-verticalalign-top/
+           *         Vertically aligned top
+           * @sample {highcharts} highcharts/yaxis/stacklabels-verticalalign-middle/
+           *         Vertically aligned middle
+           * @sample {highcharts} highcharts/yaxis/stacklabels-verticalalign-bottom/
+           *         Vertically aligned bottom
+           *
+           * @type      {Highcharts.VerticalAlignValue}
+           * @since     2.1.5
+           * @product   highcharts
+           * @apioption yAxis.stackLabels.verticalAlign
+           */
+          /**
+           * The x position offset of the label relative to the left of the
+           * stacked bar. The default value is calculated at runtime and depends
+           * on orientation and whether the stack is positive or negative.
+           *
+           * @sample {highcharts} highcharts/yaxis/stacklabels-x/
+           *         Stack total labels with x offset
+           *
+           * @type      {number}
+           * @since     2.1.5
+           * @product   highcharts
+           * @apioption yAxis.stackLabels.x
+           */
+          /**
+           * The y position offset of the label relative to the tick position
+           * on the axis. The default value is calculated at runtime and depends
+           * on orientation and whether the stack is positive or negative.
+           *
+           * @sample {highcharts} highcharts/yaxis/stacklabels-y/
+           *         Stack total labels with y offset
+           *
+           * @type      {number}
+           * @since     2.1.5
+           * @product   highcharts
+           * @apioption yAxis.stackLabels.y
+           */
+          /**
+           * Whether to force the axis to start on a tick. Use this option with
+           * the `maxPadding` option to control the axis start.
+           *
+           * This option is always disabled, when panning type is
+           * either `y` or `xy`.
+           *
+           * @see [type](#chart.panning.type)
+           *
+           * @sample {highcharts} highcharts/xaxis/startontick-false/
+           *         False by default
+           * @sample {highcharts} highcharts/xaxis/startontick-true/
+           *         True
+           * @sample {highstock} stock/xaxis/endontick/
+           *         False for Y axis
+           *
+           * @since   1.2.0
+           * @product highcharts highstock gantt
+           */
+          startOnTick: true,
+          title: {
+            /**
+             * The pixel distance between the axis labels and the title.
+             * Positive values are outside the axis line, negative are inside.
+             *
+             * @sample {highcharts} highcharts/xaxis/title-margin/
+             *         Y axis title margin of 60
+             *
+             * @type      {number}
+             * @default   40
+             * @apioption yAxis.title.margin
              */
-            getFirstValidPoint: function (data) {
-                var firstPoint = null,
-                    dataLength = data.length,
-                    i = 0;
-                while (firstPoint === null && i < dataLength) {
-                    firstPoint = data[i];
-                    i++;
-                }
-                return firstPoint;
-            },
             /**
-             * Translate data points from raw data values to chart specific
-             * positioning data needed later in the `drawPoints` and `drawGraph`
-             * functions. This function can be overridden in plugins and custom
-             * series type implementations.
-             *
-             * @function Highcharts.Series#translate
-             * @return {void}
-             * @fires Highcharts.Series#events:translate
+             * The rotation of the text in degrees. 0 is horizontal, 270 is
+             * vertical reading from bottom to top.
+             *
+             * @sample {highcharts} highcharts/yaxis/title-offset/
+             *         Horizontal
              */
-            translate: function () {
-                if (!this.processedXData) { // hidden series
-                    this.processData();
-                }
-                this.generatePoints();
-                var series = this,
-                    options = series.options,
-                    stacking = options.stacking,
-                    xAxis = series.xAxis,
-                    categories = xAxis.categories,
-                    enabledDataSorting = series.enabledDataSorting,
-                    yAxis = series.yAxis,
-                    points = series.points,
-                    dataLength = points.length,
-                    hasModifyValue = !!series.modifyValue,
-                    i,
-                    pointPlacement = series.pointPlacementToXValue(), // #7860
-                    dynamicallyPlaced = Boolean(pointPlacement),
-                    threshold = options.threshold,
-                    stackThreshold = options.startFromThreshold ? threshold : 0,
-                    plotX,
-                    lastPlotX,
-                    stackIndicator,
-                    zoneAxis = this.zoneAxis || 'y',
-                    closestPointRangePx = Number.MAX_VALUE;
-                /**
-                 * Plotted coordinates need to be within a limited range. Drawing
-                 * too far outside the viewport causes various rendering issues
-                 * (#3201, #3923, #7555).
-                 * @private
-                 */
-                function limitedRange(val) {
-                    return clamp(val, -1e5, 1e5);
-                }
-                // Translate each point
-                for (i = 0; i < dataLength; i++) {
-                    var point = points[i],
-                        xValue = point.x,
-                        yValue = point.y,
-                        yBottom = point.low,
-                        stack = stacking && yAxis.stacking && yAxis.stacking.stacks[(series.negStacks &&
-                            yValue <
-                                (stackThreshold ? 0 : threshold) ?
-                            '-' :
-                            '') + series.stackKey],
-                        pointStack,
-                        stackValues;
-                    if (yAxis.positiveValuesOnly && !yAxis.validatePositiveValue(yValue) ||
-                        xAxis.positiveValuesOnly && !xAxis.validatePositiveValue(xValue)) {
-                        point.isNull = true;
-                    }
-                    // Get the plotX translation
-                    point.plotX = plotX = correctFloat(// #5236
-                    limitedRange(xAxis.translate(// #3923
-                    xValue, 0, 0, 0, 1, pointPlacement, this.type === 'flags')) // #3923
-                    );
-                    // Calculate the bottom y value for stacked series
-                    if (stacking &&
-                        series.visible &&
-                        stack &&
-                        stack[xValue]) {
-                        stackIndicator = series.getStackIndicator(stackIndicator, xValue, series.index);
-                        if (!point.isNull) {
-                            pointStack = stack[xValue];
-                            stackValues =
-                                pointStack.points[stackIndicator.key];
-                        }
-                    }
-                    if (isArray(stackValues)) {
-                        yBottom = stackValues[0];
-                        yValue = stackValues[1];
-                        if (yBottom === stackThreshold &&
-                            stackIndicator.key ===
-                                stack[xValue].base) {
-                            yBottom = pick((isNumber(threshold) && threshold), yAxis.min);
-                        }
-                        // #1200, #1232
-                        if (yAxis.positiveValuesOnly && yBottom <= 0) {
-                            yBottom = null;
-                        }
-                        point.total = point.stackTotal = pointStack.total;
-                        point.percentage =
-                            pointStack.total &&
-                                (point.y / pointStack.total * 100);
-                        point.stackY = yValue;
-                        // Place the stack label
-                        // in case of variwide series (where widths of points are
-                        // different in most cases), stack labels are positioned
-                        // wrongly, so the call of the setOffset is omited here and
-                        // labels are correctly positioned later, at the end of the
-                        // variwide's translate function (#10962)
-                        if (!series.irregularWidths) {
-                            pointStack.setOffset(series.pointXOffset || 0, series.barW || 0);
-                        }
-                    }
-                    // Set translated yBottom or remove it
-                    point.yBottom = defined(yBottom) ?
-                        limitedRange(yAxis.translate(yBottom, 0, 1, 0, 1)) :
-                        null;
-                    // general hook, used for Highstock compare mode
-                    if (hasModifyValue) {
-                        yValue = series.modifyValue(yValue, point);
-                    }
-                    // Set the the plotY value, reset it for redraws
-                    // #3201
-                    point.plotY = ((typeof yValue === 'number' && yValue !== Infinity) ?
-                        limitedRange(yAxis.translate(yValue, 0, 1, 0, 1)) :
-                        void 0);
-                    point.isInside = this.isPointInside(point);
-                    // Set client related positions for mouse tracking
-                    point.clientX = dynamicallyPlaced ?
-                        correctFloat(xAxis.translate(xValue, 0, 0, 0, 1, pointPlacement)) :
-                        plotX; // #1514, #5383, #5518
-                    // Negative points. For bubble charts, this means negative z
-                    // values (#9728)
-                    point.negative = point[zoneAxis] < (options[zoneAxis + 'Threshold'] ||
-                        threshold ||
-                        0);
-                    // some API data
-                    point.category = (categories &&
-                        typeof categories[point.x] !== 'undefined' ?
-                        categories[point.x] :
-                        point.x);
-                    // Determine auto enabling of markers (#3635, #5099)
-                    if (!point.isNull && point.visible !== false) {
-                        if (typeof lastPlotX !== 'undefined') {
-                            closestPointRangePx = Math.min(closestPointRangePx, Math.abs(plotX - lastPlotX));
-                        }
-                        lastPlotX = plotX;
-                    }
-                    // Find point zone
-                    point.zone = (this.zones.length && point.getZone());
-                    // Animate new points with data sorting
-                    if (!point.graphic && series.group && enabledDataSorting) {
-                        point.isNew = true;
-                    }
-                }
-                series.closestPointRangePx = closestPointRangePx;
-                fireEvent(this, 'afterTranslate');
-            },
+            rotation: 270,
             /**
-             * Return the series points with null points filtered out.
+             * The actual text of the axis title. Horizontal texts can contain
+             * HTML, but rotated texts are painted using vector techniques and
+             * must be clean text. The Y axis title is disabled by setting the
+             * `text` option to `undefined`.
+             *
+             * @sample {highcharts} highcharts/xaxis/title-text/
+             *         Custom HTML
+             *
+             * @type    {string|null}
+             * @default {highcharts} Values
+             * @default {highstock} undefined
+             * @product highcharts highstock gantt
+             */
+            text: "Values",
+          },
+          /**
+           * The top position of the Y axis. If it's a number, it is interpreted
+           * as pixel position relative to the chart.
+           *
+           * Since Highcharts 2: If it's a percentage string, it is interpreted as
+           * percentages of the plot height, offset from plot area top.
+           *
+           * @see [yAxis.height](#yAxis.height)
+           *
+           * @sample {highstock} stock/demo/candlestick-and-volume/
+           *         Percentage height panes
+           *
+           * @type      {number|string}
+           * @product   highcharts highstock
+           * @apioption yAxis.top
+           */
+          /**
+           * The stack labels show the total value for each bar in a stacked
+           * column or bar chart. The label will be placed on top of positive
+           * columns and below negative columns. In case of an inverted column
+           * chart or a bar chart the label is placed to the right of positive
+           * bars and to the left of negative bars.
+           *
+           * @product highcharts
+           */
+          stackLabels: {
+            /**
+             * Enable or disable the initial animation when a series is
+             * displayed for the `stackLabels`. The animation can also be set as
+             * a configuration object. Please note that this option only
+             * applies to the initial animation.
+             * For other animations, see [chart.animation](#chart.animation)
+             * and the animation parameter under the API methods.
+             * The following properties are supported:
              *
-             * @function Highcharts.Series#getValidPoints
+             * - `defer`: The animation delay time in milliseconds.
              *
-             * @param {Array<Highcharts.Point>} [points]
-             *        The points to inspect, defaults to {@link Series.points}.
+             * @sample {highcharts} highcharts/plotoptions/animation-defer/
+             *          Animation defer settings
+             * @type {boolean|Partial<Highcharts.AnimationOptionsObject>}
+             * @since 8.2.0
+             * @apioption yAxis.stackLabels.animation
+             */
+            animation: {},
+            /**
+             * The animation delay time in milliseconds.
+             * Set to `0` renders stackLabel immediately.
+             * As `undefined` inherits defer time from the [series.animation.defer](#plotOptions.series.animation.defer).
              *
-             * @param {boolean} [insideOnly=false]
-             *        Whether to inspect only the points that are inside the visible
-             *        view.
+             * @type      {number}
+             * @since 8.2.0
+             * @apioption yAxis.stackLabels.animation.defer
+             */
+            /**
+             * Allow the stack labels to overlap.
              *
-             * @param {boolean} [allowNull=false]
-             *        Whether to allow null points to pass as valid points.
+             * @sample {highcharts} highcharts/yaxis/stacklabels-allowoverlap-false/
+             *         Default false
              *
-             * @return {Array<Highcharts.Point>}
-             *         The valid points.
+             * @since   5.0.13
+             * @product highcharts
              */
-            getValidPoints: function (points, insideOnly, allowNull) {
-                var chart = this.chart;
-                // #3916, #5029, #5085
-                return (points || this.points || []).filter(function isValidPoint(point) {
-                    if (insideOnly && !chart.isInsidePlot(point.plotX, point.plotY, chart.inverted)) {
-                        return false;
-                    }
-                    return point.visible !== false &&
-                        (allowNull || !point.isNull);
-                });
-            },
+            allowOverlap: false,
             /**
-             * Get the clipping for the series. Could be called for a series to
-             * initiate animating the clip or to set the final clip (only width
-             * and x).
+             * The background color or gradient for the stack label.
              *
-             * @private
-             * @function Highcharts.Series#getClip
-             * @param  {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation]
-             *         Initialize the animation.
-             * @param  {boolean} [finalBox]
-             *         Final size for the clip - end state for the animation.
-             * @return {Highcharts.Dictionary<number>}
+             * @sample {highcharts} highcharts/yaxis/stacklabels-box/
+             *          Stack labels box options
+             * @type      {Highcharts.ColorType}
+             * @since 8.1.0
+             * @apioption yAxis.stackLabels.backgroundColor
              */
-            getClipBox: function (animation, finalBox) {
-                var series = this,
-                    options = series.options,
-                    chart = series.chart,
-                    inverted = chart.inverted,
-                    xAxis = series.xAxis,
-                    yAxis = xAxis && series.yAxis,
-                    clipBox,
-                    scrollablePlotAreaOptions = chart.options.chart.scrollablePlotArea || {};
-                if (animation && options.clip === false && yAxis) {
-                    // support for not clipped series animation (#10450)
-                    clipBox = inverted ? {
-                        y: -chart.chartWidth + yAxis.len + yAxis.pos,
-                        height: chart.chartWidth,
-                        width: chart.chartHeight,
-                        x: -chart.chartHeight + xAxis.len + xAxis.pos
-                    } : {
-                        y: -yAxis.pos,
-                        height: chart.chartHeight,
-                        width: chart.chartWidth,
-                        x: -xAxis.pos
-                    };
-                    // x and width will be changed later when setting for animation
-                    // initial state in Series.setClip
-                }
-                else {
-                    clipBox = series.clipBox || chart.clipBox;
-                    if (finalBox) {
-                        clipBox.width = chart.plotSizeX;
-                        clipBox.x = (chart.scrollablePixelsX || 0) *
-                            (scrollablePlotAreaOptions.scrollPositionX || 0);
-                    }
-                }
-                return !finalBox ? clipBox : {
-                    width: clipBox.width,
-                    x: clipBox.x
-                };
-            },
             /**
-             * Set the clipping for the series. For animated series it is called
-             * twice, first to initiate animating the clip then the second time
-             * without the animation to set the final clip.
+             * The border color for the stack label. Defaults to `undefined`.
              *
-             * @private
-             * @function Highcharts.Series#setClip
-             * @param {boolean|Highcharts.AnimationOptionsObject} [animation]
+             * @sample {highcharts} highcharts/yaxis/stacklabels-box/
+             *          Stack labels box options
+             * @type      {Highcharts.ColorType}
+             * @since 8.1.0
+             * @apioption yAxis.stackLabels.borderColor
              */
-            setClip: function (animation) {
-                var chart = this.chart, options = this.options, renderer = chart.renderer, inverted = chart.inverted, seriesClipBox = this.clipBox, clipBox = this.getClipBox(animation), sharedClipKey = this.sharedClipKey ||
-                        [
-                            '_sharedClip',
-                            animation && animation.duration,
-                            animation && animation.easing,
-                            clipBox.height,
-                            options.xAxis,
-                            options.yAxis
-                        ].join(','), // #4526
-                    clipRect = chart[sharedClipKey], markerClipRect = chart[sharedClipKey + 'm'];
-                if (animation) {
-                    clipBox.width = 0;
-                    if (inverted) {
-                        clipBox.x = chart.plotHeight +
-                            (options.clip !== false ? 0 : chart.plotTop);
-                    }
-                }
-                // If a clipping rectangle with the same properties is currently
-                // present in the chart, use that.
-                if (!clipRect) {
-                    // When animation is set, prepare the initial positions
-                    if (animation) {
-                        chart[sharedClipKey + 'm'] = markerClipRect =
-                            renderer.clipRect(
-                            // include the width of the first marker
-                            inverted ? chart.plotSizeX + 99 : -99, inverted ? -chart.plotLeft : -chart.plotTop, 99, inverted ? chart.chartWidth : chart.chartHeight);
-                    }
-                    chart[sharedClipKey] = clipRect = renderer.clipRect(clipBox);
-                    // Create hashmap for series indexes
-                    clipRect.count = { length: 0 };
-                    // When the series is rendered again before starting animating, in
-                    // compliance to a responsive rule
-                }
-                else if (!chart.hasLoaded) {
-                    clipRect.attr(clipBox);
-                }
-                if (animation) {
-                    if (!clipRect.count[this.index]) {
-                        clipRect.count[this.index] = true;
-                        clipRect.count.length += 1;
-                    }
-                }
-                if (options.clip !== false || animation) {
-                    this.group.clip(animation || seriesClipBox ? clipRect : chart.clipRect);
-                    this.markerGroup.clip(markerClipRect);
-                    this.sharedClipKey = sharedClipKey;
-                }
-                // Remove the shared clipping rectangle when all series are shown
-                if (!animation) {
-                    if (clipRect.count[this.index]) {
-                        delete clipRect.count[this.index];
-                        clipRect.count.length -= 1;
-                    }
-                    if (clipRect.count.length === 0 &&
-                        sharedClipKey &&
-                        chart[sharedClipKey]) {
-                        if (!seriesClipBox) {
-                            chart[sharedClipKey] =
-                                chart[sharedClipKey].destroy();
-                        }
-                        if (chart[sharedClipKey + 'm']) {
-                            chart[sharedClipKey + 'm'] =
-                                chart[sharedClipKey + 'm'].destroy();
-                        }
-                    }
-                }
-            },
             /**
-             * Animate in the series. Called internally twice. First with the `init`
-             * parameter set to true, which sets up the initial state of the
-             * animation. Then when ready, it is called with the `init` parameter
-             * undefined, in order to perform the actual animation. After the
-             * second run, the function is removed.
+             * The border radius in pixels for the stack label.
              *
-             * @function Highcharts.Series#animate
-             *
-             * @param {boolean} [init]
-             *        Initialize the animation.
+             * @sample {highcharts} highcharts/yaxis/stacklabels-box/
+             *          Stack labels box options
+             * @type      {number}
+             * @default   0
+             * @since 8.1.0
+             * @apioption yAxis.stackLabels.borderRadius
              */
-            animate: function (init) {
-                var series = this,
-                    chart = series.chart,
-                    animation = animObject(series.options.animation),
-                    clipRect,
-                    sharedClipKey,
-                    finalBox;
-                // Initialize the animation. Set up the clipping rectangle.
-                if (!chart.hasRendered) {
-                    if (init) {
-                        series.setClip(animation);
-                        // Run the animation
-                    }
-                    else {
-                        sharedClipKey = this.sharedClipKey;
-                        clipRect = chart[sharedClipKey];
-                        finalBox = series.getClipBox(animation, true);
-                        if (clipRect) {
-                            clipRect.animate(finalBox, animation);
-                        }
-                        if (chart[sharedClipKey + 'm']) {
-                            chart[sharedClipKey + 'm'].animate({
-                                width: finalBox.width + 99,
-                                x: finalBox.x - (chart.inverted ? 0 : 99)
-                            }, animation);
-                        }
-                    }
-                }
-            },
             /**
-             * This runs after animation to land on the final plot clipping.
+             * The border width in pixels for the stack label.
              *
-             * @private
-             * @function Highcharts.Series#afterAnimate
-             * @fires Highcharts.Series#event:afterAnimate
+             * @sample {highcharts} highcharts/yaxis/stacklabels-box/
+             *          Stack labels box options
+             * @type      {number}
+             * @default   0
+             * @since 8.1.0
+             * @apioption yAxis.stackLabels.borderWidth
              */
-            afterAnimate: function () {
-                this.setClip();
-                fireEvent(this, 'afterAnimate');
-                this.finishedAnimating = true;
-            },
             /**
-             * Draw the markers for line-like series types, and columns or other
-             * graphical representation for {@link Point} objects for other series
-             * types. The resulting element is typically stored as
-             * {@link Point.graphic}, and is created on the first call and updated
-             * and moved on subsequent calls.
+             * Enable or disable the stack total labels.
+             *
+             * @sample {highcharts} highcharts/yaxis/stacklabels-enabled/
+             *         Enabled stack total labels
+             * @sample {highcharts} highcharts/yaxis/stacklabels-enabled-waterfall/
+             *         Enabled stack labels in waterfall chart
              *
-             * @function Highcharts.Series#drawPoints
+             * @since   2.1.5
+             * @product highcharts
              */
-            drawPoints: function () {
-                var series = this,
-                    points = series.points,
-                    chart = series.chart,
-                    i,
-                    point,
-                    graphic,
-                    verb,
-                    options = series.options,
-                    seriesMarkerOptions = options.marker,
-                    pointMarkerOptions,
-                    hasPointMarker,
-                    markerGroup = (series[series.specialGroup] ||
-                        series.markerGroup),
-                    xAxis = series.xAxis,
-                    markerAttribs,
-                    globallyEnabled = pick(seriesMarkerOptions.enabled, !xAxis || xAxis.isRadial ? true : null, 
-                    // Use larger or equal as radius is null in bubbles (#6321)
-                    series.closestPointRangePx >= (seriesMarkerOptions.enabledThreshold *
-                        seriesMarkerOptions.radius));
-                if (seriesMarkerOptions.enabled !== false ||
-                    series._hasPointMarkers) {
-                    for (i = 0; i < points.length; i++) {
-                        point = points[i];
-                        graphic = point.graphic;
-                        verb = graphic ? 'animate' : 'attr';
-                        pointMarkerOptions = point.marker || {};
-                        hasPointMarker = !!point.marker;
-                        var shouldDrawMarker = ((globallyEnabled &&
-                                typeof pointMarkerOptions.enabled === 'undefined') || pointMarkerOptions.enabled) && !point.isNull && point.visible !== false;
-                        // only draw the point if y is defined
-                        if (shouldDrawMarker) {
-                            // Shortcuts
-                            var symbol = pick(pointMarkerOptions.symbol,
-                                series.symbol);
-                            markerAttribs = series.markerAttribs(point, (point.selected && 'select'));
-                            // Set starting position for point sliding animation.
-                            if (series.enabledDataSorting) {
-                                point.startXPos = xAxis.reversed ?
-                                    -markerAttribs.width :
-                                    xAxis.width;
-                            }
-                            var isInside = point.isInside !== false;
-                            if (graphic) { // update
-                                // Since the marker group isn't clipped, each
-                                // individual marker must be toggled
-                                graphic[isInside ? 'show' : 'hide'](isInside)
-                                    .animate(markerAttribs);
-                            }
-                            else if (isInside &&
-                                (markerAttribs.width > 0 || point.hasImage)) {
-                                /**
-                                 * The graphic representation of the point.
-                                 * Typically this is a simple shape, like a `rect`
-                                 * for column charts or `path` for line markers, but
-                                 * for some complex series types like boxplot or 3D
-                                 * charts, the graphic may be a `g` element
-                                 * containing other shapes. The graphic is generated
-                                 * the first time {@link Series#drawPoints} runs,
-                                 * and updated and moved on subsequent runs.
-                                 *
-                                 * @name Point#graphic
-                                 * @type {SVGElement}
-                                 */
-                                point.graphic = graphic = chart.renderer
-                                    .symbol(symbol, markerAttribs.x, markerAttribs.y, markerAttribs.width, markerAttribs.height, hasPointMarker ?
-                                    pointMarkerOptions :
-                                    seriesMarkerOptions)
-                                    .add(markerGroup);
-                                // Sliding animation for new points
-                                if (series.enabledDataSorting &&
-                                    chart.hasRendered) {
-                                    graphic.attr({
-                                        x: point.startXPos
-                                    });
-                                    verb = 'animate';
-                                }
-                            }
-                            if (graphic && verb === 'animate') { // update
-                                // Since the marker group isn't clipped, each
-                                // individual marker must be toggled
-                                graphic[isInside ? 'show' : 'hide'](isInside)
-                                    .animate(markerAttribs);
-                            }
-                            // Presentational attributes
-                            if (graphic && !chart.styledMode) {
-                                graphic[verb](series.pointAttribs(point, (point.selected && 'select')));
-                            }
-                            if (graphic) {
-                                graphic.addClass(point.getClassName(), true);
-                            }
-                        }
-                        else if (graphic) {
-                            point.graphic = graphic.destroy(); // #1269
-                        }
-                    }
-                }
-            },
+            enabled: false,
             /**
-             * Get non-presentational attributes for a point. Used internally for
-             * both styled mode and classic. Can be overridden for different series
-             * types.
+             * Whether to hide stack labels that are outside the plot area.
+             * By default, the stack label is moved
+             * inside the plot area according to the
+             * [overflow](/highcharts/#yAxis/stackLabels/overflow)
+             * option.
              *
-             * @see Series#pointAttribs
+             * @type  {boolean}
+             * @since 7.1.3
+             */
+            crop: true,
+            /**
+             * How to handle stack total labels that flow outside the plot area.
+             * The default is set to `"justify"`,
+             * which aligns them inside the plot area.
+             * For columns and bars, this means it will be moved inside the bar.
+             * To display stack labels outside the plot area,
+             * set `crop` to `false` and `overflow` to `"allow"`.
              *
-             * @function Highcharts.Series#markerAttribs
+             * @sample highcharts/yaxis/stacklabels-overflow/
+             *         Stack labels flows outside the plot area.
              *
-             * @param {Highcharts.Point} point
-             *        The Point to inspect.
+             * @type  {Highcharts.DataLabelsOverflowValue}
+             * @since 7.1.3
+             */
+            overflow: "justify",
+            /* eslint-disable valid-jsdoc */
+            /**
+             * Callback JavaScript function to format the label. The value is
+             * given by `this.total`.
              *
-             * @param {string} [state]
-             *        The state, can be either `hover`, `select` or undefined.
+             * @sample {highcharts} highcharts/yaxis/stacklabels-formatter/
+             *         Added units to stack total value
              *
-             * @return {Highcharts.SVGAttributes}
-             *         A hash containing those attributes that are not settable from
-             *         CSS.
+             * @type    {Highcharts.FormatterCallbackFunction<Highcharts.StackItemObject>}
+             * @since   2.1.5
+             * @product highcharts
              */
-            markerAttribs: function (point, state) {
-                var seriesOptions = this.options,
-                    seriesMarkerOptions = seriesOptions.marker,
-                    seriesStateOptions,
-                    pointMarkerOptions = point.marker || {},
-                    symbol = (pointMarkerOptions.symbol ||
-                        seriesMarkerOptions.symbol),
-                    pointStateOptions,
-                    radius = pick(pointMarkerOptions.radius,
-                    seriesMarkerOptions.radius),
-                    attribs;
-                // Handle hover and select states
-                if (state) {
-                    seriesStateOptions = seriesMarkerOptions.states[state];
-                    pointStateOptions = pointMarkerOptions.states &&
-                        pointMarkerOptions.states[state];
-                    radius = pick(pointStateOptions && pointStateOptions.radius, seriesStateOptions && seriesStateOptions.radius, radius + (seriesStateOptions && seriesStateOptions.radiusPlus ||
-                        0));
-                }
-                point.hasImage = symbol && symbol.indexOf('url') === 0;
-                if (point.hasImage) {
-                    radius = 0; // and subsequently width and height is not set
-                }
-                attribs = {
-                    // Math.floor for #1843:
-                    x: seriesOptions.crisp ?
-                        Math.floor(point.plotX) - radius :
-                        point.plotX - radius,
-                    y: point.plotY - radius
-                };
-                if (radius) {
-                    attribs.width = attribs.height = 2 * radius;
-                }
-                return attribs;
+            formatter: function () {
+              var numberFormatter = this.axis.chart.numberFormatter;
+              /* eslint-enable valid-jsdoc */
+              return numberFormatter(this.total, -1);
             },
             /**
-             * Internal function to get presentational attributes for each point.
-             * Unlike {@link Series#markerAttribs}, this function should return
-             * those attributes that can also be set in CSS. In styled mode,
-             * `pointAttribs` won't be called.
-             *
-             * @private
-             * @function Highcharts.Series#pointAttribs
+             * CSS styles for the label.
              *
-             * @param {Highcharts.Point} [point]
-             *        The point instance to inspect.
+             * In styled mode, the styles are set in the
+             * `.highcharts-stack-label` class.
              *
-             * @param {string} [state]
-             *        The point state, can be either `hover`, `select` or 'normal'.
-             *        If undefined, normal state is assumed.
+             * @sample {highcharts} highcharts/yaxis/stacklabels-style/
+             *         Red stack total labels
              *
-             * @return {Highcharts.SVGAttributes}
-             *         The presentational attributes to be set on the point.
+             * @type    {Highcharts.CSSObject}
+             * @since   2.1.5
+             * @product highcharts
              */
-            pointAttribs: function (point, state) {
-                var seriesMarkerOptions = this.options.marker,
-                    seriesStateOptions,
-                    pointOptions = point && point.options,
-                    pointMarkerOptions = ((pointOptions && pointOptions.marker) || {}),
-                    pointStateOptions,
-                    color = this.color,
-                    pointColorOption = pointOptions && pointOptions.color,
-                    pointColor = point && point.color,
-                    strokeWidth = pick(pointMarkerOptions.lineWidth,
-                    seriesMarkerOptions.lineWidth),
-                    zoneColor = point && point.zone && point.zone.color,
-                    fill,
-                    stroke,
-                    opacity = 1;
-                color = (pointColorOption ||
-                    zoneColor ||
-                    pointColor ||
-                    color);
-                fill = (pointMarkerOptions.fillColor ||
-                    seriesMarkerOptions.fillColor ||
-                    color);
-                stroke = (pointMarkerOptions.lineColor ||
-                    seriesMarkerOptions.lineColor ||
-                    color);
-                // Handle hover and select states
-                state = state || 'normal';
-                if (state) {
-                    seriesStateOptions = seriesMarkerOptions.states[state];
-                    pointStateOptions = (pointMarkerOptions.states &&
-                        pointMarkerOptions.states[state]) || {};
-                    strokeWidth = pick(pointStateOptions.lineWidth, seriesStateOptions.lineWidth, strokeWidth + pick(pointStateOptions.lineWidthPlus, seriesStateOptions.lineWidthPlus, 0));
-                    fill = (pointStateOptions.fillColor ||
-                        seriesStateOptions.fillColor ||
-                        fill);
-                    stroke = (pointStateOptions.lineColor ||
-                        seriesStateOptions.lineColor ||
-                        stroke);
-                    opacity = pick(pointStateOptions.opacity, seriesStateOptions.opacity, opacity);
+            style: {
+              /** @internal */
+              color: "#000000",
+              /** @internal */
+              fontSize: "11px",
+              /** @internal */
+              fontWeight: "bold",
+              /** @internal */
+              textOutline: "1px contrast",
+            },
+          },
+          gridLineWidth: 1,
+          lineWidth: 0,
+          // tickWidth: 0
+        };
+        /**
+         * The Z axis or depth axis for 3D plots.
+         *
+         * See the [Axis class](/class-reference/Highcharts.Axis) for programmatic
+         * access to the axis.
+         *
+         * @sample {highcharts} highcharts/3d/scatter-zaxis-categories/
+         *         Z-Axis with Categories
+         * @sample {highcharts} highcharts/3d/scatter-zaxis-grid/
+         *         Z-Axis with styling
+         *
+         * @type      {*|Array<*>}
+         * @extends   xAxis
+         * @since     5.0.0
+         * @product   highcharts
+         * @excluding breaks, crosshair, height, left, lineColor, lineWidth,
+         *            nameToX, showEmpty, top, width
+         * @apioption zAxis
+         *
+         * @private
+         */
+        // This variable extends the defaultOptions for left axes.
+        Axis.defaultLeftAxisOptions = {
+          labels: {
+            x: -15,
+          },
+          title: {
+            rotation: 270,
+          },
+        };
+        // This variable extends the defaultOptions for right axes.
+        Axis.defaultRightAxisOptions = {
+          labels: {
+            x: 15,
+          },
+          title: {
+            rotation: 90,
+          },
+        };
+        // This variable extends the defaultOptions for bottom axes.
+        Axis.defaultBottomAxisOptions = {
+          labels: {
+            autoRotation: [-45],
+            x: 0,
+            // overflow: undefined,
+            // staggerLines: null
+          },
+          margin: 15,
+          title: {
+            rotation: 0,
+          },
+        };
+        // This variable extends the defaultOptions for top axes.
+        Axis.defaultTopAxisOptions = {
+          labels: {
+            autoRotation: [-45],
+            x: 0,
+            // overflow: undefined
+            // staggerLines: null
+          },
+          margin: 15,
+          title: {
+            rotation: 0,
+          },
+        };
+        // Properties to survive after destroy, needed for Axis.update (#4317,
+        // #5773, #5881).
+        Axis.keepProps = [
+          "extKey",
+          "hcEvents",
+          "names",
+          "series",
+          "userMax",
+          "userMin",
+        ];
+        return Axis;
+      })();
+      H.Axis = Axis;
+
+      return H.Axis;
+    }
+  );
+  _registerModule(
+    _modules,
+    "Core/Axis/DateTimeAxis.js",
+    [_modules["Core/Axis/Axis.js"], _modules["Core/Utilities.js"]],
+    function (Axis, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      var addEvent = U.addEvent,
+        getMagnitude = U.getMagnitude,
+        normalizeTickInterval = U.normalizeTickInterval,
+        timeUnits = U.timeUnits;
+      /* eslint-disable valid-jsdoc */
+      var DateTimeAxisAdditions = /** @class */ (function () {
+        /* *
+         *
+         *  Constructors
+         *
+         * */
+        function DateTimeAxisAdditions(axis) {
+          this.axis = axis;
+        }
+        /* *
+         *
+         *  Functions
+         *
+         * */
+        /**
+         * Get a normalized tick interval for dates. Returns a configuration object
+         * with unit range (interval), count and name. Used to prepare data for
+         * `getTimeTicks`. Previously this logic was part of getTimeTicks, but as
+         * `getTimeTicks` now runs of segments in stock charts, the normalizing
+         * logic was extracted in order to prevent it for running over again for
+         * each segment having the same interval. #662, #697.
+         * @private
+         */
+        /**
+         * Get a normalized tick interval for dates. Returns a configuration object
+         * with unit range (interval), count and name. Used to prepare data for
+         * `getTimeTicks`. Previously this logic was part of getTimeTicks, but as
+         * `getTimeTicks` now runs of segments in stock charts, the normalizing
+         * logic was extracted in order to prevent it for running over again for
+         * each segment having the same interval. #662, #697.
+         * @private
+         */
+        DateTimeAxisAdditions.prototype.normalizeTimeTickInterval = function (
+          tickInterval,
+          unitsOption
+        ) {
+          var units = unitsOption || [
+              [
+                "millisecond",
+                [1, 2, 5, 10, 20, 25, 50, 100, 200, 500], // allowed multiples
+              ],
+              ["second", [1, 2, 5, 10, 15, 30]],
+              ["minute", [1, 2, 5, 10, 15, 30]],
+              ["hour", [1, 2, 3, 4, 6, 8, 12]],
+              ["day", [1, 2]],
+              ["week", [1, 2]],
+              ["month", [1, 2, 3, 4, 6]],
+              ["year", null],
+            ],
+            unit = units[units.length - 1], // default unit is years
+            interval = timeUnits[unit[0]],
+            multiples = unit[1],
+            count,
+            i;
+          // loop through the units to find the one that best fits the
+          // tickInterval
+          for (i = 0; i < units.length; i++) {
+            unit = units[i];
+            interval = timeUnits[unit[0]];
+            multiples = unit[1];
+            if (units[i + 1]) {
+              // lessThan is in the middle between the highest multiple and
+              // the next unit.
+              var lessThan =
+                (interval * multiples[multiples.length - 1] +
+                  timeUnits[units[i + 1][0]]) /
+                2;
+              // break and keep the current unit
+              if (tickInterval <= lessThan) {
+                break;
+              }
+            }
+          }
+          // prevent 2.5 years intervals, though 25, 250 etc. are allowed
+          if (interval === timeUnits.year && tickInterval < 5 * interval) {
+            multiples = [1, 2, 5];
+          }
+          // get the count
+          count = normalizeTickInterval(
+            tickInterval / interval,
+            multiples,
+            unit[0] === "year" // #1913, #2360
+              ? Math.max(getMagnitude(tickInterval / interval), 1)
+              : 1
+          );
+          return {
+            unitRange: interval,
+            count: count,
+            unitName: unit[0],
+          };
+        };
+        return DateTimeAxisAdditions;
+      })();
+      /**
+       * Date and time support for axes.
+       *
+       * @private
+       * @class
+       */
+      var DateTimeAxis = /** @class */ (function () {
+        function DateTimeAxis() {}
+        /* *
+         *
+         *  Static Functions
+         *
+         * */
+        /**
+         * Extends axis class with date and time support.
+         * @private
+         */
+        DateTimeAxis.compose = function (AxisClass) {
+          AxisClass.keepProps.push("dateTime");
+          var axisProto = AxisClass.prototype;
+          /**
+           * Set the tick positions to a time unit that makes sense, for example
+           * on the first of each month or on every Monday. Return an array with
+           * the time positions. Used in datetime axes as well as for grouping
+           * data on a datetime axis.
+           *
+           * @private
+           * @function Highcharts.Axis#getTimeTicks
+           *
+           * @param {Highcharts.TimeNormalizeObject} normalizedInterval
+           * The interval in axis values (ms) and thecount.
+           *
+           * @param {number} min
+           * The minimum in axis values.
+           *
+           * @param {number} max
+           * The maximum in axis values.
+           *
+           * @param {number} startOfWeek
+           *
+           * @return {Highcharts.AxisTickPositionsArray}
+           */
+          axisProto.getTimeTicks = function () {
+            return this.chart.time.getTimeTicks.apply(
+              this.chart.time,
+              arguments
+            );
+          };
+          /* eslint-disable no-invalid-this */
+          addEvent(AxisClass, "init", function (e) {
+            var axis = this;
+            var options = e.userOptions;
+            if (options.type !== "datetime") {
+              axis.dateTime = void 0;
+              return;
+            }
+            if (!axis.dateTime) {
+              axis.dateTime = new DateTimeAxisAdditions(axis);
+            }
+          });
+          /* eslint-enable no-invalid-this */
+        };
+        /* *
+         *
+         *  Static Properties
+         *
+         * */
+        DateTimeAxis.AdditionsClass = DateTimeAxisAdditions;
+        return DateTimeAxis;
+      })();
+      DateTimeAxis.compose(Axis);
+
+      return DateTimeAxis;
+    }
+  );
+  _registerModule(
+    _modules,
+    "Core/Axis/LogarithmicAxis.js",
+    [_modules["Core/Axis/Axis.js"], _modules["Core/Utilities.js"]],
+    function (Axis, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      var addEvent = U.addEvent,
+        getMagnitude = U.getMagnitude,
+        normalizeTickInterval = U.normalizeTickInterval,
+        pick = U.pick;
+      /* eslint-disable valid-jsdoc */
+      /**
+       * Provides logarithmic support for axes.
+       *
+       * @private
+       * @class
+       */
+      var LogarithmicAxisAdditions = /** @class */ (function () {
+        /* *
+         *
+         *  Constructors
+         *
+         * */
+        function LogarithmicAxisAdditions(axis) {
+          this.axis = axis;
+        }
+        /* *
+         *
+         *  Functions
+         *
+         * */
+        /**
+         * Set the tick positions of a logarithmic axis.
+         */
+        LogarithmicAxisAdditions.prototype.getLogTickPositions = function (
+          interval,
+          min,
+          max,
+          minor
+        ) {
+          var log = this;
+          var axis = log.axis;
+          var axisLength = axis.len;
+          var options = axis.options;
+          // Since we use this method for both major and minor ticks,
+          // use a local variable and return the result
+          var positions = [];
+          // Reset
+          if (!minor) {
+            log.minorAutoInterval = void 0;
+          }
+          // First case: All ticks fall on whole logarithms: 1, 10, 100 etc.
+          if (interval >= 0.5) {
+            interval = Math.round(interval);
+            positions = axis.getLinearTickPositions(interval, min, max);
+            // Second case: We need intermediary ticks. For example
+            // 1, 2, 4, 6, 8, 10, 20, 40 etc.
+          } else if (interval >= 0.08) {
+            var roundedMin = Math.floor(min),
+              intermediate,
+              i,
+              j,
+              len,
+              pos,
+              lastPos,
+              break2;
+            if (interval > 0.3) {
+              intermediate = [1, 2, 4];
+              // 0.2 equals five minor ticks per 1, 10, 100 etc
+            } else if (interval > 0.15) {
+              intermediate = [1, 2, 4, 6, 8];
+            } else {
+              // 0.1 equals ten minor ticks per 1, 10, 100 etc
+              intermediate = [1, 2, 3, 4, 5, 6, 7, 8, 9];
+            }
+            for (i = roundedMin; i < max + 1 && !break2; i++) {
+              len = intermediate.length;
+              for (j = 0; j < len && !break2; j++) {
+                pos = log.log2lin(log.lin2log(i) * intermediate[j]);
+                // #1670, lastPos is #3113
+                if (
+                  pos > min &&
+                  (!minor || lastPos <= max) &&
+                  typeof lastPos !== "undefined"
+                ) {
+                  positions.push(lastPos);
                 }
-                return {
-                    'stroke': stroke,
-                    'stroke-width': strokeWidth,
-                    'fill': fill,
-                    'opacity': opacity
-                };
+                if (lastPos > max) {
+                  break2 = true;
+                }
+                lastPos = pos;
+              }
+            }
+            // Third case: We are so deep in between whole logarithmic values that
+            // we might as well handle the tick positions like a linear axis. For
+            // example 1.01, 1.02, 1.03, 1.04.
+          } else {
+            var realMin = log.lin2log(min),
+              realMax = log.lin2log(max),
+              tickIntervalOption = minor
+                ? axis.getMinorTickInterval()
+                : options.tickInterval,
+              filteredTickIntervalOption =
+                tickIntervalOption === "auto" ? null : tickIntervalOption,
+              tickPixelIntervalOption =
+                options.tickPixelInterval / (minor ? 5 : 1),
+              totalPixelLength = minor
+                ? axisLength / axis.tickPositions.length
+                : axisLength;
+            interval = pick(
+              filteredTickIntervalOption,
+              log.minorAutoInterval,
+              ((realMax - realMin) * tickPixelIntervalOption) /
+                (totalPixelLength || 1)
+            );
+            interval = normalizeTickInterval(
+              interval,
+              void 0,
+              getMagnitude(interval)
+            );
+            positions = axis
+              .getLinearTickPositions(interval, realMin, realMax)
+              .map(log.log2lin);
+            if (!minor) {
+              log.minorAutoInterval = interval / 5;
+            }
+          }
+          // Set the axis-level tickInterval variable
+          if (!minor) {
+            axis.tickInterval = interval;
+          }
+          return positions;
+        };
+        LogarithmicAxisAdditions.prototype.lin2log = function (num) {
+          return Math.pow(10, num);
+        };
+        LogarithmicAxisAdditions.prototype.log2lin = function (num) {
+          return Math.log(num) / Math.LN10;
+        };
+        return LogarithmicAxisAdditions;
+      })();
+      var LogarithmicAxis = /** @class */ (function () {
+        function LogarithmicAxis() {}
+        /**
+         * Provides logarithmic support for axes.
+         *
+         * @private
+         */
+        LogarithmicAxis.compose = function (AxisClass) {
+          AxisClass.keepProps.push("logarithmic");
+          // HC <= 8 backwards compatibility, allow wrapping
+          // Axis.prototype.lin2log and log2lin
+          // @todo Remove this in next major
+          var axisProto = AxisClass.prototype;
+          var logAxisProto = LogarithmicAxisAdditions.prototype;
+          axisProto.log2lin = logAxisProto.log2lin;
+          axisProto.lin2log = logAxisProto.lin2log;
+          /* eslint-disable no-invalid-this */
+          addEvent(AxisClass, "init", function (e) {
+            var axis = this;
+            var options = e.userOptions;
+            var logarithmic = axis.logarithmic;
+            if (options.type !== "logarithmic") {
+              axis.logarithmic = void 0;
+            } else {
+              if (!logarithmic) {
+                logarithmic = axis.logarithmic = new LogarithmicAxisAdditions(
+                  axis
+                );
+              }
+              // HC <= 8 backwards compatibility, allow wrapping
+              // Axis.prototype.lin2log and log2lin
+              // @todo Remove this in next major
+              if (axis.log2lin !== logarithmic.log2lin) {
+                logarithmic.log2lin = axis.log2lin.bind(axis);
+              }
+              if (axis.lin2log !== logarithmic.lin2log) {
+                logarithmic.lin2log = axis.lin2log.bind(axis);
+              }
+            }
+          });
+          addEvent(AxisClass, "afterInit", function () {
+            var axis = this;
+            var log = axis.logarithmic;
+            // extend logarithmic axis
+            if (log) {
+              axis.lin2val = function (num) {
+                return log.lin2log(num);
+              };
+              axis.val2lin = function (num) {
+                return log.log2lin(num);
+              };
+            }
+          });
+        };
+        return LogarithmicAxis;
+      })();
+      LogarithmicAxis.compose(Axis); // @todo move to factory functions
+
+      return LogarithmicAxis;
+    }
+  );
+  _registerModule(
+    _modules,
+    "Core/Axis/PlotLineOrBand.js",
+    [
+      _modules["Core/Axis/Axis.js"],
+      _modules["Core/Globals.js"],
+      _modules["Core/Utilities.js"],
+    ],
+    function (Axis, H, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      /**
+       * Options for plot bands on axes.
+       *
+       * @typedef {Highcharts.XAxisPlotBandsOptions|Highcharts.YAxisPlotBandsOptions|Highcharts.ZAxisPlotBandsOptions} Highcharts.AxisPlotBandsOptions
+       */
+      /**
+       * Options for plot band labels on axes.
+       *
+       * @typedef {Highcharts.XAxisPlotBandsLabelOptions|Highcharts.YAxisPlotBandsLabelOptions|Highcharts.ZAxisPlotBandsLabelOptions} Highcharts.AxisPlotBandsLabelOptions
+       */
+      /**
+       * Options for plot lines on axes.
+       *
+       * @typedef {Highcharts.XAxisPlotLinesOptions|Highcharts.YAxisPlotLinesOptions|Highcharts.ZAxisPlotLinesOptions} Highcharts.AxisPlotLinesOptions
+       */
+      /**
+       * Options for plot line labels on axes.
+       *
+       * @typedef {Highcharts.XAxisPlotLinesLabelOptions|Highcharts.YAxisPlotLinesLabelOptions|Highcharts.ZAxisPlotLinesLabelOptions} Highcharts.AxisPlotLinesLabelOptions
+       */
+      var arrayMax = U.arrayMax,
+        arrayMin = U.arrayMin,
+        defined = U.defined,
+        destroyObjectProperties = U.destroyObjectProperties,
+        erase = U.erase,
+        extend = U.extend,
+        merge = U.merge,
+        objectEach = U.objectEach,
+        pick = U.pick;
+      /* eslint-disable no-invalid-this, valid-jsdoc */
+      /**
+       * The object wrapper for plot lines and plot bands
+       *
+       * @class
+       * @name Highcharts.PlotLineOrBand
+       *
+       * @param {Highcharts.Axis} axis
+       *
+       * @param {Highcharts.AxisPlotLinesOptions|Highcharts.AxisPlotBandsOptions} [options]
+       */
+      var PlotLineOrBand = /** @class */ (function () {
+        function PlotLineOrBand(axis, options) {
+          this.axis = axis;
+          if (options) {
+            this.options = options;
+            this.id = options.id;
+          }
+        }
+        /**
+         * Render the plot line or plot band. If it is already existing,
+         * move it.
+         *
+         * @private
+         * @function Highcharts.PlotLineOrBand#render
+         * @return {Highcharts.PlotLineOrBand|undefined}
+         */
+        PlotLineOrBand.prototype.render = function () {
+          H.fireEvent(this, "render");
+          var plotLine = this,
+            axis = plotLine.axis,
+            horiz = axis.horiz,
+            log = axis.logarithmic,
+            options = plotLine.options,
+            optionsLabel = options.label,
+            label = plotLine.label,
+            to = options.to,
+            from = options.from,
+            value = options.value,
+            isBand = defined(from) && defined(to),
+            isLine = defined(value),
+            svgElem = plotLine.svgElem,
+            isNew = !svgElem,
+            path = [],
+            color = options.color,
+            zIndex = pick(options.zIndex, 0),
+            events = options.events,
+            attribs = {
+              class:
+                "highcharts-plot-" +
+                (isBand ? "band " : "line ") +
+                (options.className || ""),
+            },
+            groupAttribs = {},
+            renderer = axis.chart.renderer,
+            groupName = isBand ? "bands" : "lines",
+            group;
+          // logarithmic conversion
+          if (log) {
+            from = log.log2lin(from);
+            to = log.log2lin(to);
+            value = log.log2lin(value);
+          }
+          // Set the presentational attributes
+          if (!axis.chart.styledMode) {
+            if (isLine) {
+              attribs.stroke = color || "#999999";
+              attribs["stroke-width"] = pick(options.width, 1);
+              if (options.dashStyle) {
+                attribs.dashstyle = options.dashStyle;
+              }
+            } else if (isBand) {
+              // plot band
+              attribs.fill = color || "#e6ebf5";
+              if (options.borderWidth) {
+                attribs.stroke = options.borderColor;
+                attribs["stroke-width"] = options.borderWidth;
+              }
+            }
+          }
+          // Grouping and zIndex
+          groupAttribs.zIndex = zIndex;
+          groupName += "-" + zIndex;
+          group = axis.plotLinesAndBandsGroups[groupName];
+          if (!group) {
+            axis.plotLinesAndBandsGroups[groupName] = group = renderer
+              .g("plot-" + groupName)
+              .attr(groupAttribs)
+              .add();
+          }
+          // Create the path
+          if (isNew) {
+            /**
+             * SVG element of the plot line or band.
+             *
+             * @name Highcharts.PlotLineOrBand#svgElement
+             * @type {Highcharts.SVGElement}
+             */
+            plotLine.svgElem = svgElem = renderer
+              .path()
+              .attr(attribs)
+              .add(group);
+          }
+          // Set the path or return
+          if (isLine) {
+            path = axis.getPlotLinePath({
+              value: value,
+              lineWidth: svgElem.strokeWidth(),
+              acrossPanes: options.acrossPanes,
+            });
+          } else if (isBand) {
+            // plot band
+            path = axis.getPlotBandPath(from, to, options);
+          } else {
+            return;
+          }
+          // common for lines and bands
+          // Add events only if they were not added before.
+          if (!plotLine.eventsAdded && events) {
+            objectEach(events, function (event, eventType) {
+              svgElem.on(eventType, function (e) {
+                events[eventType].apply(plotLine, [e]);
+              });
+            });
+            plotLine.eventsAdded = true;
+          }
+          if ((isNew || !svgElem.d) && path && path.length) {
+            svgElem.attr({ d: path });
+          } else if (svgElem) {
+            if (path) {
+              svgElem.show(true);
+              svgElem.animate({ d: path });
+            } else if (svgElem.d) {
+              svgElem.hide();
+              if (label) {
+                plotLine.label = label = label.destroy();
+              }
+            }
+          }
+          // the plot band/line label
+          if (
+            optionsLabel &&
+            (defined(optionsLabel.text) || defined(optionsLabel.formatter)) &&
+            path &&
+            path.length &&
+            axis.width > 0 &&
+            axis.height > 0 &&
+            !path.isFlat
+          ) {
+            // apply defaults
+            optionsLabel = merge(
+              {
+                align: horiz && isBand && "center",
+                x: horiz ? !isBand && 4 : 10,
+                verticalAlign: !horiz && isBand && "middle",
+                y: horiz ? (isBand ? 16 : 10) : isBand ? 6 : -4,
+                rotation: horiz && !isBand && 90,
+              },
+              optionsLabel
+            );
+            this.renderLabel(optionsLabel, path, isBand, zIndex);
+          } else if (label) {
+            // move out of sight
+            label.hide();
+          }
+          // chainable
+          return plotLine;
+        };
+        /**
+         * Render and align label for plot line or band.
+         *
+         * @private
+         * @function Highcharts.PlotLineOrBand#renderLabel
+         * @param {Highcharts.AxisPlotLinesLabelOptions|Highcharts.AxisPlotBandsLabelOptions} optionsLabel
+         * @param {Highcharts.SVGPathArray} path
+         * @param {boolean} [isBand]
+         * @param {number} [zIndex]
+         * @return {void}
+         */
+        PlotLineOrBand.prototype.renderLabel = function (
+          optionsLabel,
+          path,
+          isBand,
+          zIndex
+        ) {
+          var plotLine = this,
+            label = plotLine.label,
+            renderer = plotLine.axis.chart.renderer,
+            attribs,
+            xBounds,
+            yBounds,
+            x,
+            y,
+            labelText;
+          // add the SVG element
+          if (!label) {
+            attribs = {
+              align: optionsLabel.textAlign || optionsLabel.align,
+              rotation: optionsLabel.rotation,
+              class:
+                "highcharts-plot-" +
+                (isBand ? "band" : "line") +
+                "-label " +
+                (optionsLabel.className || ""),
+            };
+            attribs.zIndex = zIndex;
+            labelText = this.getLabelText(optionsLabel);
+            /**
+             * SVG element of the label.
+             *
+             * @name Highcharts.PlotLineOrBand#label
+             * @type {Highcharts.SVGElement}
+             */
+            plotLine.label = label = renderer
+              .text(labelText, 0, 0, optionsLabel.useHTML)
+              .attr(attribs)
+              .add();
+            if (!this.axis.chart.styledMode) {
+              label.css(optionsLabel.style);
+            }
+          }
+          // get the bounding box and align the label
+          // #3000 changed to better handle choice between plotband or plotline
+          xBounds = path.xBounds || [
+            path[0][1],
+            path[1][1],
+            isBand ? path[2][1] : path[0][1],
+          ];
+          yBounds = path.yBounds || [
+            path[0][2],
+            path[1][2],
+            isBand ? path[2][2] : path[0][2],
+          ];
+          x = arrayMin(xBounds);
+          y = arrayMin(yBounds);
+          label.align(optionsLabel, false, {
+            x: x,
+            y: y,
+            width: arrayMax(xBounds) - x,
+            height: arrayMax(yBounds) - y,
+          });
+          label.show(true);
+        };
+        /**
+         * Get label's text content.
+         *
+         * @private
+         * @function Highcharts.PlotLineOrBand#getLabelText
+         * @param {Highcharts.AxisPlotLinesLabelOptions|Highcharts.AxisPlotBandsLabelOptions} optionsLabel
+         * @return {string}
+         */
+        PlotLineOrBand.prototype.getLabelText = function (optionsLabel) {
+          return defined(optionsLabel.formatter)
+            ? optionsLabel.formatter.call(this)
+            : optionsLabel.text;
+        };
+        /**
+         * Remove the plot line or band.
+         *
+         * @function Highcharts.PlotLineOrBand#destroy
+         * @return {void}
+         */
+        PlotLineOrBand.prototype.destroy = function () {
+          // remove it from the lookup
+          erase(this.axis.plotLinesAndBands, this);
+          delete this.axis;
+          destroyObjectProperties(this);
+        };
+        return PlotLineOrBand;
+      })();
+      /* eslint-enable no-invalid-this, valid-jsdoc */
+      // Object with members for extending the Axis prototype
+      extend(
+        Axis.prototype,
+        /** @lends Highcharts.Axis.prototype */ {
+          /**
+           * An array of colored bands stretching across the plot area marking an
+           * interval on the axis.
+           *
+           * In styled mode, the plot bands are styled by the `.highcharts-plot-band`
+           * class in addition to the `className` option.
+           *
+           * @productdesc {highcharts}
+           * In a gauge, a plot band on the Y axis (value axis) will stretch along the
+           * perimeter of the gauge.
+           *
+           * @type      {Array<*>}
+           * @product   highcharts highstock gantt
+           * @apioption xAxis.plotBands
+           */
+          /**
+           * Flag to decide if plotBand should be rendered across all panes.
+           *
+           * @since     7.1.2
+           * @product   highstock
+           * @type      {boolean}
+           * @default   true
+           * @apioption xAxis.plotBands.acrossPanes
+           */
+          /**
+           * Border color for the plot band. Also requires `borderWidth` to be set.
+           *
+           * @type      {Highcharts.ColorString}
+           * @apioption xAxis.plotBands.borderColor
+           */
+          /**
+           * Border width for the plot band. Also requires `borderColor` to be set.
+           *
+           * @type      {number}
+           * @default   0
+           * @apioption xAxis.plotBands.borderWidth
+           */
+          /**
+           * A custom class name, in addition to the default `highcharts-plot-band`,
+           * to apply to each individual band.
+           *
+           * @type      {string}
+           * @since     5.0.0
+           * @apioption xAxis.plotBands.className
+           */
+          /**
+           * The color of the plot band.
+           *
+           * @sample {highcharts} highcharts/xaxis/plotbands-color/
+           *         Color band
+           * @sample {highstock} stock/xaxis/plotbands/
+           *         Plot band on Y axis
+           *
+           * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+           * @default   #e6ebf5
+           * @apioption xAxis.plotBands.color
+           */
+          /**
+           * An object defining mouse events for the plot band. Supported properties
+           * are `click`, `mouseover`, `mouseout`, `mousemove`.
+           *
+           * @sample {highcharts} highcharts/xaxis/plotbands-events/
+           *         Mouse events demonstrated
+           *
+           * @since     1.2
+           * @apioption xAxis.plotBands.events
+           */
+          /**
+           * Click event on a plot band.
+           *
+           * @type      {Highcharts.EventCallbackFunction<Highcharts.PlotLineOrBand>}
+           * @apioption xAxis.plotBands.events.click
+           */
+          /**
+           * Mouse move event on a plot band.
+           *
+           * @type      {Highcharts.EventCallbackFunction<Highcharts.PlotLineOrBand>}
+           * @apioption xAxis.plotBands.events.mousemove
+           */
+          /**
+           * Mouse out event on the corner of a plot band.
+           *
+           * @type      {Highcharts.EventCallbackFunction<Highcharts.PlotLineOrBand>}
+           * @apioption xAxis.plotBands.events.mouseout
+           */
+          /**
+           * Mouse over event on a plot band.
+           *
+           * @type      {Highcharts.EventCallbackFunction<Highcharts.PlotLineOrBand>}
+           * @apioption xAxis.plotBands.events.mouseover
+           */
+          /**
+           * The start position of the plot band in axis units.
+           *
+           * @sample {highcharts} highcharts/xaxis/plotbands-color/
+           *         Datetime axis
+           * @sample {highcharts} highcharts/xaxis/plotbands-from/
+           *         Categorized axis
+           * @sample {highstock} stock/xaxis/plotbands/
+           *         Plot band on Y axis
+           *
+           * @type      {number}
+           * @apioption xAxis.plotBands.from
+           */
+          /**
+           * An id used for identifying the plot band in Axis.removePlotBand.
+           *
+           * @sample {highcharts} highcharts/xaxis/plotbands-id/
+           *         Remove plot band by id
+           * @sample {highstock} highcharts/xaxis/plotbands-id/
+           *         Remove plot band by id
+           *
+           * @type      {string}
+           * @apioption xAxis.plotBands.id
+           */
+          /**
+           * The end position of the plot band in axis units.
+           *
+           * @sample {highcharts} highcharts/xaxis/plotbands-color/
+           *         Datetime axis
+           * @sample {highcharts} highcharts/xaxis/plotbands-from/
+           *         Categorized axis
+           * @sample {highstock} stock/xaxis/plotbands/
+           *         Plot band on Y axis
+           *
+           * @type      {number}
+           * @apioption xAxis.plotBands.to
+           */
+          /**
+           * The z index of the plot band within the chart, relative to other
+           * elements. Using the same z index as another element may give
+           * unpredictable results, as the last rendered element will be on top.
+           * Values from 0 to 20 make sense.
+           *
+           * @sample {highcharts} highcharts/xaxis/plotbands-color/
+           *         Behind plot lines by default
+           * @sample {highcharts} highcharts/xaxis/plotbands-zindex/
+           *         Above plot lines
+           * @sample {highcharts} highcharts/xaxis/plotbands-zindex-above-series/
+           *         Above plot lines and series
+           *
+           * @type      {number}
+           * @since     1.2
+           * @apioption xAxis.plotBands.zIndex
+           */
+          /**
+           * Text labels for the plot bands
+           *
+           * @product   highcharts highstock gantt
+           * @apioption xAxis.plotBands.label
+           */
+          /**
+           * Horizontal alignment of the label. Can be one of "left", "center" or
+           * "right".
+           *
+           * @sample {highcharts} highcharts/xaxis/plotbands-label-align/
+           *         Aligned to the right
+           * @sample {highstock} stock/xaxis/plotbands-label/
+           *         Plot band with labels
+           *
+           * @type      {Highcharts.AlignValue}
+           * @default   center
+           * @since     2.1
+           * @apioption xAxis.plotBands.label.align
+           */
+          /**
+           * Rotation of the text label in degrees .
+           *
+           * @sample {highcharts} highcharts/xaxis/plotbands-label-rotation/
+           *         Vertical text
+           *
+           * @type      {number}
+           * @default   0
+           * @since     2.1
+           * @apioption xAxis.plotBands.label.rotation
+           */
+          /**
+           * CSS styles for the text label.
+           *
+           * In styled mode, the labels are styled by the
+           * `.highcharts-plot-band-label` class.
+           *
+           * @sample {highcharts} highcharts/xaxis/plotbands-label-style/
+           *         Blue and bold label
+           *
+           * @type      {Highcharts.CSSObject}
+           * @since     2.1
+           * @apioption xAxis.plotBands.label.style
+           */
+          /**
+           * The string text itself. A subset of HTML is supported.
+           *
+           * @type      {string}
+           * @since     2.1
+           * @apioption xAxis.plotBands.label.text
+           */
+          /**
+           * The text alignment for the label. While `align` determines where the
+           * texts anchor point is placed within the plot band, `textAlign` determines
+           * how the text is aligned against its anchor point. Possible values are
+           * "left", "center" and "right". Defaults to the same as the `align` option.
+           *
+           * @sample {highcharts} highcharts/xaxis/plotbands-label-rotation/
+           *         Vertical text in center position but text-aligned left
+           *
+           * @type       {Highcharts.AlignValue}
+           * @since      2.1
+           * @apioption  xAxis.plotBands.label.textAlign
+           */
+          /**
+           * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html)
+           * to render the labels.
+           *
+           * @type      {boolean}
+           * @default   false
+           * @since     3.0.3
+           * @apioption xAxis.plotBands.label.useHTML
+           */
+          /**
+           * Vertical alignment of the label relative to the plot band. Can be one of
+           * "top", "middle" or "bottom".
+           *
+           * @sample {highcharts} highcharts/xaxis/plotbands-label-verticalalign/
+           *         Vertically centered label
+           * @sample {highstock} stock/xaxis/plotbands-label/
+           *         Plot band with labels
+           *
+           * @type       {Highcharts.VerticalAlignValue}
+           * @default    top
+           * @since      2.1
+           * @apioption  xAxis.plotBands.label.verticalAlign
+           */
+          /**
+           * Horizontal position relative the alignment. Default varies by
+           * orientation.
+           *
+           * @sample {highcharts} highcharts/xaxis/plotbands-label-align/
+           *         Aligned 10px from the right edge
+           * @sample {highstock} stock/xaxis/plotbands-label/
+           *         Plot band with labels
+           *
+           * @type      {number}
+           * @since     2.1
+           * @apioption xAxis.plotBands.label.x
+           */
+          /**
+           * Vertical position of the text baseline relative to the alignment. Default
+           * varies by orientation.
+           *
+           * @sample {highcharts} highcharts/xaxis/plotbands-label-y/
+           *         Label on x axis
+           * @sample {highstock} stock/xaxis/plotbands-label/
+           *         Plot band with labels
+           *
+           * @type      {number}
+           * @since     2.1
+           * @apioption xAxis.plotBands.label.y
+           */
+          /**
+           * An array of lines stretching across the plot area, marking a specific
+           * value on one of the axes.
+           *
+           * In styled mode, the plot lines are styled by the
+           * `.highcharts-plot-line` class in addition to the `className` option.
+           *
+           * @type      {Array<*>}
+           * @product   highcharts highstock gantt
+           * @sample {highcharts} highcharts/xaxis/plotlines-color/
+           *         Basic plot line
+           * @sample {highcharts} highcharts/series-solidgauge/labels-auto-aligned/
+           *         Solid gauge plot line
+           * @apioption xAxis.plotLines
+           */
+          /**
+           * Flag to decide if plotLine should be rendered across all panes.
+           *
+           * @sample {highstock} stock/xaxis/plotlines-acrosspanes/
+           *         Plot lines on different panes
+           *
+           * @since     7.1.2
+           * @product   highstock
+           * @type      {boolean}
+           * @default   true
+           * @apioption xAxis.plotLines.acrossPanes
+           */
+          /**
+           * A custom class name, in addition to the default `highcharts-plot-line`,
+           * to apply to each individual line.
+           *
+           * @type      {string}
+           * @since     5.0.0
+           * @apioption xAxis.plotLines.className
+           */
+          /**
+           * The color of the line.
+           *
+           * @sample {highcharts} highcharts/xaxis/plotlines-color/
+           *         A red line from X axis
+           * @sample {highstock} stock/xaxis/plotlines/
+           *         Plot line on Y axis
+           *
+           * @type      {Highcharts.ColorString}
+           * @default   #999999
+           * @apioption xAxis.plotLines.color
+           */
+          /**
+           * The dashing or dot style for the plot line. For possible values see
+           * [this overview](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/series-dashstyle-all/).
+           *
+           * @sample {highcharts} highcharts/xaxis/plotlines-dashstyle/
+           *         Dash and dot pattern
+           * @sample {highstock} stock/xaxis/plotlines/
+           *         Plot line on Y axis
+           *
+           * @type      {Highcharts.DashStyleValue}
+           * @default   Solid
+           * @since     1.2
+           * @apioption xAxis.plotLines.dashStyle
+           */
+          /**
+           * An object defining mouse events for the plot line. Supported
+           * properties are `click`, `mouseover`, `mouseout`, `mousemove`.
+           *
+           * @sample {highcharts} highcharts/xaxis/plotlines-events/
+           *         Mouse events demonstrated
+           *
+           * @since     1.2
+           * @apioption xAxis.plotLines.events
+           */
+          /**
+           * Click event on a plot band.
+           *
+           * @type      {Highcharts.EventCallbackFunction<Highcharts.PlotLineOrBand>}
+           * @apioption xAxis.plotLines.events.click
+           */
+          /**
+           * Mouse move event on a plot band.
+           *
+           * @type      {Highcharts.EventCallbackFunction<Highcharts.PlotLineOrBand>}
+           * @apioption xAxis.plotLines.events.mousemove
+           */
+          /**
+           * Mouse out event on the corner of a plot band.
+           *
+           * @type      {Highcharts.EventCallbackFunction<Highcharts.PlotLineOrBand>}
+           * @apioption xAxis.plotLines.events.mouseout
+           */
+          /**
+           * Mouse over event on a plot band.
+           *
+           * @type      {Highcharts.EventCallbackFunction<Highcharts.PlotLineOrBand>}
+           * @apioption xAxis.plotLines.events.mouseover
+           */
+          /**
+           * An id used for identifying the plot line in Axis.removePlotLine.
+           *
+           * @sample {highcharts} highcharts/xaxis/plotlines-id/
+           *         Remove plot line by id
+           *
+           * @type      {string}
+           * @apioption xAxis.plotLines.id
+           */
+          /**
+           * The position of the line in axis units.
+           *
+           * @sample {highcharts} highcharts/xaxis/plotlines-color/
+           *         Between two categories on X axis
+           * @sample {highstock} stock/xaxis/plotlines/
+           *         Plot line on Y axis
+           *
+           * @type      {number}
+           * @apioption xAxis.plotLines.value
+           */
+          /**
+           * The width or thickness of the plot line.
+           *
+           * @sample {highcharts} highcharts/xaxis/plotlines-color/
+           *         2px wide line from X axis
+           * @sample {highstock} stock/xaxis/plotlines/
+           *         Plot line on Y axis
+           *
+           * @type      {number}
+           * @default   2
+           * @apioption xAxis.plotLines.width
+           */
+          /**
+           * The z index of the plot line within the chart.
+           *
+           * @sample {highcharts} highcharts/xaxis/plotlines-zindex-behind/
+           *         Behind plot lines by default
+           * @sample {highcharts} highcharts/xaxis/plotlines-zindex-above/
+           *         Above plot lines
+           * @sample {highcharts} highcharts/xaxis/plotlines-zindex-above-all/
+           *         Above plot lines and series
+           *
+           * @type      {number}
+           * @since     1.2
+           * @apioption xAxis.plotLines.zIndex
+           */
+          /**
+           * Text labels for the plot bands
+           *
+           * @apioption xAxis.plotLines.label
+           */
+          /**
+           * Horizontal alignment of the label. Can be one of "left", "center" or
+           * "right".
+           *
+           * @sample {highcharts} highcharts/xaxis/plotlines-label-align-right/
+           *         Aligned to the right
+           * @sample {highstock} stock/xaxis/plotlines/
+           *         Plot line on Y axis
+           *
+           * @type       {Highcharts.AlignValue}
+           * @default    left
+           * @since      2.1
+           * @apioption  xAxis.plotLines.label.align
+           */
+          /**
+           * Callback JavaScript function to format the label. Useful properties like
+           * the value of plot line or the range of plot band (`from` & `to`
+           * properties) can be found in `this.options` object.
+           *
+           * @sample {highcharts} highcharts/xaxis/plotlines-plotbands-label-formatter
+           *         Label formatters for plot line and plot band.
+           * @type      {Highcharts.FormatterCallbackFunction<Highcharts.PlotLineOrBand>}
+           * @apioption xAxis.plotLines.label.formatter
+           */
+          /**
+           * Rotation of the text label in degrees. Defaults to 0 for horizontal plot
+           * lines and 90 for vertical lines.
+           *
+           * @sample {highcharts} highcharts/xaxis/plotlines-label-verticalalign-middle/
+           *         Slanted text
+           *
+           * @type      {number}
+           * @since     2.1
+           * @apioption xAxis.plotLines.label.rotation
+           */
+          /**
+           * CSS styles for the text label.
+           *
+           * In styled mode, the labels are styled by the
+           * `.highcharts-plot-line-label` class.
+           *
+           * @sample {highcharts} highcharts/xaxis/plotlines-label-style/
+           *         Blue and bold label
+           *
+           * @type      {Highcharts.CSSObject}
+           * @since     2.1
+           * @apioption xAxis.plotLines.label.style
+           */
+          /**
+           * The text itself. A subset of HTML is supported.
+           *
+           * @type      {string}
+           * @since     2.1
+           * @apioption xAxis.plotLines.label.text
+           */
+          /**
+           * The text alignment for the label. While `align` determines where the
+           * texts anchor point is placed within the plot band, `textAlign` determines
+           * how the text is aligned against its anchor point. Possible values are
+           * "left", "center" and "right". Defaults to the same as the `align` option.
+           *
+           * @sample {highcharts} highcharts/xaxis/plotlines-label-textalign/
+           *         Text label in bottom position
+           *
+           * @type      {Highcharts.AlignValue}
+           * @since     2.1
+           * @apioption xAxis.plotLines.label.textAlign
+           */
+          /**
+           * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html)
+           * to render the labels.
+           *
+           * @type      {boolean}
+           * @default   false
+           * @since     3.0.3
+           * @apioption xAxis.plotLines.label.useHTML
+           */
+          /**
+           * Vertical alignment of the label relative to the plot line. Can be
+           * one of "top", "middle" or "bottom".
+           *
+           * @sample {highcharts} highcharts/xaxis/plotlines-label-verticalalign-middle/
+           *         Vertically centered label
+           *
+           * @type       {Highcharts.VerticalAlignValue}
+           * @default    {highcharts} top
+           * @default    {highstock} top
+           * @since      2.1
+           * @apioption  xAxis.plotLines.label.verticalAlign
+           */
+          /**
+           * Horizontal position relative the alignment. Default varies by
+           * orientation.
+           *
+           * @sample {highcharts} highcharts/xaxis/plotlines-label-align-right/
+           *         Aligned 10px from the right edge
+           * @sample {highstock} stock/xaxis/plotlines/
+           *         Plot line on Y axis
+           *
+           * @type      {number}
+           * @since     2.1
+           * @apioption xAxis.plotLines.label.x
+           */
+          /**
+           * Vertical position of the text baseline relative to the alignment. Default
+           * varies by orientation.
+           *
+           * @sample {highcharts} highcharts/xaxis/plotlines-label-y/
+           *         Label below the plot line
+           * @sample {highstock} stock/xaxis/plotlines/
+           *         Plot line on Y axis
+           *
+           * @type      {number}
+           * @since     2.1
+           * @apioption xAxis.plotLines.label.y
+           */
+          /**
+           *
+           * @type      {Array<*>}
+           * @extends   xAxis.plotBands
+           * @apioption yAxis.plotBands
+           */
+          /**
+           * In a gauge chart, this option determines the inner radius of the
+           * plot band that stretches along the perimeter. It can be given as
+           * a percentage string, like `"100%"`, or as a pixel number, like `100`.
+           * By default, the inner radius is controlled by the [thickness](
+           * #yAxis.plotBands.thickness) option.
+           *
+           * @sample {highcharts} highcharts/xaxis/plotbands-gauge
+           *         Gauge plot band
+           *
+           * @type      {number|string}
+           * @since     2.3
+           * @product   highcharts
+           * @apioption yAxis.plotBands.innerRadius
+           */
+          /**
+           * In a gauge chart, this option determines the outer radius of the
+           * plot band that stretches along the perimeter. It can be given as
+           * a percentage string, like `"100%"`, or as a pixel number, like `100`.
+           *
+           * @sample {highcharts} highcharts/xaxis/plotbands-gauge
+           *         Gauge plot band
+           *
+           * @type      {number|string}
+           * @default   100%
+           * @since     2.3
+           * @product   highcharts
+           * @apioption yAxis.plotBands.outerRadius
+           */
+          /**
+           * In a gauge chart, this option sets the width of the plot band
+           * stretching along the perimeter. It can be given as a percentage
+           * string, like `"10%"`, or as a pixel number, like `10`. The default
+           * value 10 is the same as the default [tickLength](#yAxis.tickLength),
+           * thus making the plot band act as a background for the tick markers.
+           *
+           * @sample {highcharts} highcharts/xaxis/plotbands-gauge
+           *         Gauge plot band
+           *
+           * @type      {number|string}
+           * @default   10
+           * @since     2.3
+           * @product   highcharts
+           * @apioption yAxis.plotBands.thickness
+           */
+          /**
+           * @type      {Array<*>}
+           * @extends   xAxis.plotLines
+           * @apioption yAxis.plotLines
+           */
+          /* eslint-disable no-invalid-this, valid-jsdoc */
+          /**
+           * Internal function to create the SVG path definition for a plot band.
+           *
+           * @function Highcharts.Axis#getPlotBandPath
+           *
+           * @param {number} from
+           *        The axis value to start from.
+           *
+           * @param {number} to
+           *        The axis value to end on.
+           *
+           * @param {Highcharts.AxisPlotBandsOptions|Highcharts.AxisPlotLinesOptions} options
+           *        The plotBand or plotLine configuration object.
+           *
+           * @return {Highcharts.SVGPathArray}
+           *         The SVG path definition in array form.
+           */
+          getPlotBandPath: function (from, to, options) {
+            if (options === void 0) {
+              options = this.options;
+            }
+            var toPath = this.getPlotLinePath({
+                value: to,
+                force: true,
+                acrossPanes: options.acrossPanes,
+              }),
+              path = this.getPlotLinePath({
+                value: from,
+                force: true,
+                acrossPanes: options.acrossPanes,
+              }),
+              result = [],
+              i,
+              // #4964 check if chart is inverted or plotband is on yAxis
+              horiz = this.horiz,
+              plus = 1,
+              isFlat,
+              outside =
+                (from < this.min && to < this.min) ||
+                (from > this.max && to > this.max);
+            if (path && toPath) {
+              // Flat paths don't need labels (#3836)
+              if (outside) {
+                isFlat = path.toString() === toPath.toString();
+                plus = 0;
+              }
+              // Go over each subpath - for panes in Highstock
+              for (i = 0; i < path.length; i += 2) {
+                var pathStart = path[i],
+                  pathEnd = path[i + 1],
+                  toPathStart = toPath[i],
+                  toPathEnd = toPath[i + 1];
+                // Type checking all affected path segments. Consider something
+                // smarter.
+                if (
+                  (pathStart[0] === "M" || pathStart[0] === "L") &&
+                  (pathEnd[0] === "M" || pathEnd[0] === "L") &&
+                  (toPathStart[0] === "M" || toPathStart[0] === "L") &&
+                  (toPathEnd[0] === "M" || toPathEnd[0] === "L")
+                ) {
+                  // Add 1 pixel when coordinates are the same
+                  if (horiz && toPathStart[1] === pathStart[1]) {
+                    toPathStart[1] += plus;
+                    toPathEnd[1] += plus;
+                  } else if (!horiz && toPathStart[2] === pathStart[2]) {
+                    toPathStart[2] += plus;
+                    toPathEnd[2] += plus;
+                  }
+                  result.push(
+                    ["M", pathStart[1], pathStart[2]],
+                    ["L", pathEnd[1], pathEnd[2]],
+                    ["L", toPathEnd[1], toPathEnd[2]],
+                    ["L", toPathStart[1], toPathStart[2]],
+                    ["Z"]
+                  );
+                }
+                result.isFlat = isFlat;
+              }
+            } else {
+              // outside the axis area
+              path = null;
+            }
+            return result;
+          },
+          /**
+           * Add a plot band after render time.
+           *
+           * @sample highcharts/members/axis-addplotband/
+           *         Toggle the plot band from a button
+           *
+           * @function Highcharts.Axis#addPlotBand
+           *
+           * @param {Highcharts.AxisPlotBandsOptions} options
+           *        A configuration object for the plot band, as defined in
+           *        [xAxis.plotBands](https://api.highcharts.com/highcharts/xAxis.plotBands).
+           *
+           * @return {Highcharts.PlotLineOrBand|undefined}
+           *         The added plot band.
+           */
+          addPlotBand: function (options) {
+            return this.addPlotBandOrLine(options, "plotBands");
+          },
+          /**
+           * Add a plot line after render time.
+           *
+           * @sample highcharts/members/axis-addplotline/
+           *         Toggle the plot line from a button
+           *
+           * @function Highcharts.Axis#addPlotLine
+           *
+           * @param {Highcharts.AxisPlotLinesOptions} options
+           *        A configuration object for the plot line, as defined in
+           *        [xAxis.plotLines](https://api.highcharts.com/highcharts/xAxis.plotLines).
+           *
+           * @return {Highcharts.PlotLineOrBand|undefined}
+           *         The added plot line.
+           */
+          addPlotLine: function (options) {
+            return this.addPlotBandOrLine(options, "plotLines");
+          },
+          /**
+           * Add a plot band or plot line after render time. Called from addPlotBand
+           * and addPlotLine internally.
+           *
+           * @private
+           * @function Highcharts.Axis#addPlotBandOrLine
+           *
+           * @param {Highcharts.AxisPlotBandsOptions|Highcharts.AxisPlotLinesOptions} options
+           *        The plotBand or plotLine configuration object.
+           *
+           * @param {"plotBands"|"plotLines"} [coll]
+           *
+           * @return {Highcharts.PlotLineOrBand|undefined}
+           */
+          addPlotBandOrLine: function (options, coll) {
+            var obj = new H.PlotLineOrBand(this, options),
+              userOptions = this.userOptions;
+            if (this.visible) {
+              obj = obj.render();
+            }
+            if (obj) {
+              // #2189
+              // Add it to the user options for exporting and Axis.update
+              if (coll) {
+                // Workaround Microsoft/TypeScript issue #32693
+                var updatedOptions = userOptions[coll] || [];
+                updatedOptions.push(options);
+                userOptions[coll] = updatedOptions;
+              }
+              this.plotLinesAndBands.push(obj);
+              this._addedPlotLB = true;
+            }
+            return obj;
+          },
+          /**
+           * Remove a plot band or plot line from the chart by id. Called internally
+           * from `removePlotBand` and `removePlotLine`.
+           *
+           * @private
+           * @function Highcharts.Axis#removePlotBandOrLine
+           * @param {string} id
+           * @return {void}
+           */
+          removePlotBandOrLine: function (id) {
+            var plotLinesAndBands = this.plotLinesAndBands,
+              options = this.options,
+              userOptions = this.userOptions,
+              i = plotLinesAndBands.length;
+            while (i--) {
+              if (plotLinesAndBands[i].id === id) {
+                plotLinesAndBands[i].destroy();
+              }
+            }
+            [
+              options.plotLines || [],
+              userOptions.plotLines || [],
+              options.plotBands || [],
+              userOptions.plotBands || [],
+            ].forEach(function (arr) {
+              i = arr.length;
+              while (i--) {
+                if ((arr[i] || {}).id === id) {
+                  erase(arr, arr[i]);
+                }
+              }
+            });
+          },
+          /**
+           * Remove a plot band by its id.
+           *
+           * @sample highcharts/members/axis-removeplotband/
+           *         Remove plot band by id
+           * @sample highcharts/members/axis-addplotband/
+           *         Toggle the plot band from a button
+           *
+           * @function Highcharts.Axis#removePlotBand
+           *
+           * @param {string} id
+           *        The plot band's `id` as given in the original configuration
+           *        object or in the `addPlotBand` option.
+           *
+           * @return {void}
+           */
+          removePlotBand: function (id) {
+            this.removePlotBandOrLine(id);
+          },
+          /**
+           * Remove a plot line by its id.
+           *
+           * @sample highcharts/xaxis/plotlines-id/
+           *         Remove plot line by id
+           * @sample highcharts/members/axis-addplotline/
+           *         Toggle the plot line from a button
+           *
+           * @function Highcharts.Axis#removePlotLine
+           *
+           * @param {string} id
+           *        The plot line's `id` as given in the original configuration
+           *        object or in the `addPlotLine` option.
+           */
+          removePlotLine: function (id) {
+            this.removePlotBandOrLine(id);
+          },
+        }
+      );
+      H.PlotLineOrBand = PlotLineOrBand;
+
+      return H.PlotLineOrBand;
+    }
+  );
+  _registerModule(
+    _modules,
+    "Core/Tooltip.js",
+    [_modules["Core/Globals.js"], _modules["Core/Utilities.js"]],
+    function (H, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      var doc = H.doc;
+      var clamp = U.clamp,
+        css = U.css,
+        defined = U.defined,
+        discardElement = U.discardElement,
+        extend = U.extend,
+        fireEvent = U.fireEvent,
+        format = U.format,
+        isNumber = U.isNumber,
+        isString = U.isString,
+        merge = U.merge,
+        pick = U.pick,
+        splat = U.splat,
+        syncTimeout = U.syncTimeout,
+        timeUnits = U.timeUnits;
+      /**
+       * Callback function to format the text of the tooltip from scratch.
+       *
+       * In case of single or shared tooltips, a string should be be returned. In case
+       * of splitted tooltips, it should return an array where the first item is the
+       * header, and subsequent items are mapped to the points. Return `false` to
+       * disable tooltip for a specific point on series.
+       *
+       * @callback Highcharts.TooltipFormatterCallbackFunction
+       *
+       * @param {Highcharts.TooltipFormatterContextObject} this
+       *        Context to format
+       *
+       * @param {Highcharts.Tooltip} tooltip
+       *        The tooltip instance
+       *
+       * @return {false|string|Array<(string|null|undefined)>|null|undefined}
+       *         Formatted text or false
+       */
+      /**
+       * @interface Highcharts.TooltipFormatterContextObject
+       */ /**
+       * @name Highcharts.TooltipFormatterContextObject#color
+       * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+       */ /**
+       * @name Highcharts.TooltipFormatterContextObject#colorIndex
+       * @type {number|undefined}
+       */ /**
+       * @name Highcharts.TooltipFormatterContextObject#key
+       * @type {number}
+       */ /**
+       * @name Highcharts.TooltipFormatterContextObject#percentage
+       * @type {number|undefined}
+       */ /**
+       * @name Highcharts.TooltipFormatterContextObject#point
+       * @type {Highcharts.Point}
+       */ /**
+       * @name Highcharts.TooltipFormatterContextObject#points
+       * @type {Array<Highcharts.TooltipFormatterContextObject>|undefined}
+       */ /**
+       * @name Highcharts.TooltipFormatterContextObject#series
+       * @type {Highcharts.Series}
+       */ /**
+       * @name Highcharts.TooltipFormatterContextObject#total
+       * @type {number|undefined}
+       */ /**
+       * @name Highcharts.TooltipFormatterContextObject#x
+       * @type {number}
+       */ /**
+       * @name Highcharts.TooltipFormatterContextObject#y
+       * @type {number}
+       */
+      /**
+       * A callback function to place the tooltip in a specific position.
+       *
+       * @callback Highcharts.TooltipPositionerCallbackFunction
+       *
+       * @param {Highcharts.Tooltip} this
+       * Tooltip context of the callback.
+       *
+       * @param {number} labelWidth
+       * Width of the tooltip.
+       *
+       * @param {number} labelHeight
+       * Height of the tooltip.
+       *
+       * @param {Highcharts.TooltipPositionerPointObject} point
+       * Point information for positioning a tooltip.
+       *
+       * @return {Highcharts.PositionObject}
+       * New position for the tooltip.
+       */
+      /**
+       * Point information for positioning a tooltip.
+       *
+       * @interface Highcharts.TooltipPositionerPointObject
+       * @extends Highcharts.Point
+       */ /**
+       * If `tooltip.split` option is enabled and positioner is called for each of the
+       * boxes separately, this property indicates the call on the xAxis header, which
+       * is not a point itself.
+       * @name Highcharts.TooltipPositionerPointObject#isHeader
+       * @type {boolean}
+       */ /**
+       * The reference point relative to the plot area. Add chart.plotLeft to get the
+       * full coordinates.
+       * @name Highcharts.TooltipPositionerPointObject#plotX
+       * @type {number}
+       */ /**
+       * The reference point relative to the plot area. Add chart.plotTop to get the
+       * full coordinates.
+       * @name Highcharts.TooltipPositionerPointObject#plotY
+       * @type {number}
+       */
+      /**
+       * @typedef {"callout"|"circle"|"square"} Highcharts.TooltipShapeValue
+       */
+      (""); // separates doclets above from variables below
+      /* eslint-disable no-invalid-this, valid-jsdoc */
+      /**
+       * Tooltip of a chart.
+       *
+       * @class
+       * @name Highcharts.Tooltip
+       *
+       * @param {Highcharts.Chart} chart
+       * The chart instance.
+       *
+       * @param {Highcharts.TooltipOptions} options
+       * Tooltip options.
+       */
+      var Tooltip = /** @class */ (function () {
+        /* *
+         *
+         *  Constructors
+         *
+         * */
+        function Tooltip(chart, options) {
+          this.container = void 0;
+          this.crosshairs = [];
+          this.distance = 0;
+          this.isHidden = true;
+          this.isSticky = false;
+          this.now = {};
+          this.options = {};
+          this.outside = false;
+          this.chart = chart;
+          this.init(chart, options);
+        }
+        /* *
+         *
+         *  Functions
+         *
+         * */
+        /**
+         * In styled mode, apply the default filter for the tooltip drop-shadow. It
+         * needs to have an id specific to the chart, otherwise there will be issues
+         * when one tooltip adopts the filter of a different chart, specifically one
+         * where the container is hidden.
+         *
+         * @private
+         * @function Highcharts.Tooltip#applyFilter
+         */
+        Tooltip.prototype.applyFilter = function () {
+          var chart = this.chart;
+          chart.renderer.definition({
+            tagName: "filter",
+            id: "drop-shadow-" + chart.index,
+            opacity: 0.5,
+            children: [
+              {
+                tagName: "feGaussianBlur",
+                in: "SourceAlpha",
+                stdDeviation: 1,
+              },
+              {
+                tagName: "feOffset",
+                dx: 1,
+                dy: 1,
+              },
+              {
+                tagName: "feComponentTransfer",
+                children: [
+                  {
+                    tagName: "feFuncA",
+                    type: "linear",
+                    slope: 0.3,
+                  },
+                ],
+              },
+              {
+                tagName: "feMerge",
+                children: [
+                  {
+                    tagName: "feMergeNode",
+                  },
+                  {
+                    tagName: "feMergeNode",
+                    in: "SourceGraphic",
+                  },
+                ],
+              },
+            ],
+          });
+          chart.renderer.definition({
+            tagName: "style",
+            textContent:
+              ".highcharts-tooltip-" +
+              chart.index +
+              "{" +
+              "filter:url(#drop-shadow-" +
+              chart.index +
+              ")" +
+              "}",
+          });
+        };
+        /**
+         * Build the body (lines) of the tooltip by iterating over the items and
+         * returning one entry for each item, abstracting this functionality allows
+         * to easily overwrite and extend it.
+         *
+         * @private
+         * @function Highcharts.Tooltip#bodyFormatter
+         * @param {Array<(Highcharts.Point|Highcharts.Series)>} items
+         * @return {Array<string>}
+         */
+        Tooltip.prototype.bodyFormatter = function (items) {
+          return items.map(function (item) {
+            var tooltipOptions = item.series.tooltipOptions;
+            return (
+              tooltipOptions[
+                (item.point.formatPrefix || "point") + "Formatter"
+              ] || item.point.tooltipFormatter
+            ).call(
+              item.point,
+              tooltipOptions[(item.point.formatPrefix || "point") + "Format"] ||
+                ""
+            );
+          });
+        };
+        /**
+         * Destroy the single tooltips in a split tooltip.
+         * If the tooltip is active then it is not destroyed, unless forced to.
+         *
+         * @private
+         * @function Highcharts.Tooltip#cleanSplit
+         *
+         * @param {boolean} [force]
+         *        Force destroy all tooltips.
+         */
+        Tooltip.prototype.cleanSplit = function (force) {
+          this.chart.series.forEach(function (series) {
+            var tt = series && series.tt;
+            if (tt) {
+              if (!tt.isActive || force) {
+                series.tt = tt.destroy();
+              } else {
+                tt.isActive = false;
+              }
+            }
+          });
+        };
+        /**
+         * In case no user defined formatter is given, this will be used. Note that
+         * the context here is an object holding point, series, x, y etc.
+         *
+         * @function Highcharts.Tooltip#defaultFormatter
+         *
+         * @param {Highcharts.Tooltip} tooltip
+         *
+         * @return {Array<string>}
+         */
+        Tooltip.prototype.defaultFormatter = function (tooltip) {
+          var items = this.points || splat(this),
+            s;
+          // Build the header
+          s = [tooltip.tooltipFooterHeaderFormatter(items[0])];
+          // build the values
+          s = s.concat(tooltip.bodyFormatter(items));
+          // footer
+          s.push(tooltip.tooltipFooterHeaderFormatter(items[0], true));
+          return s;
+        };
+        /**
+         * Removes and destroys the tooltip and its elements.
+         *
+         * @function Highcharts.Tooltip#destroy
+         */
+        Tooltip.prototype.destroy = function () {
+          // Destroy and clear local variables
+          if (this.label) {
+            this.label = this.label.destroy();
+          }
+          if (this.split && this.tt) {
+            this.cleanSplit(this.chart, true);
+            this.tt = this.tt.destroy();
+          }
+          if (this.renderer) {
+            this.renderer = this.renderer.destroy();
+            discardElement(this.container);
+          }
+          U.clearTimeout(this.hideTimer);
+          U.clearTimeout(this.tooltipTimeout);
+        };
+        /**
+         * Extendable method to get the anchor position of the tooltip
+         * from a point or set of points
+         *
+         * @private
+         * @function Highcharts.Tooltip#getAnchor
+         *
+         * @param {Highcharts.Point|Array<Highcharts.Point>} points
+         *
+         * @param {Highcharts.PointerEventObject} [mouseEvent]
+         *
+         * @return {Array<number>}
+         */
+        Tooltip.prototype.getAnchor = function (points, mouseEvent) {
+          var ret,
+            chart = this.chart,
+            pointer = chart.pointer,
+            inverted = chart.inverted,
+            plotTop = chart.plotTop,
+            plotLeft = chart.plotLeft,
+            plotX = 0,
+            plotY = 0,
+            yAxis,
+            xAxis;
+          points = splat(points);
+          // When tooltip follows mouse, relate the position to the mouse
+          if (this.followPointer && mouseEvent) {
+            if (typeof mouseEvent.chartX === "undefined") {
+              mouseEvent = pointer.normalize(mouseEvent);
+            }
+            ret = [mouseEvent.chartX - plotLeft, mouseEvent.chartY - plotTop];
+            // Some series types use a specificly calculated tooltip position for
+            // each point
+          } else if (points[0].tooltipPos) {
+            ret = points[0].tooltipPos;
+            // When shared, use the average position
+          } else {
+            points.forEach(function (point) {
+              yAxis = point.series.yAxis;
+              xAxis = point.series.xAxis;
+              plotX +=
+                point.plotX + (!inverted && xAxis ? xAxis.left - plotLeft : 0);
+              plotY +=
+                (point.plotLow
+                  ? (point.plotLow + point.plotHigh) / 2
+                  : point.plotY) +
+                (!inverted && yAxis ? yAxis.top - plotTop : 0); // #1151
+            });
+            plotX /= points.length;
+            plotY /= points.length;
+            ret = [
+              inverted ? chart.plotWidth - plotY : plotX,
+              this.shared && !inverted && points.length > 1 && mouseEvent
+                ? // place shared tooltip next to the mouse (#424)
+                  mouseEvent.chartY - plotTop
+                : inverted
+                ? chart.plotHeight - plotX
+                : plotY,
+            ];
+          }
+          return ret.map(Math.round);
+        };
+        /**
+         * Get the optimal date format for a point, based on a range.
+         *
+         * @private
+         * @function Highcharts.Tooltip#getDateFormat
+         *
+         * @param {number} range
+         *        The time range
+         *
+         * @param {number} date
+         *        The date of the point in question
+         *
+         * @param {number} startOfWeek
+         *        An integer representing the first day of the week, where 0 is
+         *        Sunday.
+         *
+         * @param {Highcharts.Dictionary<string>} dateTimeLabelFormats
+         *        A map of time units to formats.
+         *
+         * @return {string}
+         *         The optimal date format for a point.
+         */
+        Tooltip.prototype.getDateFormat = function (
+          range,
+          date,
+          startOfWeek,
+          dateTimeLabelFormats
+        ) {
+          var time = this.chart.time,
+            dateStr = time.dateFormat("%m-%d %H:%M:%S.%L", date),
+            format,
+            n,
+            blank = "01-01 00:00:00.000",
+            strpos = {
+              millisecond: 15,
+              second: 12,
+              minute: 9,
+              hour: 6,
+              day: 3,
             },
-            /**
-             * Clear DOM objects and free up memory.
-             *
-             * @private
-             * @function Highcharts.Series#destroy
-             * @param {boolean} [keepEventsForUpdate]
-             * @return {void}
-             * @fires Highcharts.Series#event:destroy
-             */
-            destroy: function (keepEventsForUpdate) {
-                var series = this,
-                    chart = series.chart,
-                    issue134 = /AppleWebKit\/533/.test(win.navigator.userAgent),
-                    destroy,
-                    i,
-                    data = series.data || [],
-                    point,
-                    axis;
-                // add event hook
-                fireEvent(series, 'destroy');
-                // remove events
-                this.removeEvents(keepEventsForUpdate);
-                // erase from axes
-                (series.axisTypes || []).forEach(function (AXIS) {
-                    axis = series[AXIS];
-                    if (axis && axis.series) {
-                        erase(axis.series, series);
-                        axis.isDirty = axis.forceRedraw = true;
-                    }
-                });
-                // remove legend items
-                if (series.legendItem) {
-                    series.chart.legend.destroyItem(series);
-                }
-                // destroy all points with their elements
-                i = data.length;
-                while (i--) {
-                    point = data[i];
-                    if (point && point.destroy) {
-                        point.destroy();
-                    }
-                }
-                series.points = null;
-                // Clear the animation timeout if we are destroying the series
-                // during initial animation
-                U.clearTimeout(series.animationTimeout);
-                // Destroy all SVGElements associated to the series
-                objectEach(series, function (val, prop) {
-                    // Survive provides a hook for not destroying
-                    if (val instanceof SVGElement && !val.survive) {
-                        // issue 134 workaround
-                        destroy = issue134 && prop === 'group' ?
-                            'hide' :
-                            'destroy';
-                        val[destroy]();
-                    }
-                });
-                // remove from hoverSeries
-                if (chart.hoverSeries === series) {
-                    chart.hoverSeries = null;
-                }
-                erase(chart.series, series);
-                chart.orderSeries();
-                // clear all members
-                objectEach(series, function (val, prop) {
-                    if (!keepEventsForUpdate || prop !== 'hcEvents') {
-                        delete series[prop];
-                    }
-                });
+            lastN = "millisecond"; // for sub-millisecond data, #4223
+          for (n in timeUnits) {
+            // eslint-disable-line guard-for-in
+            // If the range is exactly one week and we're looking at a
+            // Sunday/Monday, go for the week format
+            if (
+              range === timeUnits.week &&
+              +time.dateFormat("%w", date) === startOfWeek &&
+              dateStr.substr(6) === blank.substr(6)
+            ) {
+              n = "week";
+              break;
+            }
+            // The first format that is too great for the range
+            if (timeUnits[n] > range) {
+              n = lastN;
+              break;
+            }
+            // If the point is placed every day at 23:59, we need to show
+            // the minutes as well. #2637.
+            if (
+              strpos[n] &&
+              dateStr.substr(strpos[n]) !== blank.substr(strpos[n])
+            ) {
+              break;
+            }
+            // Weeks are outside the hierarchy, only apply them on
+            // Mondays/Sundays like in the first condition
+            if (n !== "week") {
+              lastN = n;
+            }
+          }
+          if (n) {
+            format = time.resolveDTLFormat(dateTimeLabelFormats[n]).main;
+          }
+          return format;
+        };
+        /**
+         * Creates the Tooltip label element if it does not exist, then returns it.
+         *
+         * @function Highcharts.Tooltip#getLabel
+         * @return {Highcharts.SVGElement}
+         */
+        Tooltip.prototype.getLabel = function () {
+          var _a, _b;
+          var tooltip = this,
+            renderer = this.chart.renderer,
+            styledMode = this.chart.styledMode,
+            options = this.options,
+            className =
+              "tooltip" +
+              (defined(options.className) ? " " + options.className : ""),
+            pointerEvents =
+              ((_a = options.style) === null || _a === void 0
+                ? void 0
+                : _a.pointerEvents) ||
+              (!this.followPointer && options.stickOnContact ? "auto" : "none"),
+            container,
+            set,
+            onMouseEnter = function () {
+              tooltip.inContact = true;
             },
-            /**
-             * Get the graph path.
-             *
-             * @private
-             * @function Highcharts.Series#getGraphPath
-             * @param {Array<Highcharts.Point>} points
-             * @param {boolean} [nullsAsZeroes]
-             * @param {boolean} [connectCliffs]
-             * @return {Highcharts.SVGPathArray}
-             */
-            getGraphPath: function (points, nullsAsZeroes, connectCliffs) {
-                var series = this,
-                    options = series.options,
-                    step = options.step,
-                    reversed,
-                    graphPath = [],
-                    xMap = [],
-                    gap;
-                points = points || series.points;
-                // Bottom of a stack is reversed
-                reversed = points.reversed;
-                if (reversed) {
-                    points.reverse();
-                }
-                // Reverse the steps (#5004)
-                step = {
-                    right: 1,
-                    center: 2
-                }[step] || (step && 3);
-                if (step && reversed) {
-                    step = 4 - step;
-                }
-                // Remove invalid points, especially in spline (#5015)
-                points = this.getValidPoints(points, false, !(options.connectNulls && !nullsAsZeroes && !connectCliffs));
-                // Build the line
-                points.forEach(function (point, i) {
-                    var plotX = point.plotX,
-                        plotY = point.plotY,
-                        lastPoint = points[i - 1], 
-                        // the path to this point from the previous
-                        pathToPoint;
-                    if ((point.leftCliff || (lastPoint && lastPoint.rightCliff)) &&
-                        !connectCliffs) {
-                        gap = true; // ... and continue
-                    }
-                    // Line series, nullsAsZeroes is not handled
-                    if (point.isNull && !defined(nullsAsZeroes) && i > 0) {
-                        gap = !options.connectNulls;
-                        // Area series, nullsAsZeroes is set
-                    }
-                    else if (point.isNull && !nullsAsZeroes) {
-                        gap = true;
-                    }
-                    else {
-                        if (i === 0 || gap) {
-                            pathToPoint = [[
-                                    'M',
-                                    point.plotX,
-                                    point.plotY
-                                ]];
-                            // Generate the spline as defined in the SplineSeries object
-                        }
-                        else if (series.getPointSpline) {
-                            pathToPoint = [series.getPointSpline(points, point, i)];
-                        }
-                        else if (step) {
-                            if (step === 1) { // right
-                                pathToPoint = [[
-                                        'L',
-                                        lastPoint.plotX,
-                                        plotY
-                                    ]];
-                            }
-                            else if (step === 2) { // center
-                                pathToPoint = [[
-                                        'L',
-                                        (lastPoint.plotX + plotX) / 2,
-                                        lastPoint.plotY
-                                    ], [
-                                        'L',
-                                        (lastPoint.plotX + plotX) / 2,
-                                        plotY
-                                    ]];
-                            }
-                            else {
-                                pathToPoint = [[
-                                        'L',
-                                        plotX,
-                                        lastPoint.plotY
-                                    ]];
-                            }
-                            pathToPoint.push([
-                                'L',
-                                plotX,
-                                plotY
-                            ]);
-                        }
-                        else {
-                            // normal line to next point
-                            pathToPoint = [[
-                                    'L',
-                                    plotX,
-                                    plotY
-                                ]];
-                        }
-                        // Prepare for animation. When step is enabled, there are
-                        // two path nodes for each x value.
-                        xMap.push(point.x);
-                        if (step) {
-                            xMap.push(point.x);
-                            if (step === 2) { // step = center (#8073)
-                                xMap.push(point.x);
-                            }
-                        }
-                        graphPath.push.apply(graphPath, pathToPoint);
-                        gap = false;
-                    }
+            onMouseLeave = function () {
+              var series = tooltip.chart.hoverSeries;
+              tooltip.inContact = false;
+              if (series && series.onMouseOut) {
+                series.onMouseOut();
+              }
+            };
+          if (!this.label) {
+            if (this.outside) {
+              /**
+               * Reference to the tooltip's container, when
+               * [Highcharts.Tooltip#outside] is set to true, otherwise
+               * it's undefined.
+               *
+               * @name Highcharts.Tooltip#container
+               * @type {Highcharts.HTMLDOMElement|undefined}
+               */
+              this.container = container = H.doc.createElement("div");
+              container.className = "highcharts-tooltip-container";
+              css(container, {
+                position: "absolute",
+                top: "1px",
+                pointerEvents: pointerEvents,
+                zIndex: 3,
+              });
+              H.doc.body.appendChild(container);
+              /**
+               * Reference to the tooltip's renderer, when
+               * [Highcharts.Tooltip#outside] is set to true, otherwise
+               * it's undefined.
+               *
+               * @name Highcharts.Tooltip#renderer
+               * @type {Highcharts.SVGRenderer|undefined}
+               */
+              this.renderer = renderer = new H.Renderer(
+                container,
+                0,
+                0,
+                (_b = this.chart.options.chart) === null || _b === void 0
+                  ? void 0
+                  : _b.style,
+                void 0,
+                void 0,
+                renderer.styledMode
+              );
+            }
+            // Create the label
+            if (this.split) {
+              this.label = renderer.g(className);
+            } else {
+              this.label = renderer
+                .label(
+                  "",
+                  0,
+                  0,
+                  options.shape || "callout",
+                  null,
+                  null,
+                  options.useHTML,
+                  null,
+                  className
+                )
+                .attr({
+                  padding: options.padding,
+                  r: options.borderRadius,
                 });
-                graphPath.xMap = xMap;
-                series.graphPath = graphPath;
-                return graphPath;
+              if (!styledMode) {
+                this.label
+                  .attr({
+                    fill: options.backgroundColor,
+                    "stroke-width": options.borderWidth,
+                  })
+                  // #2301, #2657
+                  .css(options.style)
+                  .css({ pointerEvents: pointerEvents })
+                  .shadow(options.shadow);
+              }
+            }
+            if (styledMode) {
+              // Apply the drop-shadow filter
+              this.applyFilter();
+              this.label.addClass("highcharts-tooltip-" + this.chart.index);
+            }
+            // Split tooltip use updateTooltipContainer to position the tooltip
+            // container.
+            if (tooltip.outside && !tooltip.split) {
+              var label_1 = this.label;
+              var xSetter_1 = label_1.xSetter,
+                ySetter_1 = label_1.ySetter;
+              label_1.xSetter = function (value) {
+                xSetter_1.call(label_1, tooltip.distance);
+                container.style.left = value + "px";
+              };
+              label_1.ySetter = function (value) {
+                ySetter_1.call(label_1, tooltip.distance);
+                container.style.top = value + "px";
+              };
+            }
+            this.label
+              .on("mouseenter", onMouseEnter)
+              .on("mouseleave", onMouseLeave)
+              .attr({ zIndex: 8 })
+              .add();
+          }
+          return this.label;
+        };
+        /**
+         * Place the tooltip in a chart without spilling over
+         * and not covering the point it self.
+         *
+         * @private
+         * @function Highcharts.Tooltip#getPosition
+         *
+         * @param {number} boxWidth
+         *
+         * @param {number} boxHeight
+         *
+         * @param {Highcharts.Point} point
+         *
+         * @return {Highcharts.PositionObject}
+         */
+        Tooltip.prototype.getPosition = function (boxWidth, boxHeight, point) {
+          var chart = this.chart,
+            distance = this.distance,
+            ret = {},
+            // Don't use h if chart isn't inverted (#7242) ???
+            h = (chart.inverted && point.h) || 0, // #4117 ???
+            swapped,
+            outside = this.outside,
+            outerWidth = outside
+              ? // substract distance to prevent scrollbars
+                doc.documentElement.clientWidth - 2 * distance
+              : chart.chartWidth,
+            outerHeight = outside
+              ? Math.max(
+                  doc.body.scrollHeight,
+                  doc.documentElement.scrollHeight,
+                  doc.body.offsetHeight,
+                  doc.documentElement.offsetHeight,
+                  doc.documentElement.clientHeight
+                )
+              : chart.chartHeight,
+            chartPosition = chart.pointer.getChartPosition(),
+            containerScaling = chart.containerScaling,
+            scaleX = function (val) {
+              return (
+                // eslint-disable-line no-confusing-arrow
+                containerScaling ? val * containerScaling.scaleX : val
+              );
             },
-            /**
-             * Draw the graph. Called internally when rendering line-like series
-             * types. The first time it generates the `series.graph` item and
-             * optionally other series-wide items like `series.area` for area
-             * charts. On subsequent calls these items are updated with new
-             * positions and attributes.
-             *
-             * @function Highcharts.Series#drawGraph
-             */
-            drawGraph: function () {
-                var series = this,
-                    options = this.options,
-                    graphPath = (this.gappedPath || this.getGraphPath).call(this),
-                    styledMode = this.chart.styledMode,
-                    props = [[
-                            'graph',
-                            'highcharts-graph'
-                        ]];
-                // Presentational properties
-                if (!styledMode) {
-                    props[0].push((options.lineColor ||
-                        this.color ||
-                        '#cccccc' // when colorByPoint = true
-                    ), options.dashStyle);
-                }
-                props = series.getZonesGraphs(props);
-                // Draw the graph
-                props.forEach(function (prop, i) {
-                    var graphKey = prop[0],
-                        graph = series[graphKey],
-                        verb = graph ? 'animate' : 'attr',
-                        attribs;
-                    if (graph) {
-                        graph.endX = series.preventGraphAnimation ?
-                            null :
-                            graphPath.xMap;
-                        graph.animate({ d: graphPath });
-                    }
-                    else if (graphPath.length) { // #1487
-                        /**
-                         * SVG element of area-based charts. Can be used for styling
-                         * purposes. If zones are configured, this element will be
-                         * hidden and replaced by multiple zone areas, accessible
-                         * via `series['zone-area-x']` (where x is a number,
-                         * starting with 0).
-                         *
-                         * @name Highcharts.Series#area
-                         * @type {Highcharts.SVGElement|undefined}
-                         */
-                        /**
-                         * SVG element of line-based charts. Can be used for styling
-                         * purposes. If zones are configured, this element will be
-                         * hidden and replaced by multiple zone lines, accessible
-                         * via `series['zone-graph-x']` (where x is a number,
-                         * starting with 0).
-                         *
-                         * @name Highcharts.Series#graph
-                         * @type {Highcharts.SVGElement|undefined}
-                         */
-                        series[graphKey] = graph = series.chart.renderer
-                            .path(graphPath)
-                            .addClass(prop[1])
-                            .attr({ zIndex: 1 }) // #1069
-                            .add(series.group);
-                    }
-                    if (graph && !styledMode) {
-                        attribs = {
-                            'stroke': prop[2],
-                            'stroke-width': options.lineWidth,
-                            // Polygon series use filled graph
-                            'fill': (series.fillGraph && series.color) || 'none'
-                        };
-                        if (prop[3]) {
-                            attribs.dashstyle = prop[3];
-                        }
-                        else if (options.linecap !== 'square') {
-                            attribs['stroke-linecap'] =
-                                attribs['stroke-linejoin'] = 'round';
-                        }
-                        graph[verb](attribs)
-                            // Add shadow to normal series (0) or to first
-                            // zone (1) #3932
-                            .shadow((i < 2) && options.shadow);
-                    }
-                    // Helpers for animation
-                    if (graph) {
-                        graph.startX = graphPath.xMap;
-                        graph.isArea = graphPath.isArea; // For arearange animation
-                    }
-                });
+            scaleY = function (val) {
+              return (
+                // eslint-disable-line no-confusing-arrow
+                containerScaling ? val * containerScaling.scaleY : val
+              );
             },
-            /**
-             * Get zones properties for building graphs. Extendable by series with
-             * multiple lines within one series.
-             *
-             * @private
-             * @function Highcharts.Series#getZonesGraphs
-             *
-             * @param {Array<Array<string>>} props
-             *
-             * @return {Array<Array<string>>}
-             */
-            getZonesGraphs: function (props) {
-                // Add the zone properties if any
-                this.zones.forEach(function (zone, i) {
-                    var propset = [
-                            'zone-graph-' + i,
-                            'highcharts-graph highcharts-zone-graph-' + i + ' ' +
-                                (zone.className || '')
-                        ];
-                    if (!this.chart.styledMode) {
-                        propset.push((zone.color || this.color), (zone.dashStyle || this.options.dashStyle));
-                    }
-                    props.push(propset);
-                }, this);
-                return props;
+            // Build parameter arrays for firstDimension()/secondDimension()
+            buildDimensionArray = function (dim) {
+              var isX = dim === "x";
+              return [
+                dim,
+                isX ? outerWidth : outerHeight,
+                isX ? boxWidth : boxHeight,
+              ].concat(
+                outside
+                  ? [
+                      // If we are using tooltip.outside, we need to scale the
+                      // position to match scaling of the container in case there
+                      // is a transform/zoom on the container. #11329
+                      isX ? scaleX(boxWidth) : scaleY(boxHeight),
+                      isX
+                        ? chartPosition.left -
+                          distance +
+                          scaleX(point.plotX + chart.plotLeft)
+                        : chartPosition.top -
+                          distance +
+                          scaleY(point.plotY + chart.plotTop),
+                      0,
+                      isX ? outerWidth : outerHeight,
+                    ]
+                  : [
+                      // Not outside, no scaling is needed
+                      isX ? boxWidth : boxHeight,
+                      isX
+                        ? point.plotX + chart.plotLeft
+                        : point.plotY + chart.plotTop,
+                      isX ? chart.plotLeft : chart.plotTop,
+                      isX
+                        ? chart.plotLeft + chart.plotWidth
+                        : chart.plotTop + chart.plotHeight,
+                    ]
+              );
             },
-            /**
-             * Clip the graphs into zones for colors and styling.
-             *
-             * @private
-             * @function Highcharts.Series#applyZones
-             * @return {void}
-             */
-            applyZones: function () {
-                var series = this,
-                    chart = this.chart,
-                    renderer = chart.renderer,
-                    zones = this.zones,
-                    translatedFrom,
-                    translatedTo,
-                    clips = (this.clips || []),
-                    clipAttr,
-                    graph = this.graph,
-                    area = this.area,
-                    chartSizeMax = Math.max(chart.chartWidth,
-                    chart.chartHeight),
-                    axis = this[(this.zoneAxis || 'y') + 'Axis'],
-                    extremes,
-                    reversed,
-                    inverted = chart.inverted,
-                    horiz,
-                    pxRange,
-                    pxPosMin,
-                    pxPosMax,
-                    ignoreZones = false,
-                    zoneArea,
-                    zoneGraph;
-                if (zones.length &&
-                    (graph || area) &&
-                    axis &&
-                    typeof axis.min !== 'undefined') {
-                    reversed = axis.reversed;
-                    horiz = axis.horiz;
-                    // The use of the Color Threshold assumes there are no gaps
-                    // so it is safe to hide the original graph and area
-                    // unless it is not waterfall series, then use showLine property
-                    // to set lines between columns to be visible (#7862)
-                    if (graph && !this.showLine) {
-                        graph.hide();
-                    }
-                    if (area) {
-                        area.hide();
-                    }
-                    // Create the clips
-                    extremes = axis.getExtremes();
-                    zones.forEach(function (threshold, i) {
-                        translatedFrom = reversed ?
-                            (horiz ? chart.plotWidth : 0) :
-                            (horiz ? 0 : (axis.toPixels(extremes.min) || 0));
-                        translatedFrom = clamp(pick(translatedTo, translatedFrom), 0, chartSizeMax);
-                        translatedTo = clamp(Math.round(axis.toPixels(pick(threshold.value, extremes.max), true) || 0), 0, chartSizeMax);
-                        if (ignoreZones) {
-                            translatedFrom = translatedTo =
-                                axis.toPixels(extremes.max);
-                        }
-                        pxRange = Math.abs(translatedFrom - translatedTo);
-                        pxPosMin = Math.min(translatedFrom, translatedTo);
-                        pxPosMax = Math.max(translatedFrom, translatedTo);
-                        if (axis.isXAxis) {
-                            clipAttr = {
-                                x: inverted ? pxPosMax : pxPosMin,
-                                y: 0,
-                                width: pxRange,
-                                height: chartSizeMax
-                            };
-                            if (!horiz) {
-                                clipAttr.x = chart.plotHeight - clipAttr.x;
-                            }
-                        }
-                        else {
-                            clipAttr = {
-                                x: 0,
-                                y: inverted ? pxPosMax : pxPosMin,
-                                width: chartSizeMax,
-                                height: pxRange
-                            };
-                            if (horiz) {
-                                clipAttr.y = chart.plotWidth - clipAttr.y;
-                            }
-                        }
-                        // VML SUPPPORT
-                        if (inverted && renderer.isVML) {
-                            if (axis.isXAxis) {
-                                clipAttr = {
-                                    x: 0,
-                                    y: reversed ? pxPosMin : pxPosMax,
-                                    height: clipAttr.width,
-                                    width: chart.chartWidth
-                                };
-                            }
-                            else {
-                                clipAttr = {
-                                    x: (clipAttr.y -
-                                        chart.plotLeft -
-                                        chart.spacingBox.x),
-                                    y: 0,
-                                    width: clipAttr.height,
-                                    height: chart.chartHeight
-                                };
-                            }
-                        }
-                        // END OF VML SUPPORT
-                        if (clips[i]) {
-                            clips[i].animate(clipAttr);
-                        }
-                        else {
-                            clips[i] = renderer.clipRect(clipAttr);
-                        }
-                        // when no data, graph zone is not applied and after setData
-                        // clip was ignored. As a result, it should be applied each
-                        // time.
-                        zoneArea = series['zone-area-' + i];
-                        zoneGraph = series['zone-graph-' + i];
-                        if (graph && zoneGraph) {
-                            zoneGraph.clip(clips[i]);
-                        }
-                        if (area && zoneArea) {
-                            zoneArea.clip(clips[i]);
-                        }
-                        // if this zone extends out of the axis, ignore the others
-                        ignoreZones = threshold.value > extremes.max;
-                        // Clear translatedTo for indicators
-                        if (series.resetZones && translatedTo === 0) {
-                            translatedTo = void 0;
-                        }
-                    });
-                    this.clips = clips;
-                }
-                else if (series.visible) {
-                    // If zones were removed, restore graph and area
-                    if (graph) {
-                        graph.show(true);
-                    }
-                    if (area) {
-                        area.show(true);
-                    }
-                }
+            first = buildDimensionArray("y"),
+            second = buildDimensionArray("x"),
+            // The far side is right or bottom
+            preferFarSide =
+              !this.followPointer &&
+              pick(point.ttBelow, !chart.inverted === !!point.negative), // #4984
+            /*
+             * Handle the preferred dimension. When the preferred dimension is
+             * tooltip on top or bottom of the point, it will look for space
+             * there.
+             *
+             * @private
+             */
+            firstDimension = function (
+              dim,
+              outerSize,
+              innerSize,
+              scaledInnerSize, // #11329
+              point,
+              min,
+              max
+            ) {
+              var scaledDist =
+                  dim === "y" ? scaleY(distance) : scaleX(distance),
+                scaleDiff = (innerSize - scaledInnerSize) / 2,
+                roomLeft = scaledInnerSize < point - distance,
+                roomRight = point + distance + scaledInnerSize < outerSize,
+                alignedLeft = point - scaledDist - innerSize + scaleDiff,
+                alignedRight = point + scaledDist - scaleDiff;
+              if (preferFarSide && roomRight) {
+                ret[dim] = alignedRight;
+              } else if (!preferFarSide && roomLeft) {
+                ret[dim] = alignedLeft;
+              } else if (roomLeft) {
+                ret[dim] = Math.min(
+                  max - scaledInnerSize,
+                  alignedLeft - h < 0 ? alignedLeft : alignedLeft - h
+                );
+              } else if (roomRight) {
+                ret[dim] = Math.max(
+                  min,
+                  alignedRight + h + innerSize > outerSize
+                    ? alignedRight
+                    : alignedRight + h
+                );
+              } else {
+                return false;
+              }
             },
-            /**
-             * Initialize and perform group inversion on series.group and
-             * series.markerGroup.
-             *
-             * @private
-             * @function Highcharts.Series#invertGroups
-             * @param {boolean} [inverted]
-             * @return {void}
+            /*
+             * Handle the secondary dimension. If the preferred dimension is
+             * tooltip on top or bottom of the point, the second dimension is to
+             * align the tooltip above the point, trying to align center but
+             * allowing left or right align within the chart box.
+             *
+             * @private
+             */
+            secondDimension = function (
+              dim,
+              outerSize,
+              innerSize,
+              scaledInnerSize, // #11329
+              point
+            ) {
+              var retVal;
+              // Too close to the edge, return false and swap dimensions
+              if (point < distance || point > outerSize - distance) {
+                retVal = false;
+                // Align left/top
+              } else if (point < innerSize / 2) {
+                ret[dim] = 1;
+                // Align right/bottom
+              } else if (point > outerSize - scaledInnerSize / 2) {
+                ret[dim] = outerSize - scaledInnerSize - 2;
+                // Align center
+              } else {
+                ret[dim] = point - innerSize / 2;
+              }
+              return retVal;
+            },
+            /*
+             * Swap the dimensions
              */
-            invertGroups: function (inverted) {
-                var series = this,
-                    chart = series.chart;
-                /**
-                 * @private
-                 */
-                function setInvert() {
-                    ['group', 'markerGroup'].forEach(function (groupName) {
-                        if (series[groupName]) {
-                            // VML/HTML needs explicit attributes for flipping
-                            if (chart.renderer.isVML) {
-                                series[groupName].attr({
-                                    width: series.yAxis.len,
-                                    height: series.xAxis.len
-                                });
-                            }
-                            series[groupName].width = series.yAxis.len;
-                            series[groupName].height = series.xAxis.len;
-                            // If inverted polar, don't invert series group
-                            series[groupName].invert(series.isRadialSeries ? false : inverted);
-                        }
-                    });
-                }
-                // Pie, go away (#1736)
-                if (!series.xAxis) {
-                    return;
+            swap = function (count) {
+              var temp = first;
+              first = second;
+              second = temp;
+              swapped = count;
+            },
+            run = function () {
+              if (firstDimension.apply(0, first) !== false) {
+                if (secondDimension.apply(0, second) === false && !swapped) {
+                  swap(true);
+                  run();
+                }
+              } else if (!swapped) {
+                swap(true);
+                run();
+              } else {
+                ret.x = ret.y = 0;
+              }
+            };
+          // Under these conditions, prefer the tooltip on the side of the point
+          if (chart.inverted || this.len > 1) {
+            swap();
+          }
+          run();
+          return ret;
+        };
+        /**
+         * Get the best X date format based on the closest point range on the axis.
+         *
+         * @private
+         * @function Highcharts.Tooltip#getXDateFormat
+         *
+         * @param {Highcharts.Point} point
+         *
+         * @param {Highcharts.TooltipOptions} options
+         *
+         * @param {Highcharts.Axis} xAxis
+         *
+         * @return {string}
+         */
+        Tooltip.prototype.getXDateFormat = function (point, options, xAxis) {
+          var xDateFormat,
+            dateTimeLabelFormats = options.dateTimeLabelFormats,
+            closestPointRange = xAxis && xAxis.closestPointRange;
+          if (closestPointRange) {
+            xDateFormat = this.getDateFormat(
+              closestPointRange,
+              point.x,
+              xAxis.options.startOfWeek,
+              dateTimeLabelFormats
+            );
+          } else {
+            xDateFormat = dateTimeLabelFormats.day;
+          }
+          return xDateFormat || dateTimeLabelFormats.year; // #2546, 2581
+        };
+        /**
+         * Hides the tooltip with a fade out animation.
+         *
+         * @function Highcharts.Tooltip#hide
+         *
+         * @param {number} [delay]
+         *        The fade out in milliseconds. If no value is provided the value
+         *        of the tooltip.hideDelay option is used. A value of 0 disables
+         *        the fade out animation.
+         */
+        Tooltip.prototype.hide = function (delay) {
+          var tooltip = this;
+          // disallow duplicate timers (#1728, #1766)
+          U.clearTimeout(this.hideTimer);
+          delay = pick(delay, this.options.hideDelay, 500);
+          if (!this.isHidden) {
+            this.hideTimer = syncTimeout(function () {
+              // If there is a delay, do fadeOut with the default duration. If
+              // the hideDelay is 0, we assume no animation is wanted, so we
+              // pass 0 duration. #12994.
+              tooltip.getLabel().fadeOut(delay ? void 0 : delay);
+              tooltip.isHidden = true;
+            }, delay);
+          }
+        };
+        /**
+         * @private
+         * @function Highcharts.Tooltip#init
+         *
+         * @param {Highcharts.Chart} chart
+         *        The chart instance.
+         *
+         * @param {Highcharts.TooltipOptions} options
+         *        Tooltip options.
+         */
+        Tooltip.prototype.init = function (chart, options) {
+          /**
+           * Chart of the tooltip.
+           *
+           * @readonly
+           * @name Highcharts.Tooltip#chart
+           * @type {Highcharts.Chart}
+           */
+          this.chart = chart;
+          /**
+           * Used tooltip options.
+           *
+           * @readonly
+           * @name Highcharts.Tooltip#options
+           * @type {Highcharts.TooltipOptions}
+           */
+          this.options = options;
+          /**
+           * List of crosshairs.
+           *
+           * @private
+           * @readonly
+           * @name Highcharts.Tooltip#crosshairs
+           * @type {Array<null>}
+           */
+          this.crosshairs = [];
+          /**
+           * Current values of x and y when animating.
+           *
+           * @private
+           * @readonly
+           * @name Highcharts.Tooltip#now
+           * @type {Highcharts.PositionObject}
+           */
+          this.now = { x: 0, y: 0 };
+          /**
+           * Tooltips are initially hidden.
+           *
+           * @private
+           * @readonly
+           * @name Highcharts.Tooltip#isHidden
+           * @type {boolean}
+           */
+          this.isHidden = true;
+          /**
+           * True, if the tooltip is split into one label per series, with the
+           * header close to the axis.
+           *
+           * @readonly
+           * @name Highcharts.Tooltip#split
+           * @type {boolean|undefined}
+           */
+          this.split = options.split && !chart.inverted && !chart.polar;
+          /**
+           * When the tooltip is shared, the entire plot area will capture mouse
+           * movement or touch events.
+           *
+           * @readonly
+           * @name Highcharts.Tooltip#shared
+           * @type {boolean|undefined}
+           */
+          this.shared = options.shared || this.split;
+          /**
+           * Whether to allow the tooltip to render outside the chart's SVG
+           * element box. By default (false), the tooltip is rendered within the
+           * chart's SVG element, which results in the tooltip being aligned
+           * inside the chart area.
+           *
+           * @readonly
+           * @name Highcharts.Tooltip#outside
+           * @type {boolean}
+           *
+           * @todo
+           * Split tooltip does not support outside in the first iteration. Should
+           * not be too complicated to implement.
+           */
+          this.outside = pick(
+            options.outside,
+            Boolean(chart.scrollablePixelsX || chart.scrollablePixelsY)
+          );
+        };
+        /**
+         * Returns true, if the pointer is in contact with the tooltip tracker.
+         */
+        Tooltip.prototype.isStickyOnContact = function () {
+          return !!(
+            !this.followPointer &&
+            this.options.stickOnContact &&
+            this.inContact
+          );
+        };
+        /**
+         * Moves the tooltip with a soft animation to a new position.
+         *
+         * @private
+         * @function Highcharts.Tooltip#move
+         *
+         * @param {number} x
+         *
+         * @param {number} y
+         *
+         * @param {number} anchorX
+         *
+         * @param {number} anchorY
+         */
+        Tooltip.prototype.move = function (x, y, anchorX, anchorY) {
+          var tooltip = this,
+            now = tooltip.now,
+            animate =
+              tooltip.options.animation !== false &&
+              !tooltip.isHidden &&
+              // When we get close to the target position, abort animation and
+              // land on the right place (#3056)
+              (Math.abs(x - now.x) > 1 || Math.abs(y - now.y) > 1),
+            skipAnchor = tooltip.followPointer || tooltip.len > 1;
+          // Get intermediate values for animation
+          extend(now, {
+            x: animate ? (2 * now.x + x) / 3 : x,
+            y: animate ? (now.y + y) / 2 : y,
+            anchorX: skipAnchor
+              ? void 0
+              : animate
+              ? (2 * now.anchorX + anchorX) / 3
+              : anchorX,
+            anchorY: skipAnchor
+              ? void 0
+              : animate
+              ? (now.anchorY + anchorY) / 2
+              : anchorY,
+          });
+          // Move to the intermediate value
+          tooltip.getLabel().attr(now);
+          tooltip.drawTracker();
+          // Run on next tick of the mouse tracker
+          if (animate) {
+            // Never allow two timeouts
+            U.clearTimeout(this.tooltipTimeout);
+            // Set the fixed interval ticking for the smooth tooltip
+            this.tooltipTimeout = setTimeout(function () {
+              // The interval function may still be running during destroy,
+              // so check that the chart is really there before calling.
+              if (tooltip) {
+                tooltip.move(x, y, anchorX, anchorY);
+              }
+            }, 32);
+          }
+        };
+        /**
+         * Refresh the tooltip's text and position.
+         *
+         * @function Highcharts.Tooltip#refresh
+         *
+         * @param {Highcharts.Point|Array<Highcharts.Point>} pointOrPoints
+         *        Either a point or an array of points.
+         *
+         * @param {Highcharts.PointerEventObject} [mouseEvent]
+         *        Mouse event, that is responsible for the refresh and should be
+         *        used for the tooltip update.
+         */
+        Tooltip.prototype.refresh = function (pointOrPoints, mouseEvent) {
+          var tooltip = this,
+            chart = this.chart,
+            options = tooltip.options,
+            x,
+            y,
+            point = pointOrPoints,
+            anchor,
+            textConfig = {},
+            text,
+            pointConfig = [],
+            formatter = options.formatter || tooltip.defaultFormatter,
+            shared = tooltip.shared,
+            currentSeries,
+            styledMode = chart.styledMode;
+          if (!options.enabled) {
+            return;
+          }
+          U.clearTimeout(this.hideTimer);
+          // get the reference point coordinates (pie charts use tooltipPos)
+          tooltip.followPointer =
+            splat(point)[0].series.tooltipOptions.followPointer;
+          anchor = tooltip.getAnchor(point, mouseEvent);
+          x = anchor[0];
+          y = anchor[1];
+          // shared tooltip, array is sent over
+          if (shared && !(point.series && point.series.noSharedTooltip)) {
+            chart.pointer.applyInactiveState(point);
+            // Now set hover state for the choosen ones:
+            point.forEach(function (item) {
+              item.setState("hover");
+              pointConfig.push(item.getLabelConfig());
+            });
+            textConfig = {
+              x: point[0].category,
+              y: point[0].y,
+            };
+            textConfig.points = pointConfig;
+            point = point[0];
+            // single point tooltip
+          } else {
+            textConfig = point.getLabelConfig();
+          }
+          this.len = pointConfig.length; // #6128
+          text = formatter.call(textConfig, tooltip);
+          // register the current series
+          currentSeries = point.series;
+          this.distance = pick(currentSeries.tooltipOptions.distance, 16);
+          // update the inner HTML
+          if (text === false) {
+            this.hide();
+          } else {
+            // update text
+            if (tooltip.split) {
+              this.renderSplit(text, splat(pointOrPoints));
+            } else {
+              var label = tooltip.getLabel();
+              // Prevent the tooltip from flowing over the chart box (#6659)
+              if (!options.style.width || styledMode) {
+                label.css({
+                  width: this.chart.spacingBox.width + "px",
+                });
+              }
+              label.attr({
+                text: text && text.join ? text.join("") : text,
+              });
+              // Set the stroke color of the box to reflect the point
+              label
+                .removeClass(/highcharts-color-[\d]+/g)
+                .addClass(
+                  "highcharts-color-" +
+                    pick(point.colorIndex, currentSeries.colorIndex)
+                );
+              if (!styledMode) {
+                label.attr({
+                  stroke:
+                    options.borderColor ||
+                    point.color ||
+                    currentSeries.color ||
+                    "#666666",
+                });
+              }
+              tooltip.updatePosition({
+                plotX: x,
+                plotY: y,
+                negative: point.negative,
+                ttBelow: point.ttBelow,
+                h: anchor[2] || 0,
+              });
+            }
+            // show it
+            if (tooltip.isHidden && tooltip.label) {
+              tooltip.label
+                .attr({
+                  opacity: 1,
+                })
+                .show();
+            }
+            tooltip.isHidden = false;
+          }
+          fireEvent(this, "refresh");
+        };
+        /**
+         * Render the split tooltip. Loops over each point's text and adds
+         * a label next to the point, then uses the distribute function to
+         * find best non-overlapping positions.
+         *
+         * @private
+         * @function Highcharts.Tooltip#renderSplit
+         *
+         * @param {string|Array<(boolean|string)>} labels
+         *
+         * @param {Array<Highcharts.Point>} points
+         */
+        Tooltip.prototype.renderSplit = function (labels, points) {
+          var tooltip = this;
+          var chart = tooltip.chart,
+            _a = tooltip.chart,
+            chartWidth = _a.chartWidth,
+            chartHeight = _a.chartHeight,
+            plotHeight = _a.plotHeight,
+            plotLeft = _a.plotLeft,
+            plotTop = _a.plotTop,
+            pointer = _a.pointer,
+            ren = _a.renderer,
+            _b = _a.scrollablePixelsY,
+            scrollablePixelsY = _b === void 0 ? 0 : _b,
+            _c = _a.scrollingContainer,
+            _d = _c === void 0 ? { scrollLeft: 0, scrollTop: 0 } : _c,
+            scrollLeft = _d.scrollLeft,
+            scrollTop = _d.scrollTop,
+            styledMode = _a.styledMode,
+            distance = tooltip.distance,
+            options = tooltip.options,
+            positioner = tooltip.options.positioner;
+          // The area which the tooltip should be limited to. Limit to scrollable
+          // plot area if enabled, otherwise limit to the chart container.
+          var bounds = {
+            left: scrollLeft,
+            right: scrollLeft + chartWidth,
+            top: scrollTop,
+            bottom: scrollTop + chartHeight,
+          };
+          var tooltipLabel = tooltip.getLabel();
+          var headerTop = Boolean(chart.xAxis[0] && chart.xAxis[0].opposite);
+          var distributionBoxTop = plotTop + scrollTop;
+          var headerHeight = 0;
+          var adjustedPlotHeight = plotHeight - scrollablePixelsY;
+          /**
+           * Calculates the anchor position for the partial tooltip
+           *
+           * @private
+           * @param {Highcharts.Point} point The point related to the tooltip
+           * @return {object} Returns an object with anchorX and anchorY
+           */
+          function getAnchor(point) {
+            var isHeader = point.isHeader,
+              _a = point.plotX,
+              plotX = _a === void 0 ? 0 : _a,
+              _b = point.plotY,
+              plotY = _b === void 0 ? 0 : _b,
+              series = point.series;
+            var anchorX;
+            var anchorY;
+            if (isHeader) {
+              // Set anchorX to plotX
+              anchorX = plotLeft + plotX;
+              // Set anchorY to center of visible plot area.
+              anchorY = plotTop + plotHeight / 2;
+            } else {
+              var xAxis = series.xAxis,
+                yAxis = series.yAxis;
+              // Set anchorX to plotX. Limit to within xAxis.
+              anchorX =
+                xAxis.pos + clamp(plotX, -distance, xAxis.len + distance);
+              // Set anchorY, limit to the scrollable plot area
+              if (
+                yAxis.pos + plotY >= scrollTop + plotTop &&
+                yAxis.pos + plotY <=
+                  scrollTop + plotTop + plotHeight - scrollablePixelsY
+              ) {
+                anchorY = yAxis.pos + plotY;
+              }
+            }
+            // Limit values to plot area
+            anchorX = clamp(
+              anchorX,
+              bounds.left - distance,
+              bounds.right + distance
+            );
+            return { anchorX: anchorX, anchorY: anchorY };
+          }
+          /**
+           * Calculates the position of the partial tooltip
+           *
+           * @private
+           * @param {number} anchorX The partial tooltip anchor x position
+           * @param {number} anchorY The partial tooltip anchor y position
+           * @param {boolean} isHeader Whether the partial tooltip is a header
+           * @param {number} boxWidth Width of the partial tooltip
+           * @return {Highcharts.PositionObject} Returns the partial tooltip x and
+           * y position
+           */
+          function defaultPositioner(
+            anchorX,
+            anchorY,
+            isHeader,
+            boxWidth,
+            alignedLeft
+          ) {
+            if (alignedLeft === void 0) {
+              alignedLeft = true;
+            }
+            var y;
+            var x;
+            if (isHeader) {
+              y = headerTop ? 0 : adjustedPlotHeight;
+              x = clamp(
+                anchorX - boxWidth / 2,
+                bounds.left,
+                bounds.right - boxWidth
+              );
+            } else {
+              y = anchorY - distributionBoxTop;
+              x = alignedLeft
+                ? anchorX - boxWidth - distance
+                : anchorX + distance;
+              x = clamp(x, alignedLeft ? x : bounds.left, bounds.right);
+            }
+            // NOTE: y is relative to distributionBoxTop
+            return { x: x, y: y };
+          }
+          /**
+           * Updates the attributes and styling of the partial tooltip. Creates a
+           * new partial tooltip if it does not exists.
+           *
+           * @private
+           * @param {Highcharts.SVGElement|undefined} partialTooltip
+           *  The partial tooltip to update
+           * @param {Highcharts.Point} point
+           *  The point related to the partial tooltip
+           * @param {boolean|string} str The text for the partial tooltip
+           * @return {Highcharts.SVGElement} Returns the updated partial tooltip
+           */
+          function updatePartialTooltip(partialTooltip, point, str) {
+            var tt = partialTooltip;
+            var isHeader = point.isHeader,
+              series = point.series;
+            var colorClass =
+              "highcharts-color-" +
+              pick(point.colorIndex, series.colorIndex, "none");
+            if (!tt) {
+              var attribs = {
+                padding: options.padding,
+                r: options.borderRadius,
+              };
+              if (!styledMode) {
+                attribs.fill = options.backgroundColor;
+                attribs["stroke-width"] = options.borderWidth;
+              }
+              tt = ren
+                .label(
+                  "",
+                  0,
+                  0,
+                  options[isHeader ? "headerShape" : "shape"] || "callout",
+                  void 0,
+                  void 0,
+                  options.useHTML
+                )
+                .addClass(
+                  (isHeader ? "highcharts-tooltip-header " : "") +
+                    "highcharts-tooltip-box " +
+                    colorClass
+                )
+                .attr(attribs)
+                .add(tooltipLabel);
+            }
+            tt.isActive = true;
+            tt.attr({
+              text: str,
+            });
+            if (!styledMode) {
+              tt.css(options.style)
+                .shadow(options.shadow)
+                .attr({
+                  stroke:
+                    options.borderColor ||
+                    point.color ||
+                    series.color ||
+                    "#333333",
+                });
+            }
+            return tt;
+          }
+          // Graceful degradation for legacy formatters
+          if (isString(labels)) {
+            labels = [false, labels];
+          }
+          // Create the individual labels for header and points, ignore footer
+          var boxes = labels
+            .slice(0, points.length + 1)
+            .reduce(function (boxes, str, i) {
+              if (str !== false && str !== "") {
+                var point = points[i - 1] || {
+                  // Item 0 is the header. Instead of this, we could also
+                  // use the crosshair label
+                  isHeader: true,
+                  plotX: points[0].plotX,
+                  plotY: plotHeight,
+                  series: {},
+                };
+                var isHeader = point.isHeader;
+                // Store the tooltip label referance on the series
+                var owner = isHeader ? tooltip : point.series;
+                var tt = (owner.tt = updatePartialTooltip(
+                  owner.tt,
+                  point,
+                  str
+                ));
+                // Get X position now, so we can move all to the other side in
+                // case of overflow
+                var bBox = tt.getBBox();
+                var boxWidth = bBox.width + tt.strokeWidth();
+                if (isHeader) {
+                  headerHeight = bBox.height;
+                  adjustedPlotHeight += headerHeight;
+                  if (headerTop) {
+                    distributionBoxTop -= headerHeight;
+                  }
+                }
+                var _a = getAnchor(point),
+                  anchorX = _a.anchorX,
+                  anchorY = _a.anchorY;
+                if (typeof anchorY === "number") {
+                  var size = bBox.height + 1;
+                  var boxPosition = positioner
+                    ? positioner.call(tooltip, boxWidth, size, point)
+                    : defaultPositioner(anchorX, anchorY, isHeader, boxWidth);
+                  boxes.push({
+                    // 0-align to the top, 1-align to the bottom
+                    align: positioner ? 0 : void 0,
+                    anchorX: anchorX,
+                    anchorY: anchorY,
+                    boxWidth: boxWidth,
+                    point: point,
+                    rank: pick(boxPosition.rank, isHeader ? 1 : 0),
+                    size: size,
+                    target: boxPosition.y,
+                    tt: tt,
+                    x: boxPosition.x,
+                  });
+                } else {
+                  // Hide tooltips which anchorY is outside the visible plot
+                  // area
+                  tt.isActive = false;
+                }
+              }
+              return boxes;
+            }, []);
+          // If overflow left then align all labels to the right
+          if (
+            !positioner &&
+            boxes.some(function (box) {
+              return box.x < bounds.left;
+            })
+          ) {
+            boxes = boxes.map(function (box) {
+              var _a = defaultPositioner(
+                  box.anchorX,
+                  box.anchorY,
+                  box.point.isHeader,
+                  box.boxWidth,
+                  false
+                ),
+                x = _a.x,
+                y = _a.y;
+              return extend(box, {
+                target: y,
+                x: x,
+              });
+            });
+          }
+          // Clean previous run (for missing points)
+          tooltip.cleanSplit();
+          // Distribute and put in place
+          H.distribute(boxes, adjustedPlotHeight);
+          boxes.forEach(function (box) {
+            var anchorX = box.anchorX,
+              anchorY = box.anchorY,
+              pos = box.pos,
+              x = box.x;
+            // Put the label in place
+            box.tt.attr({
+              visibility: typeof pos === "undefined" ? "hidden" : "inherit",
+              x: x,
+              /* NOTE: y should equal pos to be consistent with !split
+               * tooltip, but is currently relative to plotTop. Is left as is
+               * to avoid breaking change. Remove distributionBoxTop to make
+               * it consistent.
+               */
+              y: pos + distributionBoxTop,
+              anchorX: anchorX,
+              anchorY: anchorY,
+            });
+          });
+          /* If we have a seperate tooltip container, then update the necessary
+           * container properties.
+           * Test that tooltip has its own container and renderer before executing
+           * the operation.
+           */
+          var container = tooltip.container,
+            outside = tooltip.outside,
+            renderer = tooltip.renderer;
+          if (outside && container && renderer) {
+            // Set container size to fit the tooltip
+            var _e = tooltipLabel.getBBox(),
+              width = _e.width,
+              height = _e.height,
+              x = _e.x,
+              y = _e.y;
+            renderer.setSize(width + x, height + y, false);
+            // Position the tooltip container to the chart container
+            var chartPosition = pointer.getChartPosition();
+            container.style.left = chartPosition.left + "px";
+            container.style.top = chartPosition.top + "px";
+          }
+        };
+        /**
+         * If the `stickOnContact` option is active, this will add a tracker shape.
+         *
+         * @private
+         * @function Highcharts.Tooltip#drawTracker
+         */
+        Tooltip.prototype.drawTracker = function () {
+          var tooltip = this;
+          if (tooltip.followPointer || !tooltip.options.stickOnContact) {
+            if (tooltip.tracker) {
+              tooltip.tracker.destroy();
+            }
+            return;
+          }
+          var chart = tooltip.chart;
+          var label = tooltip.label;
+          var point = chart.hoverPoint;
+          if (!label || !point) {
+            return;
+          }
+          var box = {
+            x: 0,
+            y: 0,
+            width: 0,
+            height: 0,
+          };
+          // Combine anchor and tooltip
+          var anchorPos = this.getAnchor(point);
+          var labelBBox = label.getBBox();
+          anchorPos[0] += chart.plotLeft - label.translateX;
+          anchorPos[1] += chart.plotTop - label.translateY;
+          // When the mouse pointer is between the anchor point and the label,
+          // the label should stick.
+          box.x = Math.min(0, anchorPos[0]);
+          box.y = Math.min(0, anchorPos[1]);
+          box.width =
+            anchorPos[0] < 0
+              ? Math.max(Math.abs(anchorPos[0]), labelBBox.width - anchorPos[0])
+              : Math.max(Math.abs(anchorPos[0]), labelBBox.width);
+          box.height =
+            anchorPos[1] < 0
+              ? Math.max(
+                  Math.abs(anchorPos[1]),
+                  labelBBox.height - Math.abs(anchorPos[1])
+                )
+              : Math.max(Math.abs(anchorPos[1]), labelBBox.height);
+          if (tooltip.tracker) {
+            tooltip.tracker.attr(box);
+          } else {
+            tooltip.tracker = label.renderer
+              .rect(box)
+              .addClass("highcharts-tracker")
+              .add(label);
+            if (!chart.styledMode) {
+              tooltip.tracker.attr({
+                fill: "rgba(0,0,0,0)",
+              });
+            }
+          }
+        };
+        /**
+         * @private
+         */
+        Tooltip.prototype.styledModeFormat = function (formatString) {
+          return formatString
+            .replace('style="font-size: 10px"', 'class="highcharts-header"')
+            .replace(
+              /style="color:{(point|series)\.color}"/g,
+              'class="highcharts-color-{$1.colorIndex}"'
+            );
+        };
+        /**
+         * Format the footer/header of the tooltip
+         * #3397: abstraction to enable formatting of footer and header
+         *
+         * @private
+         * @function Highcharts.Tooltip#tooltipFooterHeaderFormatter
+         * @param {Highcharts.PointLabelObject} labelConfig
+         * @param {boolean} [isFooter]
+         * @return {string}
+         */
+        Tooltip.prototype.tooltipFooterHeaderFormatter = function (
+          labelConfig,
+          isFooter
+        ) {
+          var footOrHead = isFooter ? "footer" : "header",
+            series = labelConfig.series,
+            tooltipOptions = series.tooltipOptions,
+            xDateFormat = tooltipOptions.xDateFormat,
+            xAxis = series.xAxis,
+            isDateTime =
+              xAxis &&
+              xAxis.options.type === "datetime" &&
+              isNumber(labelConfig.key),
+            formatString = tooltipOptions[footOrHead + "Format"],
+            e = {
+              isFooter: isFooter,
+              labelConfig: labelConfig,
+            };
+          fireEvent(this, "headerFormatter", e, function (e) {
+            // Guess the best date format based on the closest point distance
+            // (#568, #3418)
+            if (isDateTime && !xDateFormat) {
+              xDateFormat = this.getXDateFormat(
+                labelConfig,
+                tooltipOptions,
+                xAxis
+              );
+            }
+            // Insert the footer date format if any
+            if (isDateTime && xDateFormat) {
+              (
+                (labelConfig.point && labelConfig.point.tooltipDateKeys) || [
+                  "key",
+                ]
+              ).forEach(function (key) {
+                formatString = formatString.replace(
+                  "{point." + key + "}",
+                  "{point." + key + ":" + xDateFormat + "}"
+                );
+              });
+            }
+            // Replace default header style with class name
+            if (series.chart.styledMode) {
+              formatString = this.styledModeFormat(formatString);
+            }
+            e.text = format(
+              formatString,
+              {
+                point: labelConfig,
+                series: series,
+              },
+              this.chart
+            );
+          });
+          return e.text;
+        };
+        /**
+         * Updates the tooltip with the provided tooltip options.
+         *
+         * @function Highcharts.Tooltip#update
+         *
+         * @param {Highcharts.TooltipOptions} options
+         *        The tooltip options to update.
+         */
+        Tooltip.prototype.update = function (options) {
+          this.destroy();
+          // Update user options (#6218)
+          merge(true, this.chart.options.tooltip.userOptions, options);
+          this.init(this.chart, merge(true, this.options, options));
+        };
+        /**
+         * Find the new position and perform the move
+         *
+         * @private
+         * @function Highcharts.Tooltip#updatePosition
+         *
+         * @param {Highcharts.Point} point
+         */
+        Tooltip.prototype.updatePosition = function (point) {
+          var chart = this.chart,
+            pointer = chart.pointer,
+            label = this.getLabel(),
+            pos,
+            anchorX = point.plotX + chart.plotLeft,
+            anchorY = point.plotY + chart.plotTop,
+            pad;
+          // Needed for outside: true (#11688)
+          var chartPosition = pointer.getChartPosition();
+          pos = (this.options.positioner || this.getPosition).call(
+            this,
+            label.width,
+            label.height,
+            point
+          );
+          // Set the renderer size dynamically to prevent document size to change
+          if (this.outside) {
+            pad = (this.options.borderWidth || 0) + 2 * this.distance;
+            this.renderer.setSize(label.width + pad, label.height + pad, false);
+            // Anchor and tooltip container need scaling if chart container has
+            // scale transform/css zoom. #11329.
+            var containerScaling = chart.containerScaling;
+            if (containerScaling) {
+              css(this.container, {
+                transform:
+                  "scale(" +
+                  containerScaling.scaleX +
+                  ", " +
+                  containerScaling.scaleY +
+                  ")",
+              });
+              anchorX *= containerScaling.scaleX;
+              anchorY *= containerScaling.scaleY;
+            }
+            anchorX += chartPosition.left - pos.x;
+            anchorY += chartPosition.top - pos.y;
+          }
+          // do the move
+          this.move(
+            Math.round(pos.x),
+            Math.round(pos.y || 0), // can be undefined (#3977)
+            anchorX,
+            anchorY
+          );
+        };
+        return Tooltip;
+      })();
+      H.Tooltip = Tooltip;
+
+      return H.Tooltip;
+    }
+  );
+  _registerModule(
+    _modules,
+    "Core/Pointer.js",
+    [
+      _modules["Core/Color/Color.js"],
+      _modules["Core/Globals.js"],
+      _modules["Core/Tooltip.js"],
+      _modules["Core/Utilities.js"],
+    ],
+    function (Color, H, Tooltip, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      var color = Color.parse;
+      var charts = H.charts,
+        noop = H.noop;
+      var addEvent = U.addEvent,
+        attr = U.attr,
+        css = U.css,
+        defined = U.defined,
+        extend = U.extend,
+        find = U.find,
+        fireEvent = U.fireEvent,
+        isNumber = U.isNumber,
+        isObject = U.isObject,
+        objectEach = U.objectEach,
+        offset = U.offset,
+        pick = U.pick,
+        splat = U.splat;
+      /**
+       * One position in relation to an axis.
+       *
+       * @interface Highcharts.PointerAxisCoordinateObject
+       */ /**
+       * Related axis.
+       *
+       * @name Highcharts.PointerAxisCoordinateObject#axis
+       * @type {Highcharts.Axis}
+       */ /**
+       * Axis value.
+       *
+       * @name Highcharts.PointerAxisCoordinateObject#value
+       * @type {number}
+       */
+      /**
+       * Positions in terms of axis values.
+       *
+       * @interface Highcharts.PointerAxisCoordinatesObject
+       */ /**
+       * Positions on the x-axis.
+       * @name Highcharts.PointerAxisCoordinatesObject#xAxis
+       * @type {Array<Highcharts.PointerAxisCoordinateObject>}
+       */ /**
+       * Positions on the y-axis.
+       * @name Highcharts.PointerAxisCoordinatesObject#yAxis
+       * @type {Array<Highcharts.PointerAxisCoordinateObject>}
+       */
+      /**
+       * Pointer coordinates.
+       *
+       * @interface Highcharts.PointerCoordinatesObject
+       */ /**
+       * @name Highcharts.PointerCoordinatesObject#chartX
+       * @type {number}
+       */ /**
+       * @name Highcharts.PointerCoordinatesObject#chartY
+       * @type {number}
+       */
+      /**
+       * A native browser mouse or touch event, extended with position information
+       * relative to the {@link Chart.container}.
+       *
+       * @interface Highcharts.PointerEventObject
+       * @extends global.PointerEvent
+       */ /**
+       * The X coordinate of the pointer interaction relative to the chart.
+       *
+       * @name Highcharts.PointerEventObject#chartX
+       * @type {number}
+       */ /**
+       * The Y coordinate of the pointer interaction relative to the chart.
+       *
+       * @name Highcharts.PointerEventObject#chartY
+       * @type {number}
+       */
+      /**
+       * Axis-specific data of a selection.
+       *
+       * @interface Highcharts.SelectDataObject
+       */ /**
+       * @name Highcharts.SelectDataObject#axis
+       * @type {Highcharts.Axis}
+       */ /**
+       * @name Highcharts.SelectDataObject#max
+       * @type {number}
+       */ /**
+       * @name Highcharts.SelectDataObject#min
+       * @type {number}
+       */
+      /**
+       * Object for select events.
+       *
+       * @interface Highcharts.SelectEventObject
+       */ /**
+       * @name Highcharts.SelectEventObject#originalEvent
+       * @type {global.Event}
+       */ /**
+       * @name Highcharts.SelectEventObject#xAxis
+       * @type {Array<Highcharts.SelectDataObject>}
+       */ /**
+       * @name Highcharts.SelectEventObject#yAxis
+       * @type {Array<Highcharts.SelectDataObject>}
+       */
+      (""); // detach doclets above
+      /* eslint-disable no-invalid-this, valid-jsdoc */
+      /**
+       * The mouse and touch tracker object. Each {@link Chart} item has one
+       * assosiated Pointer item that can be accessed from the  {@link Chart.pointer}
+       * property.
+       *
+       * @class
+       * @name Highcharts.Pointer
+       *
+       * @param {Highcharts.Chart} chart
+       * The chart instance.
+       *
+       * @param {Highcharts.Options} options
+       * The root options object. The pointer uses options from the chart and
+       * tooltip structures.
+       */
+      var Pointer = /** @class */ (function () {
+        /* *
+         *
+         *  Constructors
+         *
+         * */
+        function Pointer(chart, options) {
+          this.lastValidTouch = {};
+          this.pinchDown = [];
+          this.runChartClick = false;
+          this.chart = chart;
+          this.hasDragged = false;
+          this.options = options;
+          this.unbindContainerMouseLeave = function () {};
+          this.unbindContainerMouseEnter = function () {};
+          this.init(chart, options);
+        }
+        /* *
+         *
+         *  Functions
+         *
+         * */
+        /**
+         * Set inactive state to all series that are not currently hovered,
+         * or, if `inactiveOtherPoints` is set to true, set inactive state to
+         * all points within that series.
+         *
+         * @private
+         * @function Highcharts.Pointer#applyInactiveState
+         * @param {Array<Highcharts.Point>} points
+         * Currently hovered points
+         */
+        Pointer.prototype.applyInactiveState = function (points) {
+          var activeSeries = [],
+            series;
+          // Get all active series from the hovered points
+          (points || []).forEach(function (item) {
+            series = item.series;
+            // Include itself
+            activeSeries.push(series);
+            // Include parent series
+            if (series.linkedParent) {
+              activeSeries.push(series.linkedParent);
+            }
+            // Include all child series
+            if (series.linkedSeries) {
+              activeSeries = activeSeries.concat(series.linkedSeries);
+            }
+            // Include navigator series
+            if (series.navigatorSeries) {
+              activeSeries.push(series.navigatorSeries);
+            }
+          });
+          // Now loop over all series, filtering out active series
+          this.chart.series.forEach(function (inactiveSeries) {
+            if (activeSeries.indexOf(inactiveSeries) === -1) {
+              // Inactive series
+              inactiveSeries.setState("inactive", true);
+            } else if (inactiveSeries.options.inactiveOtherPoints) {
+              // Active series, but other points should be inactivated
+              inactiveSeries.setAllPointsToState("inactive");
+            }
+          });
+        };
+        /**
+         * Destroys the Pointer object and disconnects DOM events.
+         *
+         * @function Highcharts.Pointer#destroy
+         */
+        Pointer.prototype.destroy = function () {
+          var pointer = this;
+          if (typeof pointer.unDocMouseMove !== "undefined") {
+            pointer.unDocMouseMove();
+          }
+          this.unbindContainerMouseLeave();
+          if (!H.chartCount) {
+            if (H.unbindDocumentMouseUp) {
+              H.unbindDocumentMouseUp = H.unbindDocumentMouseUp();
+            }
+            if (H.unbindDocumentTouchEnd) {
+              H.unbindDocumentTouchEnd = H.unbindDocumentTouchEnd();
+            }
+          }
+          // memory and CPU leak
+          clearInterval(pointer.tooltipTimeout);
+          objectEach(pointer, function (_val, prop) {
+            pointer[prop] = void 0;
+          });
+        };
+        /**
+         * Perform a drag operation in response to a mousemove event while the mouse
+         * is down.
+         *
+         * @private
+         * @function Highcharts.Pointer#drag
+         *
+         * @param {Highcharts.PointerEventObject} e
+         *
+         * @return {void}
+         */
+        Pointer.prototype.drag = function (e) {
+          var chart = this.chart,
+            chartOptions = chart.options.chart,
+            chartX = e.chartX,
+            chartY = e.chartY,
+            zoomHor = this.zoomHor,
+            zoomVert = this.zoomVert,
+            plotLeft = chart.plotLeft,
+            plotTop = chart.plotTop,
+            plotWidth = chart.plotWidth,
+            plotHeight = chart.plotHeight,
+            clickedInside,
+            size,
+            selectionMarker = this.selectionMarker,
+            mouseDownX = this.mouseDownX || 0,
+            mouseDownY = this.mouseDownY || 0,
+            panningEnabled = isObject(chartOptions.panning)
+              ? chartOptions.panning && chartOptions.panning.enabled
+              : chartOptions.panning,
+            panKey = chartOptions.panKey && e[chartOptions.panKey + "Key"];
+          // If the device supports both touch and mouse (like IE11), and we are
+          // touch-dragging inside the plot area, don't handle the mouse event.
+          // #4339.
+          if (selectionMarker && selectionMarker.touch) {
+            return;
+          }
+          // If the mouse is outside the plot area, adjust to cooordinates
+          // inside to prevent the selection marker from going outside
+          if (chartX < plotLeft) {
+            chartX = plotLeft;
+          } else if (chartX > plotLeft + plotWidth) {
+            chartX = plotLeft + plotWidth;
+          }
+          if (chartY < plotTop) {
+            chartY = plotTop;
+          } else if (chartY > plotTop + plotHeight) {
+            chartY = plotTop + plotHeight;
+          }
+          // determine if the mouse has moved more than 10px
+          this.hasDragged = Math.sqrt(
+            Math.pow(mouseDownX - chartX, 2) + Math.pow(mouseDownY - chartY, 2)
+          );
+          if (this.hasDragged > 10) {
+            clickedInside = chart.isInsidePlot(
+              mouseDownX - plotLeft,
+              mouseDownY - plotTop
+            );
+            // make a selection
+            if (
+              chart.hasCartesianSeries &&
+              (this.zoomX || this.zoomY) &&
+              clickedInside &&
+              !panKey
+            ) {
+              if (!selectionMarker) {
+                this.selectionMarker = selectionMarker = chart.renderer
+                  .rect(
+                    plotLeft,
+                    plotTop,
+                    zoomHor ? 1 : plotWidth,
+                    zoomVert ? 1 : plotHeight,
+                    0
+                  )
+                  .attr({
+                    class: "highcharts-selection-marker",
+                    zIndex: 7,
+                  })
+                  .add();
+                if (!chart.styledMode) {
+                  selectionMarker.attr({
+                    fill:
+                      chartOptions.selectionMarkerFill ||
+                      color("#335cad").setOpacity(0.25).get(),
+                  });
                 }
-                // A fixed size is needed for inversion to work
-                series.eventsToUnbind.push(addEvent(chart, 'resize', setInvert));
-                // Do it now
-                setInvert();
-                // On subsequent render and redraw, just do setInvert without
-                // setting up events again
-                series.invertGroups = setInvert;
-            },
-            /**
-             * General abstraction for creating plot groups like series.group,
-             * series.dataLabelsGroup and series.markerGroup. On subsequent calls,
-             * the group will only be adjusted to the updated plot size.
-             *
-             * @private
-             * @function Highcharts.Series#plotGroup
-             * @param {string} prop
-             * @param {string} name
-             * @param {string} visibility
-             * @param {number} [zIndex]
-             * @param {Highcharts.SVGElement} [parent]
-             * @return {Highcharts.SVGElement}
-             */
-            plotGroup: function (prop, name, visibility, zIndex, parent) {
-                var group = this[prop],
-                    isNew = !group,
-                    attrs = {
-                        visibility: visibility,
-                        zIndex: zIndex || 0.1 // IE8 and pointer logic use this
-                    };
-                // Avoid setting undefined opacity, or in styled mode
-                if (typeof this.opacity !== 'undefined' &&
-                    !this.chart.styledMode && this.state !== 'inactive' // #13719
+              }
+            }
+            // adjust the width of the selection marker
+            if (selectionMarker && zoomHor) {
+              size = chartX - mouseDownX;
+              selectionMarker.attr({
+                width: Math.abs(size),
+                x: (size > 0 ? 0 : size) + mouseDownX,
+              });
+            }
+            // adjust the height of the selection marker
+            if (selectionMarker && zoomVert) {
+              size = chartY - mouseDownY;
+              selectionMarker.attr({
+                height: Math.abs(size),
+                y: (size > 0 ? 0 : size) + mouseDownY,
+              });
+            }
+            // panning
+            if (clickedInside && !selectionMarker && panningEnabled) {
+              chart.pan(e, chartOptions.panning);
+            }
+          }
+        };
+        /**
+         * Start a drag operation.
+         *
+         * @private
+         * @function Highcharts.Pointer#dragStart
+         *
+         * @param {Highcharts.PointerEventObject} e
+         *
+         * @return {void}
+         */
+        Pointer.prototype.dragStart = function (e) {
+          var chart = this.chart;
+          // Record the start position
+          chart.mouseIsDown = e.type;
+          chart.cancelClick = false;
+          chart.mouseDownX = this.mouseDownX = e.chartX;
+          chart.mouseDownY = this.mouseDownY = e.chartY;
+        };
+        /**
+         * On mouse up or touch end across the entire document, drop the selection.
+         *
+         * @private
+         * @function Highcharts.Pointer#drop
+         *
+         * @param {global.Event} e
+         */
+        Pointer.prototype.drop = function (e) {
+          var pointer = this,
+            chart = this.chart,
+            hasPinched = this.hasPinched;
+          if (this.selectionMarker) {
+            var selectionData = {
+                originalEvent: e,
+                xAxis: [],
+                yAxis: [],
+              },
+              selectionBox = this.selectionMarker,
+              selectionLeft = selectionBox.attr
+                ? selectionBox.attr("x")
+                : selectionBox.x,
+              selectionTop = selectionBox.attr
+                ? selectionBox.attr("y")
+                : selectionBox.y,
+              selectionWidth = selectionBox.attr
+                ? selectionBox.attr("width")
+                : selectionBox.width,
+              selectionHeight = selectionBox.attr
+                ? selectionBox.attr("height")
+                : selectionBox.height,
+              runZoom;
+            // a selection has been made
+            if (this.hasDragged || hasPinched) {
+              // record each axis' min and max
+              chart.axes.forEach(function (axis) {
+                if (
+                  axis.zoomEnabled &&
+                  defined(axis.min) &&
+                  (hasPinched ||
+                    pointer[
+                      {
+                        xAxis: "zoomX",
+                        yAxis: "zoomY",
+                      }[axis.coll]
+                    ]) &&
+                  isNumber(selectionLeft) &&
+                  isNumber(selectionTop)
                 ) {
-                    attrs.opacity = this.opacity;
-                }
-                // Generate it on first call
-                if (isNew) {
-                    this[prop] = group = this.chart.renderer
-                        .g()
-                        .add(parent);
-                }
-                // Add the class names, and replace existing ones as response to
-                // Series.update (#6660)
-                group.addClass(('highcharts-' + name +
-                    ' highcharts-series-' + this.index +
-                    ' highcharts-' + this.type + '-series ' +
-                    (defined(this.colorIndex) ?
-                        'highcharts-color-' + this.colorIndex + ' ' :
-                        '') +
-                    (this.options.className || '') +
-                    (group.hasClass('highcharts-tracker') ?
-                        ' highcharts-tracker' :
-                        '')), true);
-                // Place it on first and subsequent (redraw) calls
-                group.attr(attrs)[isNew ? 'attr' : 'animate'](this.getPlotBox());
-                return group;
-            },
-            /**
-             * Get the translation and scale for the plot area of this series.
-             *
-             * @function Highcharts.Series#getPlotBox
-             *
-             * @return {Highcharts.SeriesPlotBoxObject}
-             */
-            getPlotBox: function () {
-                var chart = this.chart,
-                    xAxis = this.xAxis,
-                    yAxis = this.yAxis;
-                // Swap axes for inverted (#2339)
-                if (chart.inverted) {
-                    xAxis = yAxis;
-                    yAxis = this.xAxis;
-                }
-                return {
-                    translateX: xAxis ? xAxis.left : chart.plotLeft,
-                    translateY: yAxis ? yAxis.top : chart.plotTop,
-                    scaleX: 1,
-                    scaleY: 1
+                  // #859, #3569
+                  var horiz = axis.horiz,
+                    minPixelPadding =
+                      e.type === "touchend" ? axis.minPixelPadding : 0, // #1207, #3075
+                    selectionMin = axis.toValue(
+                      (horiz ? selectionLeft : selectionTop) + minPixelPadding
+                    ),
+                    selectionMax = axis.toValue(
+                      (horiz
+                        ? selectionLeft + selectionWidth
+                        : selectionTop + selectionHeight) - minPixelPadding
+                    );
+                  selectionData[axis.coll].push({
+                    axis: axis,
+                    // Min/max for reversed axes
+                    min: Math.min(selectionMin, selectionMax),
+                    max: Math.max(selectionMin, selectionMax),
+                  });
+                  runZoom = true;
+                }
+              });
+              if (runZoom) {
+                fireEvent(chart, "selection", selectionData, function (args) {
+                  chart.zoom(
+                    extend(args, hasPinched ? { animation: false } : null)
+                  );
+                });
+              }
+            }
+            if (isNumber(chart.index)) {
+              this.selectionMarker = this.selectionMarker.destroy();
+            }
+            // Reset scaling preview
+            if (hasPinched) {
+              this.scaleGroups();
+            }
+          }
+          // Reset all. Check isNumber because it may be destroyed on mouse up
+          // (#877)
+          if (chart && isNumber(chart.index)) {
+            css(chart.container, { cursor: chart._cursor });
+            chart.cancelClick = this.hasDragged > 10; // #370
+            chart.mouseIsDown = this.hasDragged = this.hasPinched = false;
+            this.pinchDown = [];
+          }
+        };
+        /**
+         * Finds the closest point to a set of coordinates, using the k-d-tree
+         * algorithm.
+         *
+         * @function Highcharts.Pointer#findNearestKDPoint
+         *
+         * @param {Array<Highcharts.Series>} series
+         *        All the series to search in.
+         *
+         * @param {boolean|undefined} shared
+         *        Whether it is a shared tooltip or not.
+         *
+         * @param {Highcharts.PointerEventObject} e
+         *        The pointer event object, containing chart coordinates of the
+         *        pointer.
+         *
+         * @return {Highcharts.Point|undefined}
+         *         The point closest to given coordinates.
+         */
+        Pointer.prototype.findNearestKDPoint = function (series, shared, e) {
+          var chart = this.chart;
+          var hoverPoint = chart.hoverPoint;
+          var tooltip = chart.tooltip;
+          if (hoverPoint && tooltip && tooltip.isStickyOnContact()) {
+            return hoverPoint;
+          }
+          var closest;
+          /** @private */
+          function sort(p1, p2) {
+            var isCloserX = p1.distX - p2.distX,
+              isCloser = p1.dist - p2.dist,
+              isAbove =
+                (p2.series.group && p2.series.group.zIndex) -
+                (p1.series.group && p1.series.group.zIndex),
+              result;
+            // We have two points which are not in the same place on xAxis
+            // and shared tooltip:
+            if (isCloserX !== 0 && shared) {
+              // #5721
+              result = isCloserX;
+              // Points are not exactly in the same place on x/yAxis:
+            } else if (isCloser !== 0) {
+              result = isCloser;
+              // The same xAxis and yAxis position, sort by z-index:
+            } else if (isAbove !== 0) {
+              result = isAbove;
+              // The same zIndex, sort by array index:
+            } else {
+              result = p1.series.index > p2.series.index ? -1 : 1;
+            }
+            return result;
+          }
+          series.forEach(function (s) {
+            var noSharedTooltip = s.noSharedTooltip && shared,
+              compareX =
+                !noSharedTooltip &&
+                s.options.findNearestPointBy.indexOf("y") < 0,
+              point = s.searchPoint(e, compareX);
+            if (
+              // Check that we actually found a point on the series.
+              isObject(point, true) &&
+              // Use the new point if it is closer.
+              (!isObject(closest, true) || sort(closest, point) > 0)
+            ) {
+              closest = point;
+            }
+          });
+          return closest;
+        };
+        /**
+         * @private
+         * @function Highcharts.Pointer#getChartCoordinatesFromPoint
+         * @param {Highcharts.Point} point
+         * @param {boolean} [inverted]
+         * @return {Highcharts.PointerCoordinatesObject|undefined}
+         */
+        Pointer.prototype.getChartCoordinatesFromPoint = function (
+          point,
+          inverted
+        ) {
+          var series = point.series,
+            xAxis = series.xAxis,
+            yAxis = series.yAxis,
+            plotX = pick(point.clientX, point.plotX),
+            shapeArgs = point.shapeArgs;
+          if (xAxis && yAxis) {
+            return inverted
+              ? {
+                  chartX: xAxis.len + xAxis.pos - plotX,
+                  chartY: yAxis.len + yAxis.pos - point.plotY,
+                }
+              : {
+                  chartX: plotX + xAxis.pos,
+                  chartY: point.plotY + yAxis.pos,
                 };
+          }
+          if (shapeArgs && shapeArgs.x && shapeArgs.y) {
+            // E.g. pies do not have axes
+            return {
+              chartX: shapeArgs.x,
+              chartY: shapeArgs.y,
+            };
+          }
+        };
+        /**
+         * Return the cached chartPosition if it is available on the Pointer,
+         * otherwise find it. Running offset is quite expensive, so it should be
+         * avoided when we know the chart hasn't moved.
+         *
+         * @function Highcharts.Pointer#getChartPosition
+         *
+         * @return {Highcharts.OffsetObject}
+         *         The offset of the chart container within the page
+         */
+        Pointer.prototype.getChartPosition = function () {
+          return (
+            this.chartPosition ||
+            (this.chartPosition = offset(this.chart.container))
+          );
+        };
+        /**
+         * Get the click position in terms of axis values.
+         *
+         * @function Highcharts.Pointer#getCoordinates
+         *
+         * @param {Highcharts.PointerEventObject} e
+         *        Pointer event, extended with `chartX` and `chartY` properties.
+         *
+         * @return {Highcharts.PointerAxisCoordinatesObject}
+         */
+        Pointer.prototype.getCoordinates = function (e) {
+          var coordinates = {
+            xAxis: [],
+            yAxis: [],
+          };
+          this.chart.axes.forEach(function (axis) {
+            coordinates[axis.isXAxis ? "xAxis" : "yAxis"].push({
+              axis: axis,
+              value: axis.toValue(e[axis.horiz ? "chartX" : "chartY"]),
+            });
+          });
+          return coordinates;
+        };
+        /**
+         * Calculates what is the current hovered point/points and series.
+         *
+         * @private
+         * @function Highcharts.Pointer#getHoverData
+         *
+         * @param {Highcharts.Point|undefined} existingHoverPoint
+         *        The point currrently beeing hovered.
+         *
+         * @param {Highcharts.Series|undefined} existingHoverSeries
+         *        The series currently beeing hovered.
+         *
+         * @param {Array<Highcharts.Series>} series
+         *        All the series in the chart.
+         *
+         * @param {boolean} isDirectTouch
+         *        Is the pointer directly hovering the point.
+         *
+         * @param {boolean|undefined} shared
+         *        Whether it is a shared tooltip or not.
+         *
+         * @param {Highcharts.PointerEventObject} [e]
+         *        The triggering event, containing chart coordinates of the pointer.
+         *
+         * @return {object}
+         *         Object containing resulting hover data: hoverPoint, hoverSeries,
+         *         and hoverPoints.
+         */
+        Pointer.prototype.getHoverData = function (
+          existingHoverPoint,
+          existingHoverSeries,
+          series,
+          isDirectTouch,
+          shared,
+          e
+        ) {
+          var hoverPoint,
+            hoverPoints = [],
+            hoverSeries = existingHoverSeries,
+            useExisting = !!(isDirectTouch && existingHoverPoint),
+            notSticky = hoverSeries && !hoverSeries.stickyTracking,
+            // Which series to look in for the hover point
+            searchSeries,
+            // Parameters needed for beforeGetHoverData event.
+            eventArgs = {
+              chartX: e ? e.chartX : void 0,
+              chartY: e ? e.chartY : void 0,
+              shared: shared,
             },
-            /**
-             * Removes the event handlers attached previously with addEvents.
-             *
-             * @private
-             * @function Highcharts.Series#removeEvents
-             * @param {boolean} [keepEventsForUpdate]
-             * @return {void}
-             */
-            removeEvents: function (keepEventsForUpdate) {
-                var series = this;
-                if (!keepEventsForUpdate) {
-                    // remove all events
-                    removeEvent(series);
-                }
-                else if (series.eventsToUnbind.length) {
-                    // remove only internal events for proper update
-                    // #12355 - solves problem with multiple destroy events
-                    series.eventsToUnbind.forEach(function (unbind) {
-                        unbind();
-                    });
-                    series.eventsToUnbind.length = 0;
-                }
-            },
-            /**
-             * Render the graph and markers. Called internally when first rendering
-             * and later when redrawing the chart. This function can be extended in
-             * plugins, but normally shouldn't be called directly.
-             *
-             * @function Highcharts.Series#render
-             *
-             * @return {void}
-             *
-             * @fires Highcharts.Series#event:afterRender
-             */
-            render: function () {
-                var series = this,
-                    chart = series.chart,
-                    group,
-                    options = series.options,
-                    animOptions = animObject(options.animation), 
-                    // Animation doesn't work in IE8 quirks when the group div is
-                    // hidden, and looks bad in other oldIE
-                    animDuration = (!series.finishedAnimating &&
-                        chart.renderer.isSVG &&
-                        animOptions.duration),
-                    visibility = series.visible ? 'inherit' : 'hidden', // #2597
-                    zIndex = options.zIndex,
-                    hasRendered = series.hasRendered,
-                    chartSeriesGroup = chart.seriesGroup,
-                    inverted = chart.inverted;
-                fireEvent(this, 'render');
-                // the group
-                group = series.plotGroup('group', 'series', visibility, zIndex, chartSeriesGroup);
-                series.markerGroup = series.plotGroup('markerGroup', 'markers', visibility, zIndex, chartSeriesGroup);
-                // initiate the animation
-                if (animDuration && series.animate) {
-                    series.animate(true);
-                }
-                // SVGRenderer needs to know this before drawing elements (#1089,
-                // #1795)
-                group.inverted = series.isCartesian || series.invertable ?
-                    inverted : false;
-                // Draw the graph if any
-                if (series.drawGraph) {
-                    series.drawGraph();
-                    series.applyZones();
-                }
-                // Draw the points
-                if (series.visible) {
-                    series.drawPoints();
-                }
-                /* series.points.forEach(function (point) {
-                    if (point.redraw) {
-                        point.redraw();
-                    }
-                }); */
-                // Draw the data labels
-                if (series.drawDataLabels) {
-                    series.drawDataLabels();
-                }
-                // In pie charts, slices are added to the DOM, but actual rendering
-                // is postponed until labels reserved their space
-                if (series.redrawPoints) {
-                    series.redrawPoints();
-                }
-                // draw the mouse tracking area
-                if (series.drawTracker &&
-                    series.options.enableMouseTracking !== false) {
-                    series.drawTracker();
-                }
-                // Handle inverted series and tracker groups
-                series.invertGroups(inverted);
-                // Initial clipping, must be defined after inverting groups for VML.
-                // Applies to columns etc. (#3839).
-                if (options.clip !== false &&
-                    !series.sharedClipKey &&
-                    !hasRendered) {
-                    group.clip(chart.clipRect);
-                }
-                // Run the animation
-                if (animDuration && series.animate) {
-                    series.animate();
-                }
-                // Call the afterAnimate function on animation complete (but don't
-                // overwrite the animation.complete option which should be available
-                // to the user).
-                if (!hasRendered) {
-                    // Additional time if defer is defined before afterAnimate
-                    // will be triggered
-                    if (animDuration && animOptions.defer) {
-                        animDuration += animOptions.defer;
-                    }
-                    series.animationTimeout = syncTimeout(function () {
-                        series.afterAnimate();
-                    }, animDuration || 0);
-                }
-                // Means data is in accordance with what you see
-                series.isDirty = false;
-                // (See #322) series.isDirty = series.isDirtyData = false; // means
-                // data is in accordance with what you see
-                series.hasRendered = true;
-                fireEvent(series, 'afterRender');
-            },
-            /**
-             * Redraw the series. This function is called internally from
-             * `chart.redraw` and normally shouldn't be called directly.
-             *
-             * @private
-             * @function Highcharts.Series#redraw
-             * @return {void}
-             */
-            redraw: function () {
-                var series = this,
-                    chart = series.chart, 
-                    // cache it here as it is set to false in render, but used after
-                    wasDirty = series.isDirty || series.isDirtyData,
-                    group = series.group,
-                    xAxis = series.xAxis,
-                    yAxis = series.yAxis;
-                // reposition on resize
-                if (group) {
-                    if (chart.inverted) {
-                        group.attr({
-                            width: chart.plotWidth,
-                            height: chart.plotHeight
-                        });
-                    }
-                    group.animate({
-                        translateX: pick(xAxis && xAxis.left, chart.plotLeft),
-                        translateY: pick(yAxis && yAxis.top, chart.plotTop)
-                    });
-                }
-                series.translate();
-                series.render();
-                if (wasDirty) { // #3868, #3945
-                    delete this.kdTree;
-                }
-            },
-            kdAxisArray: ['clientX', 'plotY'],
-            /**
-             * @private
-             * @function Highcharts.Series#searchPoint
-             * @param {Highcharts.PointerEventObject} e
-             * @param {boolean} [compareX]
-             * @return {Highcharts.Point}
-             */
-            searchPoint: function (e, compareX) {
-                var series = this,
-                    xAxis = series.xAxis,
-                    yAxis = series.yAxis,
-                    inverted = series.chart.inverted;
-                return this.searchKDTree({
-                    clientX: inverted ?
-                        xAxis.len - e.chartY + xAxis.pos :
-                        e.chartX - xAxis.pos,
-                    plotY: inverted ?
-                        yAxis.len - e.chartX + yAxis.pos :
-                        e.chartY - yAxis.pos
-                }, compareX, e);
-            },
-            /**
-             * Build the k-d-tree that is used by mouse and touch interaction to get
-             * the closest point. Line-like series typically have a one-dimensional
-             * tree where points are searched along the X axis, while scatter-like
-             * series typically search in two dimensions, X and Y.
-             *
-             * @private
-             * @function Highcharts.Series#buildKDTree
-             * @param {Highcharts.PointerEventObject} [e]
-             * @return {void}
-             */
-            buildKDTree: function (e) {
-                // Prevent multiple k-d-trees from being built simultaneously
-                // (#6235)
-                this.buildingKdTree = true;
-                var series = this,
-                    dimensions = series.options.findNearestPointBy
-                        .indexOf('y') > -1 ? 2 : 1;
-                /**
-                 * Internal function
-                 * @private
-                 */
-                function _kdtree(points, depth, dimensions) {
-                    var axis,
-                        median,
-                        length = points && points.length;
-                    if (length) {
-                        // alternate between the axis
-                        axis = series.kdAxisArray[depth % dimensions];
-                        // sort point array
-                        points.sort(function (a, b) {
-                            return a[axis] - b[axis];
-                        });
-                        median = Math.floor(length / 2);
-                        // build and return nod
-                        return {
-                            point: points[median],
-                            left: _kdtree(points.slice(0, median), depth + 1, dimensions),
-                            right: _kdtree(points.slice(median + 1), depth + 1, dimensions)
-                        };
-                    }
-                }
-                /**
-                 * Start the recursive build process with a clone of the points
-                 * array and null points filtered out. (#3873)
-                 * @private
-                 */
-                function startRecursive() {
-                    series.kdTree = _kdtree(series.getValidPoints(null, 
-                    // For line-type series restrict to plot area, but
-                    // column-type series not (#3916, #4511)
-                    !series.directTouch), dimensions, dimensions);
-                    series.buildingKdTree = false;
-                }
-                delete series.kdTree;
-                // For testing tooltips, don't build async. Also if touchstart, we
-                // may be dealing with click events on mobile, so don't delay
-                // (#6817).
-                syncTimeout(startRecursive, series.options.kdNow || (e && e.type === 'touchstart') ? 0 : 1);
-            },
-            /**
-             * @private
-             * @function Highcharts.Series#searchKDTree
-             * @param {Highcharts.KDPointSearchObject} point
-             * @param {boolean} [compareX]
-             * @param {Highcharts.PointerEventObject} [e]
-             * @return {Highcharts.Point|undefined}
-             */
-            searchKDTree: function (point, compareX, e) {
-                var series = this,
-                    kdX = this.kdAxisArray[0],
-                    kdY = this.kdAxisArray[1],
-                    kdComparer = compareX ? 'distX' : 'dist',
-                    kdDimensions = series.options.findNearestPointBy
-                        .indexOf('y') > -1 ? 2 : 1;
-                /**
-                 * Set the one and two dimensional distance on the point object.
-                 * @private
-                 */
-                function setDistance(p1, p2) {
-                    var x = (defined(p1[kdX]) &&
-                            defined(p2[kdX])) ?
-                            Math.pow(p1[kdX] - p2[kdX], 2) :
-                            null,
-                        y = (defined(p1[kdY]) &&
-                            defined(p2[kdY])) ?
-                            Math.pow(p1[kdY] - p2[kdY], 2) :
-                            null,
-                        r = (x || 0) + (y || 0);
-                    p2.dist = defined(r) ? Math.sqrt(r) : Number.MAX_VALUE;
-                    p2.distX = defined(x) ? Math.sqrt(x) : Number.MAX_VALUE;
-                }
-                /**
-                 * @private
-                 */
-                function _search(search, tree, depth, dimensions) {
-                    var point = tree.point,
-                        axis = series.kdAxisArray[depth % dimensions],
-                        tdist,
-                        sideA,
-                        sideB,
-                        ret = point,
-                        nPoint1,
-                        nPoint2;
-                    setDistance(search, point);
-                    // Pick side based on distance to splitting point
-                    tdist = search[axis] - point[axis];
-                    sideA = tdist < 0 ? 'left' : 'right';
-                    sideB = tdist < 0 ? 'right' : 'left';
-                    // End of tree
-                    if (tree[sideA]) {
-                        nPoint1 = _search(search, tree[sideA], depth + 1, dimensions);
-                        ret = (nPoint1[kdComparer] <
-                            ret[kdComparer] ?
-                            nPoint1 :
-                            point);
-                    }
-                    if (tree[sideB]) {
-                        // compare distance to current best to splitting point to
-                        // decide wether to check side B or not
-                        if (Math.sqrt(tdist * tdist) < ret[kdComparer]) {
-                            nPoint2 = _search(search, tree[sideB], depth + 1, dimensions);
-                            ret = (nPoint2[kdComparer] <
-                                ret[kdComparer] ?
-                                nPoint2 :
-                                ret);
-                        }
-                    }
-                    return ret;
-                }
-                if (!this.kdTree && !this.buildingKdTree) {
-                    this.buildKDTree(e);
-                }
-                if (this.kdTree) {
-                    return _search(point, this.kdTree, kdDimensions, kdDimensions);
-                }
-            },
-            /**
-             * @private
-             * @function Highcharts.Series#pointPlacementToXValue
-             * @return {number}
-             */
-            pointPlacementToXValue: function () {
-                var _a = this,
-                    _b = _a.options,
-                    pointPlacement = _b.pointPlacement,
-                    pointRange = _b.pointRange,
-                    axis = _a.xAxis;
-                var factor = pointPlacement;
-                // Point placement is relative to each series pointRange (#5889)
-                if (factor === 'between') {
-                    factor = axis.reversed ? -0.5 : 0.5; // #11955
-                }
-                return isNumber(factor) ?
-                    factor * pick(pointRange, axis.pointRange) :
-                    0;
-            },
-            /**
-             * @private
-             * @function Highcharts.Series#isPointInside
-             * @param {Highcharts.Point} point
-             * @return {boolean}
-             */
-            isPointInside: function (point) {
-                var isInside = typeof point.plotY !== 'undefined' &&
-                        typeof point.plotX !== 'undefined' &&
-                        point.plotY >= 0 &&
-                        point.plotY <= this.yAxis.len && // #3519
-                        point.plotX >= 0 &&
-                        point.plotX <= this.xAxis.len;
-                return isInside;
-            }
-        }); // end Series prototype
-        /**
-         * A line series displays information as a series of data points connected by
-         * straight line segments.
-         *
-         * @sample {highcharts} highcharts/demo/line-basic/
-         *         Line chart
-         * @sample {highstock} stock/demo/basic-line/
-         *         Line chart
-         *
-         * @extends   plotOptions.series
-         * @product   highcharts highstock
-         * @apioption plotOptions.line
+            filter = function (s) {
+              return (
+                s.visible &&
+                !(!shared && s.directTouch) && // #3821
+                pick(s.options.enableMouseTracking, true)
+              );
+            };
+          // Find chart.hoverPane and update filter method in polar.
+          fireEvent(this, "beforeGetHoverData", eventArgs);
+          searchSeries = notSticky
+            ? // Only search on hovered series if it has stickyTracking false
+              [hoverSeries]
+            : // Filter what series to look in.
+              series.filter(function (s) {
+                return eventArgs.filter
+                  ? eventArgs.filter(s)
+                  : filter(s) && s.stickyTracking;
+              });
+          // Use existing hovered point or find the one closest to coordinates.
+          hoverPoint =
+            useExisting || !e
+              ? existingHoverPoint
+              : this.findNearestKDPoint(searchSeries, shared, e);
+          // Assign hover series
+          hoverSeries = hoverPoint && hoverPoint.series;
+          // If we have a hoverPoint, assign hoverPoints.
+          if (hoverPoint) {
+            // When tooltip is shared, it displays more than one point
+            if (shared && !hoverSeries.noSharedTooltip) {
+              searchSeries = series.filter(function (s) {
+                return eventArgs.filter
+                  ? eventArgs.filter(s)
+                  : filter(s) && !s.noSharedTooltip;
+              });
+              // Get all points with the same x value as the hoverPoint
+              searchSeries.forEach(function (s) {
+                var point = find(s.points, function (p) {
+                  return p.x === hoverPoint.x && !p.isNull;
+                });
+                if (isObject(point)) {
+                  /*
+                   * Boost returns a minimal point. Convert it to a usable
+                   * point for tooltip and states.
+                   */
+                  if (s.chart.isBoosting) {
+                    point = s.getPoint(point);
+                  }
+                  hoverPoints.push(point);
+                }
+              });
+            } else {
+              hoverPoints.push(hoverPoint);
+            }
+          }
+          // Check whether the hoverPoint is inside pane we are hovering over.
+          eventArgs = { hoverPoint: hoverPoint };
+          fireEvent(this, "afterGetHoverData", eventArgs);
+          return {
+            hoverPoint: eventArgs.hoverPoint,
+            hoverSeries: hoverSeries,
+            hoverPoints: hoverPoints,
+          };
+        };
+        /**
+         * @private
+         * @function Highcharts.Pointer#getPointFromEvent
+         *
+         * @param {global.Event} e
+         *
+         * @return {Highcharts.Point|undefined}
+         */
+        Pointer.prototype.getPointFromEvent = function (e) {
+          var target = e.target,
+            point;
+          while (target && !point) {
+            point = target.point;
+            target = target.parentNode;
+          }
+          return point;
+        };
+        /**
+         * @private
+         * @function Highcharts.Pointer#onTrackerMouseOut
+         *
+         * @param {Highcharts.PointerEventObject} e
+         *
+         * @return {void}
+         */
+        Pointer.prototype.onTrackerMouseOut = function (e) {
+          var chart = this.chart;
+          var relatedTarget = e.relatedTarget || e.toElement;
+          var series = chart.hoverSeries;
+          this.isDirectTouch = false;
+          if (
+            series &&
+            relatedTarget &&
+            !series.stickyTracking &&
+            !this.inClass(relatedTarget, "highcharts-tooltip") &&
+            (!this.inClass(
+              relatedTarget,
+              "highcharts-series-" + series.index
+            ) || // #2499, #4465, #5553
+              !this.inClass(relatedTarget, "highcharts-tracker"))
+          ) {
+            series.onMouseOut();
+          }
+        };
+        /**
+         * Utility to detect whether an element has, or has a parent with, a
+         * specificclass name. Used on detection of tracker objects and on deciding
+         * whether hovering the tooltip should cause the active series to mouse out.
+         *
+         * @function Highcharts.Pointer#inClass
+         *
+         * @param {Highcharts.SVGDOMElement|Highcharts.HTMLDOMElement} element
+         *        The element to investigate.
+         *
+         * @param {string} className
+         *        The class name to look for.
+         *
+         * @return {boolean|undefined}
+         *         True if either the element or one of its parents has the given
+         *         class name.
+         */
+        Pointer.prototype.inClass = function (element, className) {
+          var elemClassName;
+          while (element) {
+            elemClassName = attr(element, "class");
+            if (elemClassName) {
+              if (elemClassName.indexOf(className) !== -1) {
+                return true;
+              }
+              if (elemClassName.indexOf("highcharts-container") !== -1) {
+                return false;
+              }
+            }
+            element = element.parentNode;
+          }
+        };
+        /**
+         * Initialize the Pointer.
+         *
+         * @private
+         * @function Highcharts.Pointer#init
+         *
+         * @param {Highcharts.Chart} chart
+         *        The Chart instance.
+         *
+         * @param {Highcharts.Options} options
+         *        The root options object. The pointer uses options from the chart
+         *        and tooltip structures.
+         *
+         * @return {void}
+         */
+        Pointer.prototype.init = function (chart, options) {
+          // Store references
+          this.options = options;
+          this.chart = chart;
+          // Do we need to handle click on a touch device?
+          this.runChartClick =
+            options.chart.events && !!options.chart.events.click;
+          this.pinchDown = [];
+          this.lastValidTouch = {};
+          if (Tooltip) {
+            /**
+             * Tooltip object for points of series.
+             *
+             * @name Highcharts.Chart#tooltip
+             * @type {Highcharts.Tooltip}
+             */
+            chart.tooltip = new Tooltip(chart, options.tooltip);
+            this.followTouchMove = pick(options.tooltip.followTouchMove, true);
+          }
+          this.setDOMEvents();
+        };
+        /**
+         * Takes a browser event object and extends it with custom Highcharts
+         * properties `chartX` and `chartY` in order to work on the internal
+         * coordinate system.
+         *
+         * @function Highcharts.Pointer#normalize
+         *
+         * @param {global.MouseEvent|global.PointerEvent|global.TouchEvent} e
+         *        Event object in standard browsers.
+         *
+         * @param {Highcharts.OffsetObject} [chartPosition]
+         *        Additional chart offset.
+         *
+         * @return {Highcharts.PointerEventObject}
+         *         A browser event with extended properties `chartX` and `chartY`.
+         */
+        Pointer.prototype.normalize = function (e, chartPosition) {
+          var touches = e.touches;
+          // iOS (#2757)
+          var ePos = touches
+            ? touches.length
+              ? touches.item(0)
+              : pick(
+                  // #13534
+                  touches.changedTouches,
+                  e.changedTouches
+                )[0]
+            : e;
+          // Get mouse position
+          if (!chartPosition) {
+            chartPosition = this.getChartPosition();
+          }
+          var chartX = ePos.pageX - chartPosition.left,
+            chartY = ePos.pageY - chartPosition.top;
+          // #11329 - when there is scaling on a parent element, we need to take
+          // this into account
+          var containerScaling = this.chart.containerScaling;
+          if (containerScaling) {
+            chartX /= containerScaling.scaleX;
+            chartY /= containerScaling.scaleY;
+          }
+          return extend(e, {
+            chartX: Math.round(chartX),
+            chartY: Math.round(chartY),
+          });
+        };
+        /**
+         * @private
+         * @function Highcharts.Pointer#onContainerClick
+         */
+        Pointer.prototype.onContainerClick = function (e) {
+          var chart = this.chart;
+          var hoverPoint = chart.hoverPoint;
+          var pEvt = this.normalize(e);
+          var plotLeft = chart.plotLeft;
+          var plotTop = chart.plotTop;
+          if (!chart.cancelClick) {
+            // On tracker click, fire the series and point events. #783, #1583
+            if (hoverPoint && this.inClass(pEvt.target, "highcharts-tracker")) {
+              // the series click event
+              fireEvent(
+                hoverPoint.series,
+                "click",
+                extend(pEvt, {
+                  point: hoverPoint,
+                })
+              );
+              // the point click event
+              if (chart.hoverPoint) {
+                // it may be destroyed (#1844)
+                hoverPoint.firePointEvent("click", pEvt);
+              }
+              // When clicking outside a tracker, fire a chart event
+            } else {
+              extend(pEvt, this.getCoordinates(pEvt));
+              // fire a click event in the chart
+              if (
+                chart.isInsidePlot(
+                  pEvt.chartX - plotLeft,
+                  pEvt.chartY - plotTop
+                )
+              ) {
+                fireEvent(chart, "click", pEvt);
+              }
+            }
+          }
+        };
+        /**
+         * @private
+         * @function Highcharts.Pointer#onContainerMouseDown
+         *
+         * @param {global.MouseEvent} e
+         */
+        Pointer.prototype.onContainerMouseDown = function (e) {
+          var isPrimaryButton = ((e.buttons || e.button) & 1) === 1;
+          // Normalize before the 'if' for the legacy IE (#7850)
+          e = this.normalize(e);
+          // #11635, Firefox does not reliable fire move event after click scroll
+          if (H.isFirefox && e.button !== 0) {
+            this.onContainerMouseMove(e);
+          }
+          // #11635, limiting to primary button (incl. IE 8 support)
+          if (typeof e.button === "undefined" || isPrimaryButton) {
+            this.zoomOption(e);
+            // #295, #13737 solve conflict between container drag and chart zoom
+            if (isPrimaryButton && e.preventDefault) {
+              e.preventDefault();
+            }
+            this.dragStart(e);
+          }
+        };
+        /**
+         * When mouse leaves the container, hide the tooltip.
+         *
+         * @private
+         * @function Highcharts.Pointer#onContainerMouseLeave
+         *
+         * @param {global.MouseEvent} e
+         *
+         * @return {void}
+         */
+        Pointer.prototype.onContainerMouseLeave = function (e) {
+          var chart = charts[pick(H.hoverChartIndex, -1)];
+          var tooltip = this.chart.tooltip;
+          e = this.normalize(e);
+          // #4886, MS Touch end fires mouseleave but with no related target
+          if (chart && (e.relatedTarget || e.toElement)) {
+            chart.pointer.reset();
+            // Also reset the chart position, used in #149 fix
+            chart.pointer.chartPosition = void 0;
+          }
+          if (
+            // #11635, Firefox wheel scroll does not fire out events consistently
+            tooltip &&
+            !tooltip.isHidden
+          ) {
+            this.reset();
+          }
+        };
+        /**
+         * When mouse enters the container, delete pointer's chartPosition.
+         *
+         * @private
+         * @function Highcharts.Pointer#onContainerMouseEnter
+         *
+         * @param {global.MouseEvent} e
+         *
+         * @return {void}
+         */
+        Pointer.prototype.onContainerMouseEnter = function (e) {
+          delete this.chartPosition;
+        };
+        /**
+         * The mousemove, touchmove and touchstart event handler
+         *
+         * @private
+         * @function Highcharts.Pointer#onContainerMouseMove
+         *
+         * @param {global.MouseEvent} e
+         *
+         * @return {void}
+         */
+        Pointer.prototype.onContainerMouseMove = function (e) {
+          var chart = this.chart;
+          var pEvt = this.normalize(e);
+          this.setHoverChartIndex();
+          // In IE8 we apparently need this returnValue set to false in order to
+          // avoid text being selected. But in Chrome, e.returnValue is prevented,
+          // plus we don't need to run e.preventDefault to prevent selected text
+          // in modern browsers. So we set it conditionally. Remove it when IE8 is
+          // no longer needed. #2251, #3224.
+          if (!pEvt.preventDefault) {
+            pEvt.returnValue = false;
+          }
+          if (chart.mouseIsDown === "mousedown") {
+            this.drag(pEvt);
+          }
+          // Show the tooltip and run mouse over events (#977)
+          if (
+            !chart.openMenu &&
+            (this.inClass(pEvt.target, "highcharts-tracker") ||
+              chart.isInsidePlot(
+                pEvt.chartX - chart.plotLeft,
+                pEvt.chartY - chart.plotTop
+              ))
+          ) {
+            this.runPointActions(pEvt);
+          }
+        };
+        /**
+         * @private
+         * @function Highcharts.Pointer#onDocumentTouchEnd
+         *
+         * @param {Highcharts.PointerEventObject} e
+         *
+         * @return {void}
+         */
+        Pointer.prototype.onDocumentTouchEnd = function (e) {
+          if (charts[H.hoverChartIndex]) {
+            charts[H.hoverChartIndex].pointer.drop(e);
+          }
+        };
+        /**
+         * @private
+         * @function Highcharts.Pointer#onContainerTouchMove
+         *
+         * @param {Highcharts.PointerEventObject} e
+         *
+         * @return {void}
          */
+        Pointer.prototype.onContainerTouchMove = function (e) {
+          this.touch(e);
+        };
+        /**
+         * @private
+         * @function Highcharts.Pointer#onContainerTouchStart
+         *
+         * @param {Highcharts.PointerEventObject} e
+         *
+         * @return {void}
+         */
+        Pointer.prototype.onContainerTouchStart = function (e) {
+          this.zoomOption(e);
+          this.touch(e, true);
+        };
+        /**
+         * Special handler for mouse move that will hide the tooltip when the mouse
+         * leaves the plotarea. Issue #149 workaround. The mouseleave event does not
+         * always fire.
+         *
+         * @private
+         * @function Highcharts.Pointer#onDocumentMouseMove
+         *
+         * @param {global.MouseEvent} e
+         *
+         * @return {void}
+         */
+        Pointer.prototype.onDocumentMouseMove = function (e) {
+          var chart = this.chart;
+          var chartPosition = this.chartPosition;
+          var pEvt = this.normalize(e, chartPosition);
+          var tooltip = chart.tooltip;
+          // If we're outside, hide the tooltip
+          if (
+            chartPosition &&
+            (!tooltip || !tooltip.isStickyOnContact()) &&
+            !chart.isInsidePlot(
+              pEvt.chartX - chart.plotLeft,
+              pEvt.chartY - chart.plotTop
+            ) &&
+            !this.inClass(pEvt.target, "highcharts-tracker")
+          ) {
+            this.reset();
+          }
+        };
         /**
-         * The SVG value used for the `stroke-linecap` and `stroke-linejoin`
-         * of a line graph. Round means that lines are rounded in the ends and
-         * bends.
+         * @private
+         * @function Highcharts.Pointer#onDocumentMouseUp
+         *
+         * @param {global.MouseEvent} e
          *
-         * @type       {Highcharts.SeriesLinecapValue}
-         * @default    round
-         * @since      3.0.7
-         * @apioption  plotOptions.line.linecap
+         * @return {void}
          */
+        Pointer.prototype.onDocumentMouseUp = function (e) {
+          var chart = charts[pick(H.hoverChartIndex, -1)];
+          if (chart) {
+            chart.pointer.drop(e);
+          }
+        };
         /**
-         * A `line` series. If the [type](#series.line.type) option is not
-         * specified, it is inherited from [chart.type](#chart.type).
+         * Handle touch events with two touches
          *
-         * @extends   series,plotOptions.line
-         * @excluding dataParser,dataURL
-         * @product   highcharts highstock
-         * @apioption series.line
-         */
-        /**
-         * An array of data points for the series. For the `line` series type,
-         * points can be given in the following ways:
-         *
-         * 1. An array of numerical values. In this case, the numerical values will be
-         *    interpreted as `y` options. The `x` values will be automatically
-         *    calculated, either starting at 0 and incremented by 1, or from
-         *    `pointStart` and `pointInterval` given in the series options. If the axis
-         *    has categories, these will be used. Example:
-         *    ```js
-         *    data: [0, 5, 3, 5]
-         *    ```
-         *
-         * 2. An array of arrays with 2 values. In this case, the values correspond to
-         *    `x,y`. If the first value is a string, it is applied as the name of the
-         *    point, and the `x` value is inferred.
-         *    ```js
-         *    data: [
-         *        [0, 1],
-         *        [1, 2],
-         *        [2, 8]
-         *    ]
-         *    ```
-         *
-         * 3. An array of objects with named values. The following snippet shows only a
-         *    few settings, see the complete options set below. If the total number of
-         *    data points exceeds the series'
-         *    [turboThreshold](#series.line.turboThreshold),
-         *    this option is not available.
-         *    ```js
-         *    data: [{
-         *        x: 1,
-         *        y: 9,
-         *        name: "Point2",
-         *        color: "#00FF00"
-         *    }, {
-         *        x: 1,
-         *        y: 6,
-         *        name: "Point1",
-         *        color: "#FF00FF"
-         *    }]
-         *    ```
-         *
-         * **Note:** In TypeScript you have to extend `PointOptionsObject` with an
-         * additional declaration to allow custom data types:
-         * ```ts
-         * declare module `highcharts` {
-         *   interface PointOptionsObject {
-         *     custom: Record<string, (boolean|number|string)>;
-         *   }
-         * }
-         * ```
+         * @private
+         * @function Highcharts.Pointer#pinch
          *
-         * @sample {highcharts} highcharts/chart/reflow-true/
-         *         Numerical values
-         * @sample {highcharts} highcharts/series/data-array-of-arrays/
-         *         Arrays of numeric x and y
-         * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
-         *         Arrays of datetime x and y
-         * @sample {highcharts} highcharts/series/data-array-of-name-value/
-         *         Arrays of point.name and y
-         * @sample {highcharts} highcharts/series/data-array-of-objects/
-         *         Config objects
+         * @param {Highcharts.PointerEventObject} e
          *
-         * @declare   Highcharts.PointOptionsObject
-         * @type      {Array<number|Array<(number|string),(number|null)>|null|*>}
-         * @apioption series.line.data
+         * @return {void}
          */
+        Pointer.prototype.pinch = function (e) {
+          var self = this,
+            chart = self.chart,
+            pinchDown = self.pinchDown,
+            touches = e.touches || [],
+            touchesLength = touches.length,
+            lastValidTouch = self.lastValidTouch,
+            hasZoom = self.hasZoom,
+            selectionMarker = self.selectionMarker,
+            transform = {},
+            fireClickEvent =
+              touchesLength === 1 &&
+              ((self.inClass(e.target, "highcharts-tracker") &&
+                chart.runTrackerClick) ||
+                self.runChartClick),
+            clip = {};
+          // Don't initiate panning until the user has pinched. This prevents us
+          // from blocking page scrolling as users scroll down a long page
+          // (#4210).
+          if (touchesLength > 1) {
+            self.initiated = true;
+          }
+          // On touch devices, only proceed to trigger click if a handler is
+          // defined
+          if (
+            hasZoom &&
+            self.initiated &&
+            !fireClickEvent &&
+            e.cancelable !== false
+          ) {
+            e.preventDefault();
+          }
+          // Normalize each touch
+          [].map.call(touches, function (e) {
+            return self.normalize(e);
+          });
+          // Register the touch start position
+          if (e.type === "touchstart") {
+            [].forEach.call(touches, function (e, i) {
+              pinchDown[i] = { chartX: e.chartX, chartY: e.chartY };
+            });
+            lastValidTouch.x = [
+              pinchDown[0].chartX,
+              pinchDown[1] && pinchDown[1].chartX,
+            ];
+            lastValidTouch.y = [
+              pinchDown[0].chartY,
+              pinchDown[1] && pinchDown[1].chartY,
+            ];
+            // Identify the data bounds in pixels
+            chart.axes.forEach(function (axis) {
+              if (axis.zoomEnabled) {
+                var bounds = chart.bounds[axis.horiz ? "h" : "v"],
+                  minPixelPadding = axis.minPixelPadding,
+                  min = axis.toPixels(
+                    Math.min(pick(axis.options.min, axis.dataMin), axis.dataMin)
+                  ),
+                  max = axis.toPixels(
+                    Math.max(pick(axis.options.max, axis.dataMax), axis.dataMax)
+                  ),
+                  absMin = Math.min(min, max),
+                  absMax = Math.max(min, max);
+                // Store the bounds for use in the touchmove handler
+                bounds.min = Math.min(axis.pos, absMin - minPixelPadding);
+                bounds.max = Math.max(
+                  axis.pos + axis.len,
+                  absMax + minPixelPadding
+                );
+              }
+            });
+            self.res = true; // reset on next move
+            // Optionally move the tooltip on touchmove
+          } else if (self.followTouchMove && touchesLength === 1) {
+            this.runPointActions(self.normalize(e));
+            // Event type is touchmove, handle panning and pinching
+          } else if (pinchDown.length) {
+            // can be 0 when releasing, if touchend
+            // fires first
+            // Set the marker
+            if (!selectionMarker) {
+              self.selectionMarker = selectionMarker = extend(
+                {
+                  destroy: noop,
+                  touch: true,
+                },
+                chart.plotBox
+              );
+            }
+            self.pinchTranslate(
+              pinchDown,
+              touches,
+              transform,
+              selectionMarker,
+              clip,
+              lastValidTouch
+            );
+            self.hasPinched = hasZoom;
+            // Scale and translate the groups to provide visual feedback during
+            // pinching
+            self.scaleGroups(transform, clip);
+            if (self.res) {
+              self.res = false;
+              this.reset(false, 0);
+            }
+          }
+        };
         /**
-         * An additional, individual class name for the data point's graphic
-         * representation.
+         * Run translation operations
          *
-         * @type      {string}
-         * @since     5.0.0
-         * @product   highcharts gantt
-         * @apioption series.line.data.className
-         */
-        /**
-         * Individual color for the point. By default the color is pulled from
-         * the global `colors` array.
+         * @private
+         * @function Highcharts.Pointer#pinchTranslate
+         *
+         * @param {Array<*>} pinchDown
          *
-         * In styled mode, the `color` option doesn't take effect. Instead, use
-         * `colorIndex`.
+         * @param {Array<Highcharts.PointerEventObject>} touches
          *
-         * @sample {highcharts} highcharts/point/color/
-         *         Mark the highest point
+         * @param {*} transform
          *
-         * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-         * @product   highcharts highstock gantt
-         * @apioption series.line.data.color
+         * @param {*} selectionMarker
+         *
+         * @param {*} clip
+         *
+         * @param {*} lastValidTouch
+         *
+         * @return {void}
          */
+        Pointer.prototype.pinchTranslate = function (
+          pinchDown,
+          touches,
+          transform,
+          selectionMarker,
+          clip,
+          lastValidTouch
+        ) {
+          if (this.zoomHor) {
+            this.pinchTranslateDirection(
+              true,
+              pinchDown,
+              touches,
+              transform,
+              selectionMarker,
+              clip,
+              lastValidTouch
+            );
+          }
+          if (this.zoomVert) {
+            this.pinchTranslateDirection(
+              false,
+              pinchDown,
+              touches,
+              transform,
+              selectionMarker,
+              clip,
+              lastValidTouch
+            );
+          }
+        };
         /**
-         * A specific color index to use for the point, so its graphic representations
-         * are given the class name `highcharts-color-{n}`. In styled mode this will
-         * change the color of the graphic. In non-styled mode, the color by is set by
-         * the `fill` attribute, so the change in class name won't have a visual effect
-         * by default.
+         * Run translation operations for each direction (horizontal and vertical)
+         * independently.
          *
-         * @type      {number}
-         * @since     5.0.0
-         * @product   highcharts gantt
-         * @apioption series.line.data.colorIndex
+         * @private
+         * @function Highcharts.Pointer#pinchTranslateDirection
+         *
+         * @param {boolean} horiz
+         *
+         * @param {Array<*>} pinchDown
+         *
+         * @param {Array<Highcharts.PointerEventObject>} touches
+         *
+         * @param {*} transform
+         *
+         * @param {*} selectionMarker
+         *
+         * @param {*} clip
+         *
+         * @param {*} lastValidTouch
+         *
+         * @param {number|undefined} [forcedScale=1]
+         *
+         * @return {void}
          */
+        Pointer.prototype.pinchTranslateDirection = function (
+          horiz,
+          pinchDown,
+          touches,
+          transform,
+          selectionMarker,
+          clip,
+          lastValidTouch,
+          forcedScale
+        ) {
+          var chart = this.chart,
+            xy = horiz ? "x" : "y",
+            XY = horiz ? "X" : "Y",
+            sChartXY = "chart" + XY,
+            wh = horiz ? "width" : "height",
+            plotLeftTop = chart["plot" + (horiz ? "Left" : "Top")],
+            selectionWH,
+            selectionXY,
+            clipXY,
+            scale = forcedScale || 1,
+            inverted = chart.inverted,
+            bounds = chart.bounds[horiz ? "h" : "v"],
+            singleTouch = pinchDown.length === 1,
+            touch0Start = pinchDown[0][sChartXY],
+            touch0Now = touches[0][sChartXY],
+            touch1Start = !singleTouch && pinchDown[1][sChartXY],
+            touch1Now = !singleTouch && touches[1][sChartXY],
+            outOfBounds,
+            transformScale,
+            scaleKey,
+            setScale = function () {
+              // Don't zoom if fingers are too close on this axis
+              if (
+                typeof touch1Now === "number" &&
+                Math.abs(touch0Start - touch1Start) > 20
+              ) {
+                scale =
+                  forcedScale ||
+                  Math.abs(touch0Now - touch1Now) /
+                    Math.abs(touch0Start - touch1Start);
+              }
+              clipXY = (plotLeftTop - touch0Now) / scale + touch0Start;
+              selectionWH =
+                chart["plot" + (horiz ? "Width" : "Height")] / scale;
+            };
+          // Set the scale, first pass
+          setScale();
+          // The clip position (x or y) is altered if out of bounds, the selection
+          // position is not
+          selectionXY = clipXY;
+          // Out of bounds
+          if (selectionXY < bounds.min) {
+            selectionXY = bounds.min;
+            outOfBounds = true;
+          } else if (selectionXY + selectionWH > bounds.max) {
+            selectionXY = bounds.max - selectionWH;
+            outOfBounds = true;
+          }
+          // Is the chart dragged off its bounds, determined by dataMin and
+          // dataMax?
+          if (outOfBounds) {
+            // Modify the touchNow position in order to create an elastic drag
+            // movement. This indicates to the user that the chart is responsive
+            // but can't be dragged further.
+            touch0Now -= 0.8 * (touch0Now - lastValidTouch[xy][0]);
+            if (typeof touch1Now === "number") {
+              touch1Now -= 0.8 * (touch1Now - lastValidTouch[xy][1]);
+            }
+            // Set the scale, second pass to adapt to the modified touchNow
+            // positions
+            setScale();
+          } else {
+            lastValidTouch[xy] = [touch0Now, touch1Now];
+          }
+          // Set geometry for clipping, selection and transformation
+          if (!inverted) {
+            clip[xy] = clipXY - plotLeftTop;
+            clip[wh] = selectionWH;
+          }
+          scaleKey = inverted ? (horiz ? "scaleY" : "scaleX") : "scale" + XY;
+          transformScale = inverted ? 1 / scale : scale;
+          selectionMarker[wh] = selectionWH;
+          selectionMarker[xy] = selectionXY;
+          transform[scaleKey] = scale;
+          transform["translate" + XY] =
+            transformScale * plotLeftTop +
+            (touch0Now - transformScale * touch0Start);
+        };
         /**
-         * A reserved subspace to store options and values for customized functionality.
-         * Here you can add additional data for your own event callbacks and formatter
-         * callbacks.
+         * Reset the tracking by hiding the tooltip, the hover series state and the
+         * hover point
+         *
+         * @function Highcharts.Pointer#reset
+         *
+         * @param {boolean} [allowMove]
+         *        Instead of destroying the tooltip altogether, allow moving it if
+         *        possible.
          *
-         * @sample {highcharts} highcharts/point/custom/
-         *         Point and series with custom data
+         * @param {number} [delay]
          *
-         * @type      {Highcharts.Dictionary<*>}
-         * @apioption series.line.data.custom
+         * @return {void}
          */
+        Pointer.prototype.reset = function (allowMove, delay) {
+          var pointer = this,
+            chart = pointer.chart,
+            hoverSeries = chart.hoverSeries,
+            hoverPoint = chart.hoverPoint,
+            hoverPoints = chart.hoverPoints,
+            tooltip = chart.tooltip,
+            tooltipPoints =
+              tooltip && tooltip.shared ? hoverPoints : hoverPoint;
+          // Check if the points have moved outside the plot area (#1003, #4736,
+          // #5101)
+          if (allowMove && tooltipPoints) {
+            splat(tooltipPoints).forEach(function (point) {
+              if (
+                point.series.isCartesian &&
+                typeof point.plotX === "undefined"
+              ) {
+                allowMove = false;
+              }
+            });
+          }
+          // Just move the tooltip, #349
+          if (allowMove) {
+            if (tooltip && tooltipPoints && splat(tooltipPoints).length) {
+              tooltip.refresh(tooltipPoints);
+              if (tooltip.shared && hoverPoints) {
+                // #8284
+                hoverPoints.forEach(function (point) {
+                  point.setState(point.state, true);
+                  if (point.series.isCartesian) {
+                    if (point.series.xAxis.crosshair) {
+                      point.series.xAxis.drawCrosshair(null, point);
+                    }
+                    if (point.series.yAxis.crosshair) {
+                      point.series.yAxis.drawCrosshair(null, point);
+                    }
+                  }
+                });
+              } else if (hoverPoint) {
+                // #2500
+                hoverPoint.setState(hoverPoint.state, true);
+                chart.axes.forEach(function (axis) {
+                  if (axis.crosshair && hoverPoint.series[axis.coll] === axis) {
+                    axis.drawCrosshair(null, hoverPoint);
+                  }
+                });
+              }
+            }
+            // Full reset
+          } else {
+            if (hoverPoint) {
+              hoverPoint.onMouseOut();
+            }
+            if (hoverPoints) {
+              hoverPoints.forEach(function (point) {
+                point.setState();
+              });
+            }
+            if (hoverSeries) {
+              hoverSeries.onMouseOut();
+            }
+            if (tooltip) {
+              tooltip.hide(delay);
+            }
+            if (pointer.unDocMouseMove) {
+              pointer.unDocMouseMove = pointer.unDocMouseMove();
+            }
+            // Remove crosshairs
+            chart.axes.forEach(function (axis) {
+              axis.hideCrosshair();
+            });
+            pointer.hoverX = chart.hoverPoints = chart.hoverPoint = null;
+          }
+        };
         /**
-         * Individual data label for each point. The options are the same as
-         * the ones for [plotOptions.series.dataLabels](
-         * #plotOptions.series.dataLabels).
+         * With line type charts with a single tracker, get the point closest to the
+         * mouse. Run Point.onMouseOver and display tooltip for the point or points.
+         *
+         * @private
+         * @function Highcharts.Pointer#runPointActions
          *
-         * @sample highcharts/point/datalabels/
-         *         Show a label for the last value
+         * @param {global.Event} e
          *
-         * @declare   Highcharts.DataLabelsOptions
-         * @extends   plotOptions.line.dataLabels
-         * @product   highcharts highstock gantt
-         * @apioption series.line.data.dataLabels
-         */
+         * @param {Highcharts.PointerEventObject} [p]
+         *
+         * @return {void}
+         *
+         * @fires Highcharts.Point#event:mouseOut
+         * @fires Highcharts.Point#event:mouseOver
+         */
+        Pointer.prototype.runPointActions = function (e, p) {
+          var pointer = this,
+            chart = pointer.chart,
+            series = chart.series,
+            tooltip =
+              chart.tooltip && chart.tooltip.options.enabled
+                ? chart.tooltip
+                : void 0,
+            shared = tooltip ? tooltip.shared : false,
+            hoverPoint = p || chart.hoverPoint,
+            hoverSeries =
+              (hoverPoint && hoverPoint.series) || chart.hoverSeries,
+            // onMouseOver or already hovering a series with directTouch
+            isDirectTouch =
+              (!e || e.type !== "touchmove") &&
+              (!!p ||
+                (hoverSeries &&
+                  hoverSeries.directTouch &&
+                  pointer.isDirectTouch)),
+            hoverData = this.getHoverData(
+              hoverPoint,
+              hoverSeries,
+              series,
+              isDirectTouch,
+              shared,
+              e
+            ),
+            useSharedTooltip,
+            followPointer,
+            anchor,
+            points;
+          // Update variables from hoverData.
+          hoverPoint = hoverData.hoverPoint;
+          points = hoverData.hoverPoints;
+          hoverSeries = hoverData.hoverSeries;
+          followPointer =
+            hoverSeries && hoverSeries.tooltipOptions.followPointer;
+          useSharedTooltip =
+            shared && hoverSeries && !hoverSeries.noSharedTooltip;
+          // Refresh tooltip for kdpoint if new hover point or tooltip was hidden
+          // #3926, #4200
+          if (
+            hoverPoint &&
+            // !(hoverSeries && hoverSeries.directTouch) &&
+            (hoverPoint !== chart.hoverPoint || (tooltip && tooltip.isHidden))
+          ) {
+            (chart.hoverPoints || []).forEach(function (p) {
+              if (points.indexOf(p) === -1) {
+                p.setState();
+              }
+            });
+            // Set normal state to previous series
+            if (chart.hoverSeries !== hoverSeries) {
+              hoverSeries.onMouseOver();
+            }
+            pointer.applyInactiveState(points);
+            // Do mouseover on all points (#3919, #3985, #4410, #5622)
+            (points || []).forEach(function (p) {
+              p.setState("hover");
+            });
+            // If tracking is on series in stead of on each point,
+            // fire mouseOver on hover point. // #4448
+            if (chart.hoverPoint) {
+              chart.hoverPoint.firePointEvent("mouseOut");
+            }
+            // Hover point may have been destroyed in the event handlers (#7127)
+            if (!hoverPoint.series) {
+              return;
+            }
+            /**
+             * Contains all hovered points.
+             *
+             * @name Highcharts.Chart#hoverPoints
+             * @type {Array<Highcharts.Point>|null}
+             */
+            chart.hoverPoints = points;
+            /**
+             * Contains the original hovered point.
+             *
+             * @name Highcharts.Chart#hoverPoint
+             * @type {Highcharts.Point|null}
+             */
+            chart.hoverPoint = hoverPoint;
+            /**
+             * Hover state should not be lost when axis is updated (#12569)
+             * Axis.update runs pointer.reset which uses chart.hoverPoint.state
+             * to apply state which does not exist in hoverPoint yet.
+             * The mouseOver event should be triggered when hoverPoint
+             * is correct.
+             */
+            hoverPoint.firePointEvent("mouseOver");
+            // Draw tooltip if necessary
+            if (tooltip) {
+              tooltip.refresh(useSharedTooltip ? points : hoverPoint, e);
+            }
+            // Update positions (regardless of kdpoint or hoverPoint)
+          } else if (followPointer && tooltip && !tooltip.isHidden) {
+            anchor = tooltip.getAnchor([{}], e);
+            tooltip.updatePosition({ plotX: anchor[0], plotY: anchor[1] });
+          }
+          // Start the event listener to pick up the tooltip and crosshairs
+          if (!pointer.unDocMouseMove) {
+            pointer.unDocMouseMove = addEvent(
+              chart.container.ownerDocument,
+              "mousemove",
+              function (e) {
+                var chart = charts[H.hoverChartIndex];
+                if (chart) {
+                  chart.pointer.onDocumentMouseMove(e);
+                }
+              }
+            );
+          }
+          // Issues related to crosshair #4927, #5269 #5066, #5658
+          chart.axes.forEach(function drawAxisCrosshair(axis) {
+            var snap = pick((axis.crosshair || {}).snap, true);
+            var point;
+            if (snap) {
+              point = chart.hoverPoint; // #13002
+              if (!point || point.series[axis.coll] !== axis) {
+                point = find(points, function (p) {
+                  return p.series[axis.coll] === axis;
+                });
+              }
+            }
+            // Axis has snapping crosshairs, and one of the hover points belongs
+            // to axis. Always call drawCrosshair when it is not snap.
+            if (point || !snap) {
+              axis.drawCrosshair(e, point);
+              // Axis has snapping crosshairs, but no hover point belongs to axis
+            } else {
+              axis.hideCrosshair();
+            }
+          });
+        };
         /**
-         * A description of the point to add to the screen reader information
-         * about the point.
+         * Scale series groups to a certain scale and translation.
          *
-         * @type      {string}
-         * @since     5.0.0
-         * @requires  modules/accessibility
-         * @apioption series.line.data.description
+         * @private
+         * @function Highcharts.Pointer#scaleGroups
+         *
+         * @param {Highcharts.SeriesPlotBoxObject} [attribs]
+         *
+         * @param {boolean} [clip]
+         *
+         * @return {void}
          */
+        Pointer.prototype.scaleGroups = function (attribs, clip) {
+          var chart = this.chart,
+            seriesAttribs;
+          // Scale each series
+          chart.series.forEach(function (series) {
+            seriesAttribs = attribs || series.getPlotBox(); // #1701
+            if (series.xAxis && series.xAxis.zoomEnabled && series.group) {
+              series.group.attr(seriesAttribs);
+              if (series.markerGroup) {
+                series.markerGroup.attr(seriesAttribs);
+                series.markerGroup.clip(clip ? chart.clipRect : null);
+              }
+              if (series.dataLabelsGroup) {
+                series.dataLabelsGroup.attr(seriesAttribs);
+              }
+            }
+          });
+          // Clip
+          chart.clipRect.attr(clip || chart.clipBox);
+        };
         /**
-         * An id for the point. This can be used after render time to get a
-         * pointer to the point object through `chart.get()`.
+         * Set the JS DOM events on the container and document. This method should
+         * contain a one-to-one assignment between methods and their handlers. Any
+         * advanced logic should be moved to the handler reflecting the event's
+         * name.
          *
-         * @sample {highcharts} highcharts/point/id/
-         *         Remove an id'd point
+         * @private
+         * @function Highcharts.Pointer#setDOMEvents
          *
-         * @type      {string}
-         * @since     1.2.0
-         * @product   highcharts highstock gantt
-         * @apioption series.line.data.id
+         * @return {void}
          */
+        Pointer.prototype.setDOMEvents = function () {
+          var container = this.chart.container,
+            ownerDoc = container.ownerDocument;
+          container.onmousedown = this.onContainerMouseDown.bind(this);
+          container.onmousemove = this.onContainerMouseMove.bind(this);
+          container.onclick = this.onContainerClick.bind(this);
+          this.unbindContainerMouseEnter = addEvent(
+            container,
+            "mouseenter",
+            this.onContainerMouseEnter.bind(this)
+          );
+          this.unbindContainerMouseLeave = addEvent(
+            container,
+            "mouseleave",
+            this.onContainerMouseLeave.bind(this)
+          );
+          if (!H.unbindDocumentMouseUp) {
+            H.unbindDocumentMouseUp = addEvent(
+              ownerDoc,
+              "mouseup",
+              this.onDocumentMouseUp.bind(this)
+            );
+          }
+          if (H.hasTouch) {
+            addEvent(
+              container,
+              "touchstart",
+              this.onContainerTouchStart.bind(this)
+            );
+            addEvent(
+              container,
+              "touchmove",
+              this.onContainerTouchMove.bind(this)
+            );
+            if (!H.unbindDocumentTouchEnd) {
+              H.unbindDocumentTouchEnd = addEvent(
+                ownerDoc,
+                "touchend",
+                this.onDocumentTouchEnd.bind(this)
+              );
+            }
+          }
+        };
         /**
-         * The rank for this point's data label in case of collision. If two
-         * data labels are about to overlap, only the one with the highest `labelrank`
-         * will be drawn.
+         * Sets the index of the hovered chart and leaves the previous hovered
+         * chart, to reset states like tooltip.
          *
-         * @type      {number}
-         * @apioption series.line.data.labelrank
-         */
+         * @private
+         * @function Highcharts.Pointer#setHoverChartIndex
+         */
+        Pointer.prototype.setHoverChartIndex = function () {
+          var chart = this.chart;
+          var hoverChart = H.charts[pick(H.hoverChartIndex, -1)];
+          if (hoverChart && hoverChart !== chart) {
+            hoverChart.pointer.onContainerMouseLeave({ relatedTarget: true });
+          }
+          if (!hoverChart || !hoverChart.mouseIsDown) {
+            H.hoverChartIndex = chart.index;
+          }
+        };
         /**
-         * The name of the point as shown in the legend, tooltip, dataLabels, etc.
+         * General touch handler shared by touchstart and touchmove.
          *
-         * @see [xAxis.uniqueNames](#xAxis.uniqueNames)
+         * @private
+         * @function Highcharts.Pointer#touch
          *
-         * @sample {highcharts} highcharts/series/data-array-of-objects/
-         *         Point names
+         * @param {Highcharts.PointerEventObject} e
          *
-         * @type      {string}
-         * @apioption series.line.data.name
+         * @param {boolean} [start]
+         *
+         * @return {void}
          */
+        Pointer.prototype.touch = function (e, start) {
+          var chart = this.chart,
+            hasMoved,
+            pinchDown,
+            isInside;
+          this.setHoverChartIndex();
+          if (e.touches.length === 1) {
+            e = this.normalize(e);
+            isInside = chart.isInsidePlot(
+              e.chartX - chart.plotLeft,
+              e.chartY - chart.plotTop
+            );
+            if (isInside && !chart.openMenu) {
+              // Run mouse events and display tooltip etc
+              if (start) {
+                this.runPointActions(e);
+              }
+              // Android fires touchmove events after the touchstart even if
+              // the finger hasn't moved, or moved only a pixel or two. In iOS
+              // however, the touchmove doesn't fire unless the finger moves
+              // more than ~4px. So we emulate this behaviour in Android by
+              // checking how much it moved, and cancelling on small
+              // distances. #3450.
+              if (e.type === "touchmove") {
+                pinchDown = this.pinchDown;
+                hasMoved = pinchDown[0]
+                  ? Math.sqrt(
+                      // #5266
+                      Math.pow(pinchDown[0].chartX - e.chartX, 2) +
+                        Math.pow(pinchDown[0].chartY - e.chartY, 2)
+                    ) >= 4
+                  : false;
+              }
+              if (pick(hasMoved, true)) {
+                this.pinch(e);
+              }
+            } else if (start) {
+              // Hide the tooltip on touching outside the plot area (#1203)
+              this.reset();
+            }
+          } else if (e.touches.length === 2) {
+            this.pinch(e);
+          }
+        };
         /**
-         * Whether the data point is selected initially.
+         * Resolve the zoomType option, this is reset on all touch start and mouse
+         * down events.
          *
-         * @type      {boolean}
-         * @default   false
-         * @product   highcharts highstock gantt
-         * @apioption series.line.data.selected
-         */
+         * @private
+         * @function Highcharts.Pointer#zoomOption
+         *
+         * @param {global.Event} e
+         *        Event object.
+         *
+         * @param {void}
+         */
+        Pointer.prototype.zoomOption = function (e) {
+          var chart = this.chart,
+            options = chart.options.chart,
+            zoomType = options.zoomType || "",
+            inverted = chart.inverted,
+            zoomX,
+            zoomY;
+          // Look for the pinchType option
+          if (/touch/.test(e.type)) {
+            zoomType = pick(options.pinchType, zoomType);
+          }
+          this.zoomX = zoomX = /x/.test(zoomType);
+          this.zoomY = zoomY = /y/.test(zoomType);
+          this.zoomHor = (zoomX && !inverted) || (zoomY && inverted);
+          this.zoomVert = (zoomY && !inverted) || (zoomX && inverted);
+          this.hasZoom = zoomX || zoomY;
+        };
+        return Pointer;
+      })();
+      H.Pointer = Pointer;
+
+      return Pointer;
+    }
+  );
+  _registerModule(
+    _modules,
+    "Core/MSPointer.js",
+    [
+      _modules["Core/Globals.js"],
+      _modules["Core/Pointer.js"],
+      _modules["Core/Utilities.js"],
+    ],
+    function (H, Pointer, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      var __extends =
+        (this && this.__extends) ||
+        (function () {
+          var extendStatics = function (d, b) {
+            extendStatics =
+              Object.setPrototypeOf ||
+              ({ __proto__: [] } instanceof Array &&
+                function (d, b) {
+                  d.__proto__ = b;
+                }) ||
+              function (d, b) {
+                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+              };
+            return extendStatics(d, b);
+          };
+          return function (d, b) {
+            extendStatics(d, b);
+            function __() {
+              this.constructor = d;
+            }
+            d.prototype =
+              b === null
+                ? Object.create(b)
+                : ((__.prototype = b.prototype), new __());
+          };
+        })();
+      var charts = H.charts,
+        doc = H.doc,
+        noop = H.noop,
+        win = H.win;
+      var addEvent = U.addEvent,
+        css = U.css,
+        objectEach = U.objectEach,
+        removeEvent = U.removeEvent;
+      /* globals MSPointerEvent, PointerEvent */
+      // The touches object keeps track of the points being touched at all times
+      var touches = {};
+      var hasPointerEvent = !!win.PointerEvent;
+      /* eslint-disable valid-jsdoc */
+      /** @private */
+      function getWebkitTouches() {
+        var fake = [];
+        fake.item = function (i) {
+          return this[i];
+        };
+        objectEach(touches, function (touch) {
+          fake.push({
+            pageX: touch.pageX,
+            pageY: touch.pageY,
+            target: touch.target,
+          });
+        });
+        return fake;
+      }
+      /** @private */
+      function translateMSPointer(e, method, wktype, func) {
+        var p;
+        if (
+          (e.pointerType === "touch" ||
+            e.pointerType === e.MSPOINTER_TYPE_TOUCH) &&
+          charts[H.hoverChartIndex]
+        ) {
+          func(e);
+          p = charts[H.hoverChartIndex].pointer;
+          p[method]({
+            type: wktype,
+            target: e.currentTarget,
+            preventDefault: noop,
+            touches: getWebkitTouches(),
+          });
+        }
+      }
+      /** @private */
+      var MSPointer = /** @class */ (function (_super) {
+        __extends(MSPointer, _super);
+        function MSPointer() {
+          return (_super !== null && _super.apply(this, arguments)) || this;
+        }
+        /* *
+         *
+         *  Functions
+         *
+         * */
         /**
-         * The x value of the point. For datetime axes, the X value is the timestamp
-         * in milliseconds since 1970.
+         * Add or remove the MS Pointer specific events
          *
-         * @type      {number}
-         * @product   highcharts highstock
-         * @apioption series.line.data.x
+         * @private
+         * @function Highcharts.Pointer#batchMSEvents
+         *
+         * @param {Function} fn
+         *
+         * @return {void}
          */
+        MSPointer.prototype.batchMSEvents = function (fn) {
+          fn(
+            this.chart.container,
+            hasPointerEvent ? "pointerdown" : "MSPointerDown",
+            this.onContainerPointerDown
+          );
+          fn(
+            this.chart.container,
+            hasPointerEvent ? "pointermove" : "MSPointerMove",
+            this.onContainerPointerMove
+          );
+          fn(
+            doc,
+            hasPointerEvent ? "pointerup" : "MSPointerUp",
+            this.onDocumentPointerUp
+          );
+        };
+        // Destroy MS events also
+        MSPointer.prototype.destroy = function () {
+          this.batchMSEvents(removeEvent);
+          _super.prototype.destroy.call(this);
+        };
+        // Disable default IE actions for pinch and such on chart element
+        MSPointer.prototype.init = function (chart, options) {
+          _super.prototype.init.call(this, chart, options);
+          if (this.hasZoom) {
+            // #4014
+            css(chart.container, {
+              "-ms-touch-action": "none",
+              "touch-action": "none",
+            });
+          }
+        };
         /**
-         * The y value of the point.
+         * @private
+         * @function Highcharts.Pointer#onContainerPointerDown
          *
-         * @type      {number|null}
-         * @product   highcharts highstock
-         * @apioption series.line.data.y
+         * @param {Highcharts.PointerEventObject} e
+         *
+         * @return {void}
          */
+        MSPointer.prototype.onContainerPointerDown = function (e) {
+          translateMSPointer(
+            e,
+            "onContainerTouchStart",
+            "touchstart",
+            function (e) {
+              touches[e.pointerId] = {
+                pageX: e.pageX,
+                pageY: e.pageY,
+                target: e.currentTarget,
+              };
+            }
+          );
+        };
         /**
-         * The individual point events.
+         * @private
+         * @function Highcharts.Pointer#onContainerPointerMove
+         *
+         * @param {Highcharts.PointerEventObject} e
          *
-         * @extends   plotOptions.series.point.events
-         * @product   highcharts highstock gantt
-         * @apioption series.line.data.events
+         * @return {void}
          */
+        MSPointer.prototype.onContainerPointerMove = function (e) {
+          translateMSPointer(
+            e,
+            "onContainerTouchMove",
+            "touchmove",
+            function (e) {
+              touches[e.pointerId] = { pageX: e.pageX, pageY: e.pageY };
+              if (!touches[e.pointerId].target) {
+                touches[e.pointerId].target = e.currentTarget;
+              }
+            }
+          );
+        };
         /**
-         * Options for the point markers of line-like series.
+         * @private
+         * @function Highcharts.Pointer#onDocumentPointerUp
          *
-         * @declare   Highcharts.PointMarkerOptionsObject
-         * @extends   plotOptions.series.marker
-         * @product   highcharts highstock
-         * @apioption series.line.data.marker
+         * @param {Highcharts.PointerEventObject} e
+         *
+         * @return {void}
          */
-        ''; // include precedent doclets in transpilat
+        MSPointer.prototype.onDocumentPointerUp = function (e) {
+          translateMSPointer(e, "onDocumentTouchEnd", "touchend", function (e) {
+            delete touches[e.pointerId];
+          });
+        };
+        // Add IE specific touch events to chart
+        MSPointer.prototype.setDOMEvents = function () {
+          _super.prototype.setDOMEvents.call(this);
+          if (this.hasZoom || this.followTouchMove) {
+            this.batchMSEvents(addEvent);
+          }
+        };
+        return MSPointer;
+      })(Pointer);
 
-        return CartesianSeries;
-    });
-    _registerModule(_modules, 'Series/LineSeries.js', [_modules['Core/Series/CartesianSeries.js'], _modules['Core/Globals.js']], function (CartesianSeries, H) {
+      return MSPointer;
+    }
+  );
+  _registerModule(
+    _modules,
+    "Core/Legend.js",
+    [
+      _modules["Core/Animation/AnimationUtilities.js"],
+      _modules["Core/Globals.js"],
+      _modules["Core/Utilities.js"],
+    ],
+    function (A, H, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      var animObject = A.animObject,
+        setAnimation = A.setAnimation;
+      /**
+       * Gets fired when the legend item belonging to a point is clicked. The default
+       * action is to toggle the visibility of the point. This can be prevented by
+       * returning `false` or calling `event.preventDefault()`.
+       *
+       * @callback Highcharts.PointLegendItemClickCallbackFunction
+       *
+       * @param {Highcharts.Point} this
+       *        The point on which the event occured.
+       *
+       * @param {Highcharts.PointLegendItemClickEventObject} event
+       *        The event that occured.
+       */
+      /**
+       * Information about the legend click event.
+       *
+       * @interface Highcharts.PointLegendItemClickEventObject
+       */ /**
+       * Related browser event.
+       * @name Highcharts.PointLegendItemClickEventObject#browserEvent
+       * @type {Highcharts.PointerEvent}
+       */ /**
+       * Prevent the default action of toggle the visibility of the point.
+       * @name Highcharts.PointLegendItemClickEventObject#preventDefault
+       * @type {Function}
+       */ /**
+       * Related point.
+       * @name Highcharts.PointLegendItemClickEventObject#target
+       * @type {Highcharts.Point}
+       */ /**
+       * Event type.
+       * @name Highcharts.PointLegendItemClickEventObject#type
+       * @type {"legendItemClick"}
+       */
+      /**
+       * Gets fired when the legend item belonging to a series is clicked. The default
+       * action is to toggle the visibility of the series. This can be prevented by
+       * returning `false` or calling `event.preventDefault()`.
+       *
+       * @callback Highcharts.SeriesLegendItemClickCallbackFunction
+       *
+       * @param {Highcharts.Series} this
+       *        The series where the event occured.
+       *
+       * @param {Highcharts.SeriesLegendItemClickEventObject} event
+       *        The event that occured.
+       */
+      /**
+       * Information about the legend click event.
+       *
+       * @interface Highcharts.SeriesLegendItemClickEventObject
+       */ /**
+       * Related browser event.
+       * @name Highcharts.SeriesLegendItemClickEventObject#browserEvent
+       * @type {Highcharts.PointerEvent}
+       */ /**
+       * Prevent the default action of toggle the visibility of the series.
+       * @name Highcharts.SeriesLegendItemClickEventObject#preventDefault
+       * @type {Function}
+       */ /**
+       * Related series.
+       * @name Highcharts.SeriesLegendItemClickEventObject#target
+       * @type {Highcharts.Series}
+       */ /**
+       * Event type.
+       * @name Highcharts.SeriesLegendItemClickEventObject#type
+       * @type {"legendItemClick"}
+       */
+      var addEvent = U.addEvent,
+        css = U.css,
+        defined = U.defined,
+        discardElement = U.discardElement,
+        find = U.find,
+        fireEvent = U.fireEvent,
+        format = U.format,
+        isNumber = U.isNumber,
+        merge = U.merge,
+        pick = U.pick,
+        relativeLength = U.relativeLength,
+        stableSort = U.stableSort,
+        syncTimeout = U.syncTimeout,
+        wrap = U.wrap;
+      var isFirefox = H.isFirefox,
+        marginNames = H.marginNames,
+        win = H.win;
+      /* eslint-disable no-invalid-this, valid-jsdoc */
+      /**
+       * The overview of the chart's series. The legend object is instanciated
+       * internally in the chart constructor, and is available from the `chart.legend`
+       * property. Each chart has only one legend.
+       *
+       * @class
+       * @name Highcharts.Legend
+       *
+       * @param {Highcharts.Chart} chart
+       * The chart instance.
+       *
+       * @param {Highcharts.LegendOptions} options
+       * Legend options.
+       */
+      var Legend = /** @class */ (function () {
         /* *
          *
-         *  (c) 2010-2020 Torstein Honsi
-         *
-         *  License: www.highcharts.com/license
-         *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+         *  Constructors
          *
          * */
-        H.Series = CartesianSeries; // backwards compatibility
-
-        return H.Series;
-    });
-    _registerModule(_modules, 'Extensions/Stacking.js', [_modules['Core/Axis/Axis.js'], _modules['Core/Chart/Chart.js'], _modules['Core/Globals.js'], _modules['Core/Axis/StackingAxis.js'], _modules['Core/Utilities.js']], function (Axis, Chart, H, StackingAxis, U) {
+        function Legend(chart, options) {
+          /* *
+           *
+           *  Properties
+           *
+           * */
+          this.allItems = [];
+          this.box = void 0;
+          this.contentGroup = void 0;
+          this.display = false;
+          this.group = void 0;
+          this.initialItemY = 0;
+          this.itemHeight = 0;
+          this.itemMarginBottom = 0;
+          this.itemMarginTop = 0;
+          this.itemX = 0;
+          this.itemY = 0;
+          this.lastItemY = 0;
+          this.lastLineHeight = 0;
+          this.legendHeight = 0;
+          this.legendWidth = 0;
+          this.maxItemWidth = 0;
+          this.maxLegendWidth = 0;
+          this.offsetWidth = 0;
+          this.options = {};
+          this.padding = 0;
+          this.pages = [];
+          this.proximate = false;
+          this.scrollGroup = void 0;
+          this.symbolHeight = 0;
+          this.symbolWidth = 0;
+          this.titleHeight = 0;
+          this.totalItemWidth = 0;
+          this.widthOption = 0;
+          this.chart = chart;
+          this.init(chart, options);
+        }
         /* *
          *
-         *  (c) 2010-2020 Torstein Honsi
+         *  Functions
          *
-         *  License: www.highcharts.com/license
+         * */
+        /**
+         * Initialize the legend.
          *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+         * @private
+         * @function Highcharts.Legend#init
          *
-         * */
-        var correctFloat = U.correctFloat,
-            defined = U.defined,
-            destroyObjectProperties = U.destroyObjectProperties,
-            format = U.format,
-            isNumber = U.isNumber,
-            pick = U.pick;
+         * @param {Highcharts.Chart} chart
+         * The chart instance.
+         *
+         * @param {Highcharts.LegendOptions} options
+         * Legend options.
+         */
+        Legend.prototype.init = function (chart, options) {
+          /**
+           * Chart of this legend.
+           *
+           * @readonly
+           * @name Highcharts.Legend#chart
+           * @type {Highcharts.Chart}
+           */
+          this.chart = chart;
+          this.setOptions(options);
+          if (options.enabled) {
+            // Render it
+            this.render();
+            // move checkboxes
+            addEvent(this.chart, "endResize", function () {
+              this.legend.positionCheckboxes();
+            });
+            if (this.proximate) {
+              this.unchartrender = addEvent(this.chart, "render", function () {
+                this.legend.proximatePositions();
+                this.legend.positionItems();
+              });
+            } else if (this.unchartrender) {
+              this.unchartrender();
+            }
+          }
+        };
         /**
-         * Stack of data points
+         * @private
+         * @function Highcharts.Legend#setOptions
+         * @param {Highcharts.LegendOptions} options
+         */
+        Legend.prototype.setOptions = function (options) {
+          var padding = pick(options.padding, 8);
+          /**
+           * Legend options.
+           *
+           * @readonly
+           * @name Highcharts.Legend#options
+           * @type {Highcharts.LegendOptions}
+           */
+          this.options = options;
+          if (!this.chart.styledMode) {
+            this.itemStyle = options.itemStyle;
+            this.itemHiddenStyle = merge(
+              this.itemStyle,
+              options.itemHiddenStyle
+            );
+          }
+          this.itemMarginTop = options.itemMarginTop || 0;
+          this.itemMarginBottom = options.itemMarginBottom || 0;
+          this.padding = padding;
+          this.initialItemY = padding - 5; // 5 is pixels above the text
+          this.symbolWidth = pick(options.symbolWidth, 16);
+          this.pages = [];
+          this.proximate =
+            options.layout === "proximate" && !this.chart.inverted;
+          this.baseline = void 0; // #12705: baseline has to be reset on every update
+        };
+        /**
+         * Update the legend with new options. Equivalent to running `chart.update`
+         * with a legend configuration option.
          *
-         * @product highcharts
+         * @sample highcharts/legend/legend-update/
+         *         Legend update
          *
-         * @interface Highcharts.StackItemObject
-         */ /**
-        * Alignment settings
-        * @name Highcharts.StackItemObject#alignOptions
-        * @type {Highcharts.AlignObject}
-        */ /**
-        * Related axis
-        * @name Highcharts.StackItemObject#axis
-        * @type {Highcharts.Axis}
-        */ /**
-        * Cumulative value of the stacked data points
-        * @name Highcharts.StackItemObject#cumulative
-        * @type {number}
-        */ /**
-        * True if on the negative side
-        * @name Highcharts.StackItemObject#isNegative
-        * @type {boolean}
-        */ /**
-        * Related SVG element
-        * @name Highcharts.StackItemObject#label
-        * @type {Highcharts.SVGElement}
-        */ /**
-        * Related stack options
-        * @name Highcharts.StackItemObject#options
-        * @type {Highcharts.YAxisStackLabelsOptions}
-        */ /**
-        * Total value of the stacked data points
-        * @name Highcharts.StackItemObject#total
-        * @type {number}
-        */ /**
-        * Shared x value of the stack
-        * @name Highcharts.StackItemObject#x
-        * @type {number}
-        */
-        ''; // detached doclets above
-        var Series = H.Series;
-        /* eslint-disable no-invalid-this, valid-jsdoc */
+         * @function Highcharts.Legend#update
+         *
+         * @param {Highcharts.LegendOptions} options
+         * Legend options.
+         *
+         * @param {boolean} [redraw=true]
+         * Whether to redraw the chart after the axis is altered. If doing more
+         * operations on the chart, it is a good idea to set redraw to false and
+         * call {@link Chart#redraw} after. Whether to redraw the chart.
+         *
+         * @fires Highcharts.Legends#event:afterUpdate
+         */
+        Legend.prototype.update = function (options, redraw) {
+          var chart = this.chart;
+          this.setOptions(merge(true, this.options, options));
+          this.destroy();
+          chart.isDirtyLegend = chart.isDirtyBox = true;
+          if (pick(redraw, true)) {
+            chart.redraw();
+          }
+          fireEvent(this, "afterUpdate");
+        };
         /**
-         * The class for stacks. Each stack, on a specific X value and either negative
-         * or positive, has its own stack item.
+         * Set the colors for the legend item.
          *
          * @private
-         * @class
-         * @name Highcharts.StackItem
-         * @param {Highcharts.Axis} axis
-         * @param {Highcharts.YAxisStackLabelsOptions} options
-         * @param {boolean} isNegative
-         * @param {number} x
-         * @param {Highcharts.OptionsStackingValue} [stackOption]
-         */
-        var StackItem = /** @class */ (function () {
-                function StackItem(axis, options, isNegative, x, stackOption) {
-                    var inverted = axis.chart.inverted;
-                this.axis = axis;
-                // Tells if the stack is negative
-                this.isNegative = isNegative;
-                // Save the options to be able to style the label
-                this.options = options = options || {};
-                // Save the x value to be able to position the label later
-                this.x = x;
-                // Initialize total value
-                this.total = null;
-                // This will keep each points' extremes stored by series.index and point
-                // index
-                this.points = {};
-                this.hasValidPoints = false;
-                // Save the stack option on the series configuration object,
-                // and whether to treat it as percent
-                this.stack = stackOption;
-                this.leftCliff = 0;
-                this.rightCliff = 0;
-                // The align options and text align varies on whether the stack is
-                // negative and if the chart is inverted or not.
-                // First test the user supplied value, then use the dynamic.
-                this.alignOptions = {
-                    align: options.align ||
-                        (inverted ? (isNegative ? 'left' : 'right') : 'center'),
-                    verticalAlign: options.verticalAlign ||
-                        (inverted ? 'middle' : (isNegative ? 'bottom' : 'top')),
-                    y: options.y,
-                    x: options.x
-                };
-                this.textAlign = options.textAlign ||
-                    (inverted ? (isNegative ? 'right' : 'left') : 'center');
+         * @function Highcharts.Legend#colorizeItem
+         * @param {Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series} item
+         *        A Series or Point instance
+         * @param {boolean} [visible=false]
+         *        Dimmed or colored
+         *
+         * @todo
+         * Make events official: Fires the event `afterColorizeItem`.
+         */
+        Legend.prototype.colorizeItem = function (item, visible) {
+          item.legendGroup[visible ? "removeClass" : "addClass"](
+            "highcharts-legend-item-hidden"
+          );
+          if (!this.chart.styledMode) {
+            var legend = this,
+              options = legend.options,
+              legendItem = item.legendItem,
+              legendLine = item.legendLine,
+              legendSymbol = item.legendSymbol,
+              hiddenColor = legend.itemHiddenStyle.color,
+              textColor = visible ? options.itemStyle.color : hiddenColor,
+              symbolColor = visible ? item.color || hiddenColor : hiddenColor,
+              markerOptions = item.options && item.options.marker,
+              symbolAttr = { fill: symbolColor };
+            if (legendItem) {
+              legendItem.css({
+                fill: textColor,
+                color: textColor, // #1553, oldIE
+              });
             }
-            /**
-             * @private
-             * @function Highcharts.StackItem#destroy
-             */
-            StackItem.prototype.destroy = function () {
-                destroyObjectProperties(this, this.axis);
-            };
-            /**
-             * Renders the stack total label and adds it to the stack label group.
-             *
-             * @private
-             * @function Highcharts.StackItem#render
-             * @param {Highcharts.SVGElement} group
-             */
-            StackItem.prototype.render = function (group) {
-                var chart = this.axis.chart,
-                    options = this.options,
-                    formatOption = options.format,
-                    attr = {},
-                    str = formatOption ? // format the text in the label
-                        format(formatOption,
-                    this,
-                    chart) :
-                        options.formatter.call(this);
-                // Change the text to reflect the new total and set visibility to hidden
-                // in case the serie is hidden
-                if (this.label) {
-                    this.label.attr({ text: str, visibility: 'hidden' });
-                }
-                else {
-                    // Create new label
-                    this.label = chart.renderer
-                        .label(str, null, null, options.shape, null, null, options.useHTML, false, 'stack-labels');
-                    attr = {
-                        r: options.borderRadius || 0,
-                        text: str,
-                        rotation: options.rotation,
-                        padding: pick(options.padding, 5),
-                        visibility: 'hidden' // hidden until setOffset is called
-                    };
-                    if (!chart.styledMode) {
-                        attr.fill = options.backgroundColor;
-                        attr.stroke = options.borderColor;
-                        attr['stroke-width'] = options.borderWidth;
-                        this.label.css(options.style);
-                    }
-                    this.label.attr(attr);
-                    if (!this.label.added) {
-                        this.label.add(group); // add to the labels-group
-                    }
-                }
-                // Rank it higher than data labels (#8742)
-                this.label.labelrank = chart.plotHeight;
-            };
-            /**
-             * Sets the offset that the stack has from the x value and repositions the
-             * label.
-             *
-             * @private
-             * @function Highcarts.StackItem#setOffset
-             * @param {number} xOffset
-             * @param {number} xWidth
-             * @param {number} [boxBottom]
-             * @param {number} [boxTop]
-             * @param {number} [defaultX]
-             */
-            StackItem.prototype.setOffset = function (xOffset, xWidth, boxBottom, boxTop, defaultX) {
-                var stackItem = this,
-                    axis = stackItem.axis,
-                    chart = axis.chart, 
-                    // stack value translated mapped to chart coordinates
-                    y = axis.translate(axis.stacking.usePercentage ?
-                        100 :
-                        (boxTop ?
-                            boxTop :
-                            stackItem.total), 0, 0, 0, 1),
-                    yZero = axis.translate(boxBottom ? boxBottom : 0), // stack origin
-                    // stack height:
-                    h = defined(y) && Math.abs(y - yZero), 
-                    // x position:
-                    x = pick(defaultX,
-                    chart.xAxis[0].translate(stackItem.x)) +
-                        xOffset,
-                    stackBox = defined(y) && stackItem.getStackBox(chart,
-                    stackItem,
-                    x,
-                    y,
-                    xWidth,
-                    h,
-                    axis),
-                    label = stackItem.label,
-                    isNegative = stackItem.isNegative,
-                    isJustify = pick(stackItem.options.overflow, 'justify') === 'justify',
-                    textAlign = stackItem.textAlign,
-                    visible;
-                if (label && stackBox) {
-                    var bBox = label.getBBox(),
-                        padding = label.padding,
-                        boxOffsetX,
-                        boxOffsetY;
-                    if (textAlign === 'left') {
-                        boxOffsetX = chart.inverted ? -padding : padding;
-                    }
-                    else if (textAlign === 'right') {
-                        boxOffsetX = bBox.width;
-                    }
-                    else {
-                        if (chart.inverted && textAlign === 'center') {
-                            boxOffsetX = bBox.width / 2;
-                        }
-                        else {
-                            boxOffsetX = chart.inverted ?
-                                (isNegative ? bBox.width + padding : -padding) : bBox.width / 2;
-                        }
-                    }
-                    boxOffsetY = chart.inverted ?
-                        bBox.height / 2 : (isNegative ? -padding : bBox.height);
-                    // Reset alignOptions property after justify #12337
-                    stackItem.alignOptions.x = pick(stackItem.options.x, 0);
-                    stackItem.alignOptions.y = pick(stackItem.options.y, 0);
-                    // Set the stackBox position
-                    stackBox.x -= boxOffsetX;
-                    stackBox.y -= boxOffsetY;
-                    // Align the label to the box
-                    label.align(stackItem.alignOptions, null, stackBox);
-                    // Check if label is inside the plotArea #12294
-                    if (chart.isInsidePlot(label.alignAttr.x + boxOffsetX - stackItem.alignOptions.x, label.alignAttr.y + boxOffsetY - stackItem.alignOptions.y)) {
-                        label.show();
-                    }
-                    else {
-                        // Move label away to avoid the overlapping issues
-                        label.alignAttr.y = -9999;
-                        isJustify = false;
-                    }
-                    if (isJustify) {
-                        // Justify stackLabel into the stackBox
-                        Series.prototype.justifyDataLabel.call(this.axis, label, stackItem.alignOptions, label.alignAttr, bBox, stackBox);
-                    }
-                    label.attr({
-                        x: label.alignAttr.x,
-                        y: label.alignAttr.y
-                    });
-                    if (pick(!isJustify && stackItem.options.crop, true)) {
-                        visible =
-                            isNumber(label.x) &&
-                                isNumber(label.y) &&
-                                chart.isInsidePlot(label.x - padding + label.width, label.y) &&
-                                chart.isInsidePlot(label.x + padding, label.y);
-                        if (!visible) {
-                            label.hide();
-                        }
-                    }
-                }
-            };
-            /**
-             * @private
-             * @function Highcharts.StackItem#getStackBox
-             *
-             * @param {Highcharts.Chart} chart
-             *
-             * @param {Highcharts.StackItem} stackItem
-             *
-             * @param {number} x
-             *
-             * @param {number} y
-             *
-             * @param {number} xWidth
-             *
-             * @param {number} h
-             *
-             * @param {Highcharts.Axis} axis
-             *
-             * @return {Highcharts.BBoxObject}
-             */
-            StackItem.prototype.getStackBox = function (chart, stackItem, x, y, xWidth, h, axis) {
-                var reversed = stackItem.axis.reversed,
-                    inverted = chart.inverted,
-                    axisPos = axis.height + axis.pos -
-                        (inverted ? chart.plotLeft : chart.plotTop),
-                    neg = (stackItem.isNegative && !reversed) ||
-                        (!stackItem.isNegative && reversed); // #4056
-                    return {
-                        x: inverted ? (neg ? y - axis.right : y - h + axis.pos - chart.plotLeft) :
-                            x + chart.xAxis[0].transB - chart.plotLeft,
-                        y: inverted ?
-                            axis.height - x - xWidth :
-                            (neg ?
-                                (axisPos - y - h) :
-                                axisPos - y),
-                        width: inverted ? h : xWidth,
-                        height: inverted ? xWidth : h
-                    };
-            };
-            return StackItem;
-        }());
+            if (legendLine) {
+              legendLine.attr({ stroke: symbolColor });
+            }
+            if (legendSymbol) {
+              // Apply marker options
+              if (markerOptions && legendSymbol.isMarker) {
+                // #585
+                symbolAttr = item.pointAttribs();
+                if (!visible) {
+                  // #6769
+                  symbolAttr.stroke = symbolAttr.fill = hiddenColor;
+                }
+              }
+              legendSymbol.attr(symbolAttr);
+            }
+          }
+          fireEvent(this, "afterColorizeItem", {
+            item: item,
+            visible: visible,
+          });
+        };
+        /**
+         * @private
+         * @function Highcharts.Legend#positionItems
+         */
+        Legend.prototype.positionItems = function () {
+          // Now that the legend width and height are established, put the items
+          // in the final position
+          this.allItems.forEach(this.positionItem, this);
+          if (!this.chart.isResizing) {
+            this.positionCheckboxes();
+          }
+        };
+        /**
+         * Position the legend item.
+         *
+         * @private
+         * @function Highcharts.Legend#positionItem
+         * @param {Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series} item
+         * The item to position
+         */
+        Legend.prototype.positionItem = function (item) {
+          var _this = this;
+          var legend = this,
+            options = legend.options,
+            symbolPadding = options.symbolPadding,
+            ltr = !options.rtl,
+            legendItemPos = item._legendItemPos,
+            itemX = legendItemPos[0],
+            itemY = legendItemPos[1],
+            checkbox = item.checkbox,
+            legendGroup = item.legendGroup;
+          if (legendGroup && legendGroup.element) {
+            var attribs = {
+              translateX: ltr
+                ? itemX
+                : legend.legendWidth - itemX - 2 * symbolPadding - 4,
+              translateY: itemY,
+            };
+            var complete = function () {
+              fireEvent(_this, "afterPositionItem", { item: item });
+            };
+            if (defined(legendGroup.translateY)) {
+              legendGroup.animate(attribs, void 0, complete);
+            } else {
+              legendGroup.attr(attribs);
+              complete();
+            }
+          }
+          if (checkbox) {
+            checkbox.x = itemX;
+            checkbox.y = itemY;
+          }
+        };
         /**
-         * Generate stacks for each series and calculate stacks total values
+         * Destroy a single legend item, used internally on removing series items.
          *
          * @private
-         * @function Highcharts.Chart#getStacks
-         */
-        Chart.prototype.getStacks = function () {
-            var chart = this,
-                inverted = chart.inverted;
-            // reset stacks for each yAxis
-            chart.yAxis.forEach(function (axis) {
-                if (axis.stacking && axis.stacking.stacks && axis.hasVisibleSeries) {
-                    axis.stacking.oldStacks = axis.stacking.stacks;
-                }
-            });
-            chart.series.forEach(function (series) {
-                var xAxisOptions = series.xAxis && series.xAxis.options || {};
-                if (series.options.stacking &&
-                    (series.visible === true ||
-                        chart.options.chart.ignoreHiddenSeries === false)) {
-                    series.stackKey = [
-                        series.type,
-                        pick(series.options.stack, ''),
-                        inverted ? xAxisOptions.top : xAxisOptions.left,
-                        inverted ? xAxisOptions.height : xAxisOptions.width
-                    ].join(',');
-                }
-            });
+         * @function Highcharts.Legend#destroyItem
+         * @param {Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series} item
+         * The item to remove
+         */
+        Legend.prototype.destroyItem = function (item) {
+          var checkbox = item.checkbox;
+          // destroy SVG elements
+          ["legendItem", "legendLine", "legendSymbol", "legendGroup"].forEach(
+            function (key) {
+              if (item[key]) {
+                item[key] = item[key].destroy();
+              }
+            }
+          );
+          if (checkbox) {
+            discardElement(item.checkbox);
+          }
         };
-        // Stacking methods defined on the Axis prototype
-        StackingAxis.compose(Axis);
-        // Stacking methods defined for Series prototype
         /**
-         * Set grouped points in a stack-like object. When `centerInCategory` is true,
-         * and `stacking` is not enabled, we need a pseudo (horizontal) stack in order
-         * to handle grouping of points within the same category.
+         * Destroy the legend. Used internally. To reflow objects, `chart.redraw`
+         * must be called after destruction.
          *
          * @private
-         * @function Highcharts.Series#setStackedPoints
-         * @return {void}
-         */
-        Series.prototype.setGroupedPoints = function () {
-            if (this.options.centerInCategory &&
-                (this.is('column') || this.is('columnrange')) &&
-                // With stacking enabled, we already have stacks that we can compute
-                // from
-                !this.options.stacking &&
-                // With only one series, we don't need to consider centerInCategory
-                this.chart.series.length > 1) {
-                Series.prototype.setStackedPoints.call(this, 'group');
+         * @function Highcharts.Legend#destroy
+         */
+        Legend.prototype.destroy = function () {
+          /**
+           * @private
+           * @param {string} key
+           * @return {void}
+           */
+          function destroyItems(key) {
+            if (this[key]) {
+              this[key] = this[key].destroy();
             }
+          }
+          // Destroy items
+          this.getAllItems().forEach(function (item) {
+            ["legendItem", "legendGroup"].forEach(destroyItems, item);
+          });
+          // Destroy legend elements
+          [
+            "clipRect",
+            "up",
+            "down",
+            "pager",
+            "nav",
+            "box",
+            "title",
+            "group",
+          ].forEach(destroyItems, this);
+          this.display = null; // Reset in .render on update.
+        };
+        /**
+         * Position the checkboxes after the width is determined.
+         *
+         * @private
+         * @function Highcharts.Legend#positionCheckboxes
+         */
+        Legend.prototype.positionCheckboxes = function () {
+          var alignAttr = this.group && this.group.alignAttr,
+            translateY,
+            clipHeight = this.clipHeight || this.legendHeight,
+            titleHeight = this.titleHeight;
+          if (alignAttr) {
+            translateY = alignAttr.translateY;
+            this.allItems.forEach(function (item) {
+              var checkbox = item.checkbox,
+                top;
+              if (checkbox) {
+                top =
+                  translateY +
+                  titleHeight +
+                  checkbox.y +
+                  (this.scrollOffset || 0) +
+                  3;
+                css(checkbox, {
+                  left:
+                    alignAttr.translateX +
+                    item.checkboxOffset +
+                    checkbox.x -
+                    20 +
+                    "px",
+                  top: top + "px",
+                  display:
+                    this.proximate ||
+                    (top > translateY - 6 && top < translateY + clipHeight - 6)
+                      ? ""
+                      : "none",
+                });
+              }
+            }, this);
+          }
         };
         /**
-         * Adds series' points value to corresponding stack
+         * Render the legend title on top of the legend.
          *
          * @private
-         * @function Highcharts.Series#setStackedPoints
+         * @function Highcharts.Legend#renderTitle
+         */
+        Legend.prototype.renderTitle = function () {
+          var options = this.options,
+            padding = this.padding,
+            titleOptions = options.title,
+            titleHeight = 0,
+            bBox;
+          if (titleOptions.text) {
+            if (!this.title) {
+              /**
+               * SVG element of the legend title.
+               *
+               * @readonly
+               * @name Highcharts.Legend#title
+               * @type {Highcharts.SVGElement}
+               */
+              this.title = this.chart.renderer
+                .label(
+                  titleOptions.text,
+                  padding - 3,
+                  padding - 4,
+                  null,
+                  null,
+                  null,
+                  options.useHTML,
+                  null,
+                  "legend-title"
+                )
+                .attr({ zIndex: 1 });
+              if (!this.chart.styledMode) {
+                this.title.css(titleOptions.style);
+              }
+              this.title.add(this.group);
+            }
+            // Set the max title width (#7253)
+            if (!titleOptions.width) {
+              this.title.css({
+                width: this.maxLegendWidth + "px",
+              });
+            }
+            bBox = this.title.getBBox();
+            titleHeight = bBox.height;
+            this.offsetWidth = bBox.width; // #1717
+            this.contentGroup.attr({ translateY: titleHeight });
+          }
+          this.titleHeight = titleHeight;
+        };
+        /**
+         * Set the legend item text.
+         *
+         * @function Highcharts.Legend#setText
+         * @param {Highcharts.Point|Highcharts.Series} item
+         *        The item for which to update the text in the legend.
          */
-        Series.prototype.setStackedPoints = function (stackingParam) {
-            var stacking = stackingParam || this.options.stacking;
-            if (!stacking ||
-                (this.visible !== true &&
-                    this.chart.options.chart.ignoreHiddenSeries !== false)) {
-                return;
+        Legend.prototype.setText = function (item) {
+          var options = this.options;
+          item.legendItem.attr({
+            text: options.labelFormat
+              ? format(options.labelFormat, item, this.chart)
+              : options.labelFormatter.call(item),
+          });
+        };
+        /**
+         * Render a single specific legend item. Called internally from the `render`
+         * function.
+         *
+         * @private
+         * @function Highcharts.Legend#renderItem
+         * @param {Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series} item
+         * The item to render.
+         */
+        Legend.prototype.renderItem = function (item) {
+          var legend = this,
+            chart = legend.chart,
+            renderer = chart.renderer,
+            options = legend.options,
+            horizontal = options.layout === "horizontal",
+            symbolWidth = legend.symbolWidth,
+            symbolPadding = options.symbolPadding,
+            itemStyle = legend.itemStyle,
+            itemHiddenStyle = legend.itemHiddenStyle,
+            itemDistance = horizontal ? pick(options.itemDistance, 20) : 0,
+            ltr = !options.rtl,
+            bBox,
+            li = item.legendItem,
+            isSeries = !item.series,
+            series =
+              !isSeries && item.series.drawLegendSymbol ? item.series : item,
+            seriesOptions = series.options,
+            showCheckbox =
+              legend.createCheckboxForItem &&
+              seriesOptions &&
+              seriesOptions.showCheckbox,
+            // full width minus text width
+            itemExtraWidth =
+              symbolWidth +
+              symbolPadding +
+              itemDistance +
+              (showCheckbox ? 20 : 0),
+            useHTML = options.useHTML,
+            itemClassName = item.options.className;
+          if (!li) {
+            // generate it once, later move it
+            // Generate the group box, a group to hold the symbol and text. Text
+            // is to be appended in Legend class.
+            item.legendGroup = renderer
+              .g("legend-item")
+              .addClass(
+                "highcharts-" +
+                  series.type +
+                  "-series " +
+                  "highcharts-color-" +
+                  item.colorIndex +
+                  (itemClassName ? " " + itemClassName : "") +
+                  (isSeries ? " highcharts-series-" + item.index : "")
+              )
+              .attr({ zIndex: 1 })
+              .add(legend.scrollGroup);
+            // Generate the list item text and add it to the group
+            item.legendItem = li = renderer.text(
+              "",
+              ltr ? symbolWidth + symbolPadding : -symbolPadding,
+              legend.baseline || 0,
+              useHTML
+            );
+            if (!chart.styledMode) {
+              // merge to prevent modifying original (#1021)
+              li.css(merge(item.visible ? itemStyle : itemHiddenStyle));
             }
-            var series = this, xData = series.processedXData, yData = series.processedYData, stackedYData = [], yDataLength = yData.length, seriesOptions = series.options, threshold = seriesOptions.threshold, stackThreshold = pick(seriesOptions.startFromThreshold && threshold, 0), stackOption = seriesOptions.stack, stackKey = stackingParam ? series.type + "," + stacking : series.stackKey, negKey = '-' + stackKey, negStacks = series.negStacks, yAxis = series.yAxis, stacks = yAxis.stacking.stacks, oldStacks = yAxis.stacking.oldStacks, stackIndicator, isNegative, stack, other, key, pointKey, i, x, y;
-            yAxis.stacking.stacksTouched += 1;
-            // loop over the non-null y values and read them into a local array
-            for (i = 0; i < yDataLength; i++) {
-                x = xData[i];
-                y = yData[i];
-                stackIndicator = series.getStackIndicator(stackIndicator, x, series.index);
-                pointKey = stackIndicator.key;
-                // Read stacked values into a stack based on the x value,
-                // the sign of y and the stack key. Stacking is also handled for null
-                // values (#739)
-                isNegative = negStacks && y < (stackThreshold ? 0 : threshold);
-                key = isNegative ? negKey : stackKey;
-                // Create empty object for this stack if it doesn't exist yet
-                if (!stacks[key]) {
-                    stacks[key] =
-                        {};
-                }
-                // Initialize StackItem for this x
-                if (!stacks[key][x]) {
-                    if (oldStacks[key] &&
-                        oldStacks[key][x]) {
-                        stacks[key][x] = oldStacks[key][x];
-                        stacks[key][x].total = null;
-                    }
-                    else {
-                        stacks[key][x] = new StackItem(yAxis, yAxis.options.stackLabels, isNegative, x, stackOption);
-                    }
-                }
-                // If the StackItem doesn't exist, create it first
-                stack = stacks[key][x];
-                if (y !== null) {
-                    stack.points[pointKey] = stack.points[series.index] =
-                        [pick(stack.cumulative, stackThreshold)];
-                    // Record the base of the stack
-                    if (!defined(stack.cumulative)) {
-                        stack.base = pointKey;
-                    }
-                    stack.touched = yAxis.stacking.stacksTouched;
-                    // In area charts, if there are multiple points on the same X value,
-                    // let the area fill the full span of those points
-                    if (stackIndicator.index > 0 && series.singleStacks === false) {
-                        stack.points[pointKey][0] =
-                            stack.points[series.index + ',' + x + ',0'][0];
-                    }
-                    // When updating to null, reset the point stack (#7493)
-                }
-                else {
-                    stack.points[pointKey] = stack.points[series.index] =
-                        null;
-                }
-                // Add value to the stack total
-                if (stacking === 'percent') {
-                    // Percent stacked column, totals are the same for the positive and
-                    // negative stacks
-                    other = isNegative ? stackKey : negKey;
-                    if (negStacks && stacks[other] && stacks[other][x]) {
-                        other = stacks[other][x];
-                        stack.total = other.total =
-                            Math.max(other.total, stack.total) +
-                                Math.abs(y) ||
-                                0;
-                        // Percent stacked areas
-                    }
-                    else {
-                        stack.total =
-                            correctFloat(stack.total + (Math.abs(y) || 0));
-                    }
-                }
-                else if (stacking === 'group') {
-                    // In this stack, the total is the number of valid points
-                    if (y !== null) {
-                        stack.total = (stack.total || 0) + 1;
-                    }
-                }
-                else {
-                    stack.total = correctFloat(stack.total + (y || 0));
-                }
-                if (stacking === 'group') {
-                    // This point's index within the stack, pushed to stack.points[1]
-                    stack.cumulative = (stack.total || 1) - 1;
-                }
-                else {
-                    stack.cumulative =
-                        pick(stack.cumulative, stackThreshold) + (y || 0);
-                }
-                if (y !== null) {
-                    stack.points[pointKey].push(stack.cumulative);
-                    stackedYData[i] = stack.cumulative;
-                    stack.hasValidPoints = true;
-                }
+            li.attr({
+              align: ltr ? "left" : "right",
+              zIndex: 2,
+            }).add(item.legendGroup);
+            // Get the baseline for the first item - the font size is equal for
+            // all
+            if (!legend.baseline) {
+              legend.fontMetrics = renderer.fontMetrics(
+                chart.styledMode ? 12 : itemStyle.fontSize,
+                li
+              );
+              legend.baseline = legend.fontMetrics.f + 3 + legend.itemMarginTop;
+              li.attr("y", legend.baseline);
             }
-            if (stacking === 'percent') {
-                yAxis.stacking.usePercentage = true;
+            // Draw the legend symbol inside the group box
+            legend.symbolHeight = options.symbolHeight || legend.fontMetrics.f;
+            series.drawLegendSymbol(legend, item);
+            if (legend.setItemEvents) {
+              legend.setItemEvents(item, li, useHTML);
             }
-            if (stacking !== 'group') {
-                this.stackedYData = stackedYData; // To be used in getExtremes
+          }
+          // Add the HTML checkbox on top
+          if (showCheckbox && !item.checkbox && legend.createCheckboxForItem) {
+            legend.createCheckboxForItem(item);
+          }
+          // Colorize the items
+          legend.colorizeItem(item, item.visible);
+          // Take care of max width and text overflow (#6659)
+          if (chart.styledMode || !itemStyle.width) {
+            li.css({
+              width:
+                (options.itemWidth ||
+                  legend.widthOption ||
+                  chart.spacingBox.width) -
+                itemExtraWidth +
+                "px",
+            });
+          }
+          // Always update the text
+          legend.setText(item);
+          // calculate the positions for the next line
+          bBox = li.getBBox();
+          item.itemWidth = item.checkboxOffset =
+            options.itemWidth ||
+            item.legendItemWidth ||
+            bBox.width + itemExtraWidth;
+          legend.maxItemWidth = Math.max(legend.maxItemWidth, item.itemWidth);
+          legend.totalItemWidth += item.itemWidth;
+          legend.itemHeight = item.itemHeight = Math.round(
+            item.legendItemHeight || bBox.height || legend.symbolHeight
+          );
+        };
+        /**
+         * Get the position of the item in the layout. We now know the
+         * maxItemWidth from the previous loop.
+         *
+         * @private
+         * @function Highcharts.Legend#layoutItem
+         * @param {Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series} item
+         */
+        Legend.prototype.layoutItem = function (item) {
+          var options = this.options,
+            padding = this.padding,
+            horizontal = options.layout === "horizontal",
+            itemHeight = item.itemHeight,
+            itemMarginBottom = this.itemMarginBottom,
+            itemMarginTop = this.itemMarginTop,
+            itemDistance = horizontal ? pick(options.itemDistance, 20) : 0,
+            maxLegendWidth = this.maxLegendWidth,
+            itemWidth =
+              options.alignColumns && this.totalItemWidth > maxLegendWidth
+                ? this.maxItemWidth
+                : item.itemWidth;
+          // If the item exceeds the width, start a new line
+          if (horizontal && this.itemX - padding + itemWidth > maxLegendWidth) {
+            this.itemX = padding;
+            if (this.lastLineHeight) {
+              // Not for the first line (#10167)
+              this.itemY +=
+                itemMarginTop + this.lastLineHeight + itemMarginBottom;
             }
-            // Reset old stacks
-            yAxis.stacking.oldStacks = {};
+            this.lastLineHeight = 0; // reset for next line (#915, #3976)
+          }
+          // Set the edge positions
+          this.lastItemY = itemMarginTop + this.itemY + itemMarginBottom;
+          this.lastLineHeight = Math.max(
+            // #915
+            itemHeight,
+            this.lastLineHeight
+          );
+          // cache the position of the newly generated or reordered items
+          item._legendItemPos = [this.itemX, this.itemY];
+          // advance
+          if (horizontal) {
+            this.itemX += itemWidth;
+          } else {
+            this.itemY += itemMarginTop + itemHeight + itemMarginBottom;
+            this.lastLineHeight = itemHeight;
+          }
+          // the width of the widest item
+          this.offsetWidth =
+            this.widthOption ||
+            Math.max(
+              (horizontal
+                ? this.itemX -
+                  padding -
+                  (item.checkbox
+                    ? // decrease by itemDistance only when no checkbox #4853
+                      0
+                    : itemDistance)
+                : itemWidth) + padding,
+              this.offsetWidth
+            );
         };
         /**
-         * Iterate over all stacks and compute the absolute values to percent
+         * Get all items, which is one item per series for most series and one
+         * item per point for pie series and its derivatives. Fires the event
+         * `afterGetAllItems`.
          *
          * @private
-         * @function Highcharts.Series#modifyStacks
-         */
-        Series.prototype.modifyStacks = function () {
-            var series = this,
-                yAxis = series.yAxis,
-                stackKey = series.stackKey,
-                stacks = yAxis.stacking.stacks,
-                processedXData = series.processedXData,
-                stackIndicator,
-                stacking = series.options.stacking;
-            if (series[stacking + 'Stacker']) { // Modifier function exists
-                [stackKey, '-' + stackKey].forEach(function (key) {
-                    var i = processedXData.length,
-                        x,
-                        stack,
-                        pointExtremes;
-                    while (i--) {
-                        x = processedXData[i];
-                        stackIndicator = series.getStackIndicator(stackIndicator, x, series.index, key);
-                        stack = stacks[key] && stacks[key][x];
-                        pointExtremes =
-                            stack && stack.points[stackIndicator.key];
-                        if (pointExtremes) {
-                            series[stacking + 'Stacker'](pointExtremes, stack, i);
-                        }
-                    }
-                });
+         * @function Highcharts.Legend#getAllItems
+         * @return {Array<(Highcharts.BubbleLegend|Highcharts.Point|Highcharts.Series)>}
+         * The current items in the legend.
+         * @fires Highcharts.Legend#event:afterGetAllItems
+         */
+        Legend.prototype.getAllItems = function () {
+          var allItems = [];
+          this.chart.series.forEach(function (series) {
+            var seriesOptions = series && series.options;
+            // Handle showInLegend. If the series is linked to another series,
+            // defaults to false.
+            if (
+              series &&
+              pick(
+                seriesOptions.showInLegend,
+                !defined(seriesOptions.linkedTo) ? void 0 : false,
+                true
+              )
+            ) {
+              // Use points or series for the legend item depending on
+              // legendType
+              allItems = allItems.concat(
+                series.legendItems ||
+                  (seriesOptions.legendType === "point" ? series.data : series)
+              );
             }
+          });
+          fireEvent(this, "afterGetAllItems", { allItems: allItems });
+          return allItems;
         };
         /**
-         * Modifier function for percent stacks. Blows up the stack to 100%.
+         * Get a short, three letter string reflecting the alignment and layout.
          *
          * @private
-         * @function Highcharts.Series#percentStacker
-         * @param {Array<number>} pointExtremes
-         * @param {Highcharts.StackItem} stack
-         * @param {number} i
+         * @function Highcharts.Legend#getAlignment
+         * @return {string}
+         * The alignment, empty string if floating
+         */
+        Legend.prototype.getAlignment = function () {
+          var options = this.options;
+          // Use the first letter of each alignment option in order to detect
+          // the side. (#4189 - use charAt(x) notation instead of [x] for IE7)
+          if (this.proximate) {
+            return options.align.charAt(0) + "tv";
+          }
+          return options.floating
+            ? ""
+            : options.align.charAt(0) +
+                options.verticalAlign.charAt(0) +
+                options.layout.charAt(0);
+        };
+        /**
+         * Adjust the chart margins by reserving space for the legend on only one
+         * side of the chart. If the position is set to a corner, top or bottom is
+         * reserved for horizontal legends and left or right for vertical ones.
+         *
+         * @private
+         * @function Highcharts.Legend#adjustMargins
+         * @param {Array<number>} margin
+         * @param {Array<number>} spacing
+         */
+        Legend.prototype.adjustMargins = function (margin, spacing) {
+          var chart = this.chart,
+            options = this.options,
+            alignment = this.getAlignment();
+          if (alignment) {
+            [
+              /(lth|ct|rth)/,
+              /(rtv|rm|rbv)/,
+              /(rbh|cb|lbh)/,
+              /(lbv|lm|ltv)/,
+            ].forEach(function (alignments, side) {
+              if (alignments.test(alignment) && !defined(margin[side])) {
+                // Now we have detected on which side of the chart we should
+                // reserve space for the legend
+                chart[marginNames[side]] = Math.max(
+                  chart[marginNames[side]],
+                  chart.legend[
+                    (side + 1) % 2 ? "legendHeight" : "legendWidth"
+                  ] +
+                    [1, -1, -1, 1][side] * options[side % 2 ? "x" : "y"] +
+                    pick(options.margin, 12) +
+                    spacing[side] +
+                    (chart.titleOffset[side] || 0)
+                );
+              }
+            });
+          }
+        };
+        /**
+         * @private
+         * @function Highcharts.Legend#proximatePositions
+         */
+        Legend.prototype.proximatePositions = function () {
+          var chart = this.chart,
+            boxes = [],
+            alignLeft = this.options.align === "left";
+          this.allItems.forEach(function (item) {
+            var lastPoint,
+              height,
+              useFirstPoint = alignLeft,
+              target,
+              top;
+            if (item.yAxis) {
+              if (item.xAxis.options.reversed) {
+                useFirstPoint = !useFirstPoint;
+              }
+              if (item.points) {
+                lastPoint = find(
+                  useFirstPoint ? item.points : item.points.slice(0).reverse(),
+                  function (item) {
+                    return isNumber(item.plotY);
+                  }
+                );
+              }
+              height =
+                this.itemMarginTop +
+                item.legendItem.getBBox().height +
+                this.itemMarginBottom;
+              top = item.yAxis.top - chart.plotTop;
+              if (item.visible) {
+                target = lastPoint ? lastPoint.plotY : item.yAxis.height;
+                target += top - 0.3 * height;
+              } else {
+                target = top + item.yAxis.height;
+              }
+              boxes.push({
+                target: target,
+                size: height,
+                item: item,
+              });
+            }
+          }, this);
+          H.distribute(boxes, chart.plotHeight);
+          boxes.forEach(function (box) {
+            box.item._legendItemPos[1] =
+              chart.plotTop - chart.spacing[0] + box.pos;
+          });
+        };
+        /**
+         * Render the legend. This method can be called both before and after
+         * `chart.render`. If called after, it will only rearrange items instead
+         * of creating new ones. Called internally on initial render and after
+         * redraws.
+         *
+         * @private
+         * @function Highcharts.Legend#render
+         */
+        Legend.prototype.render = function () {
+          var legend = this,
+            chart = legend.chart,
+            renderer = chart.renderer,
+            legendGroup = legend.group,
+            allItems,
+            display,
+            legendWidth,
+            legendHeight,
+            box = legend.box,
+            options = legend.options,
+            padding = legend.padding,
+            allowedWidth;
+          legend.itemX = padding;
+          legend.itemY = legend.initialItemY;
+          legend.offsetWidth = 0;
+          legend.lastItemY = 0;
+          legend.widthOption = relativeLength(
+            options.width,
+            chart.spacingBox.width - padding
+          );
+          // Compute how wide the legend is allowed to be
+          allowedWidth = chart.spacingBox.width - 2 * padding - options.x;
+          if (
+            ["rm", "lm"].indexOf(legend.getAlignment().substring(0, 2)) > -1
+          ) {
+            allowedWidth /= 2;
+          }
+          legend.maxLegendWidth = legend.widthOption || allowedWidth;
+          if (!legendGroup) {
+            /**
+             * SVG group of the legend.
+             *
+             * @readonly
+             * @name Highcharts.Legend#group
+             * @type {Highcharts.SVGElement}
+             */
+            legend.group = legendGroup = renderer
+              .g("legend")
+              .attr({ zIndex: 7 })
+              .add();
+            legend.contentGroup = renderer
+              .g()
+              .attr({ zIndex: 1 }) // above background
+              .add(legendGroup);
+            legend.scrollGroup = renderer.g().add(legend.contentGroup);
+          }
+          legend.renderTitle();
+          // add each series or point
+          allItems = legend.getAllItems();
+          // sort by legendIndex
+          stableSort(allItems, function (a, b) {
+            return (
+              ((a.options && a.options.legendIndex) || 0) -
+              ((b.options && b.options.legendIndex) || 0)
+            );
+          });
+          // reversed legend
+          if (options.reversed) {
+            allItems.reverse();
+          }
+          /**
+           * All items for the legend, which is an array of series for most series
+           * and an array of points for pie series and its derivatives.
+           *
+           * @readonly
+           * @name Highcharts.Legend#allItems
+           * @type {Array<(Highcharts.Point|Highcharts.Series)>}
+           */
+          legend.allItems = allItems;
+          legend.display = display = !!allItems.length;
+          // Render the items. First we run a loop to set the text and properties
+          // and read all the bounding boxes. The next loop computes the item
+          // positions based on the bounding boxes.
+          legend.lastLineHeight = 0;
+          legend.maxItemWidth = 0;
+          legend.totalItemWidth = 0;
+          legend.itemHeight = 0;
+          allItems.forEach(legend.renderItem, legend);
+          allItems.forEach(legend.layoutItem, legend);
+          // Get the box
+          legendWidth = (legend.widthOption || legend.offsetWidth) + padding;
+          legendHeight =
+            legend.lastItemY + legend.lastLineHeight + legend.titleHeight;
+          legendHeight = legend.handleOverflow(legendHeight);
+          legendHeight += padding;
+          // Draw the border and/or background
+          if (!box) {
+            /**
+             * SVG element of the legend box.
+             *
+             * @readonly
+             * @name Highcharts.Legend#box
+             * @type {Highcharts.SVGElement}
+             */
+            legend.box = box = renderer
+              .rect()
+              .addClass("highcharts-legend-box")
+              .attr({
+                r: options.borderRadius,
+              })
+              .add(legendGroup);
+            box.isNew = true;
+          }
+          // Presentational
+          if (!chart.styledMode) {
+            box
+              .attr({
+                stroke: options.borderColor,
+                "stroke-width": options.borderWidth || 0,
+                fill: options.backgroundColor || "none",
+              })
+              .shadow(options.shadow);
+          }
+          if (legendWidth > 0 && legendHeight > 0) {
+            box[box.isNew ? "attr" : "animate"](
+              box.crisp.call(
+                {},
+                {
+                  x: 0,
+                  y: 0,
+                  width: legendWidth,
+                  height: legendHeight,
+                },
+                box.strokeWidth()
+              )
+            );
+            box.isNew = false;
+          }
+          // hide the border if no items
+          box[display ? "show" : "hide"]();
+          // Open for responsiveness
+          if (chart.styledMode && legendGroup.getStyle("display") === "none") {
+            legendWidth = legendHeight = 0;
+          }
+          legend.legendWidth = legendWidth;
+          legend.legendHeight = legendHeight;
+          if (display) {
+            legend.align();
+          }
+          if (!this.proximate) {
+            this.positionItems();
+          }
+          fireEvent(this, "afterRender");
+        };
+        /**
+         * Align the legend to chart's box.
+         *
+         * @private
+         * @function Highcharts.align
+         * @param {Highcharts.BBoxObject} alignTo
+         * @return {void}
          */
-        Series.prototype.percentStacker = function (pointExtremes, stack, i) {
-            var totalFactor = stack.total ? 100 / stack.total : 0;
-            // Y bottom value
-            pointExtremes[0] = correctFloat(pointExtremes[0] * totalFactor);
-            // Y value
-            pointExtremes[1] = correctFloat(pointExtremes[1] * totalFactor);
-            this.stackedYData[i] = pointExtremes[1];
+        Legend.prototype.align = function (alignTo) {
+          if (alignTo === void 0) {
+            alignTo = this.chart.spacingBox;
+          }
+          var chart = this.chart,
+            options = this.options;
+          // If aligning to the top and the layout is horizontal, adjust for
+          // the title (#7428)
+          var y = alignTo.y;
+          if (
+            /(lth|ct|rth)/.test(this.getAlignment()) &&
+            chart.titleOffset[0] > 0
+          ) {
+            y += chart.titleOffset[0];
+          } else if (
+            /(lbh|cb|rbh)/.test(this.getAlignment()) &&
+            chart.titleOffset[2] > 0
+          ) {
+            y -= chart.titleOffset[2];
+          }
+          if (y !== alignTo.y) {
+            alignTo = merge(alignTo, { y: y });
+          }
+          this.group.align(
+            merge(options, {
+              width: this.legendWidth,
+              height: this.legendHeight,
+              verticalAlign: this.proximate ? "top" : options.verticalAlign,
+            }),
+            true,
+            alignTo
+          );
         };
         /**
-         * Get stack indicator, according to it's x-value, to determine points with the
-         * same x-value
+         * Set up the overflow handling by adding navigation with up and down arrows
+         * below the legend.
          *
          * @private
-         * @function Highcharts.Series#getStackIndicator
-         * @param {Highcharts.StackItemIndicatorObject|undefined} stackIndicator
-         * @param {number} x
-         * @param {number} index
-         * @param {string} [key]
-         * @return {Highcharts.StackItemIndicatorObject}
-         */
-        Series.prototype.getStackIndicator = function (stackIndicator, x, index, key) {
-            // Update stack indicator, when:
-            // first point in a stack || x changed || stack type (negative vs positive)
-            // changed:
-            if (!defined(stackIndicator) ||
-                stackIndicator.x !== x ||
-                (key && stackIndicator.key !== key)) {
-                stackIndicator = {
-                    x: x,
-                    index: 0,
-                    key: key
-                };
+         * @function Highcharts.Legend#handleOverflow
+         * @param {number} legendHeight
+         * @return {number}
+         */
+        Legend.prototype.handleOverflow = function (legendHeight) {
+          var legend = this,
+            chart = this.chart,
+            renderer = chart.renderer,
+            options = this.options,
+            optionsY = options.y,
+            alignTop = options.verticalAlign === "top",
+            padding = this.padding,
+            spaceHeight =
+              chart.spacingBox.height +
+              (alignTop ? -optionsY : optionsY) -
+              padding,
+            maxHeight = options.maxHeight,
+            clipHeight,
+            clipRect = this.clipRect,
+            navOptions = options.navigation,
+            animation = pick(navOptions.animation, true),
+            arrowSize = navOptions.arrowSize || 12,
+            nav = this.nav,
+            pages = this.pages,
+            lastY,
+            allItems = this.allItems,
+            clipToHeight = function (height) {
+              if (typeof height === "number") {
+                clipRect.attr({
+                  height: height,
+                });
+              } else if (clipRect) {
+                // Reset (#5912)
+                legend.clipRect = clipRect.destroy();
+                legend.contentGroup.clip();
+              }
+              // useHTML
+              if (legend.contentGroup.div) {
+                legend.contentGroup.div.style.clip = height
+                  ? "rect(" +
+                    padding +
+                    "px,9999px," +
+                    (padding + height) +
+                    "px,0)"
+                  : "auto";
+              }
+            },
+            addTracker = function (key) {
+              legend[key] = renderer
+                .circle(0, 0, arrowSize * 1.3)
+                .translate(arrowSize / 2, arrowSize / 2)
+                .add(nav);
+              if (!chart.styledMode) {
+                legend[key].attr("fill", "rgba(0,0,0,0.0001)");
+              }
+              return legend[key];
+            };
+          // Adjust the height
+          if (
+            options.layout === "horizontal" &&
+            options.verticalAlign !== "middle" &&
+            !options.floating
+          ) {
+            spaceHeight /= 2;
+          }
+          if (maxHeight) {
+            spaceHeight = Math.min(spaceHeight, maxHeight);
+          }
+          // Reset the legend height and adjust the clipping rectangle
+          pages.length = 0;
+          if (legendHeight > spaceHeight && navOptions.enabled !== false) {
+            this.clipHeight = clipHeight = Math.max(
+              spaceHeight - 20 - this.titleHeight - padding,
+              0
+            );
+            this.currentPage = pick(this.currentPage, 1);
+            this.fullHeight = legendHeight;
+            // Fill pages with Y positions so that the top of each a legend item
+            // defines the scroll top for each page (#2098)
+            allItems.forEach(function (item, i) {
+              var y = item._legendItemPos[1],
+                h = Math.round(item.legendItem.getBBox().height),
+                len = pages.length;
+              if (
+                !len ||
+                (y - pages[len - 1] > clipHeight &&
+                  (lastY || y) !== pages[len - 1])
+              ) {
+                pages.push(lastY || y);
+                len++;
+              }
+              // Keep track of which page each item is on
+              item.pageIx = len - 1;
+              if (lastY) {
+                allItems[i - 1].pageIx = len - 1;
+              }
+              if (
+                i === allItems.length - 1 &&
+                y + h - pages[len - 1] > clipHeight &&
+                y !== lastY // #2617
+              ) {
+                pages.push(y);
+                item.pageIx = len;
+              }
+              if (y !== lastY) {
+                lastY = y;
+              }
+            });
+            // Only apply clipping if needed. Clipping causes blurred legend in
+            // PDF export (#1787)
+            if (!clipRect) {
+              clipRect = legend.clipRect = renderer.clipRect(
+                0,
+                padding,
+                9999,
+                0
+              );
+              legend.contentGroup.clip(clipRect);
             }
-            else {
-                (stackIndicator).index++;
+            clipToHeight(clipHeight);
+            // Add navigation elements
+            if (!nav) {
+              this.nav = nav = renderer.g().attr({ zIndex: 1 }).add(this.group);
+              this.up = renderer
+                .symbol("triangle", 0, 0, arrowSize, arrowSize)
+                .add(nav);
+              addTracker("upTracker").on("click", function () {
+                legend.scroll(-1, animation);
+              });
+              this.pager = renderer
+                .text("", 15, 10)
+                .addClass("highcharts-legend-navigation");
+              if (!chart.styledMode) {
+                this.pager.css(navOptions.style);
+              }
+              this.pager.add(nav);
+              this.down = renderer
+                .symbol("triangle-down", 0, 0, arrowSize, arrowSize)
+                .add(nav);
+              addTracker("downTracker").on("click", function () {
+                legend.scroll(1, animation);
+              });
             }
-            stackIndicator.key =
-                [index, x, stackIndicator.index].join(',');
-            return stackIndicator;
+            // Set initial position
+            legend.scroll(0);
+            legendHeight = spaceHeight;
+            // Reset
+          } else if (nav) {
+            clipToHeight();
+            this.nav = nav.destroy(); // #6322
+            this.scrollGroup.attr({
+              translateY: 1,
+            });
+            this.clipHeight = 0; // #1379
+          }
+          return legendHeight;
         };
-        H.StackItem = StackItem;
-
-        return H.StackItem;
-    });
-    _registerModule(_modules, 'Core/Dynamics.js', [_modules['Core/Animation/AnimationUtilities.js'], _modules['Core/Axis/Axis.js'], _modules['Core/Series/Series.js'], _modules['Core/Chart/Chart.js'], _modules['Core/Globals.js'], _modules['Series/LineSeries.js'], _modules['Core/Options.js'], _modules['Core/Series/Point.js'], _modules['Core/Time.js'], _modules['Core/Utilities.js']], function (A, Axis, BaseSeries, Chart, H, LineSeries, O, Point, Time, U) {
-        /* *
+        /**
+         * Scroll the legend by a number of pages.
          *
-         *  (c) 2010-2020 Torstein Honsi
+         * @private
+         * @function Highcharts.Legend#scroll
          *
-         *  License: www.highcharts.com/license
+         * @param {number} scrollBy
+         *        The number of pages to scroll.
          *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+         * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation]
+         *        Whether and how to apply animation.
          *
-         * */
-        var animate = A.animate,
-            setAnimation = A.setAnimation;
-        var seriesTypes = BaseSeries.seriesTypes;
-        var time = O.time;
-        var addEvent = U.addEvent,
-            createElement = U.createElement,
-            css = U.css,
-            defined = U.defined,
-            erase = U.erase,
-            error = U.error,
-            extend = U.extend,
-            fireEvent = U.fireEvent,
-            isArray = U.isArray,
-            isNumber = U.isNumber,
-            isObject = U.isObject,
-            isString = U.isString,
-            merge = U.merge,
-            objectEach = U.objectEach,
-            pick = U.pick,
-            relativeLength = U.relativeLength,
-            splat = U.splat;
-        /* eslint-disable valid-jsdoc */
-        /**
-         * Remove settings that have not changed, to avoid unnecessary rendering or
-         * computing (#9197).
-         * @private
+         * @return {void}
          */
-        H.cleanRecursively = function (newer, older) {
-            var result = {};
-            objectEach(newer, function (val, key) {
-                var ob;
-                // Dive into objects (except DOM nodes)
-                if (isObject(newer[key], true) &&
-                    !newer.nodeType && // #10044
-                    older[key]) {
-                    ob = H.cleanRecursively(newer[key], older[key]);
-                    if (Object.keys(ob).length) {
-                        result[key] = ob;
-                    }
-                    // Arrays, primitives and DOM nodes are copied directly
-                }
-                else if (isObject(newer[key]) ||
-                    newer[key] !== older[key]) {
-                    result[key] = newer[key];
-                }
+        Legend.prototype.scroll = function (scrollBy, animation) {
+          var _this = this;
+          var chart = this.chart,
+            pages = this.pages,
+            pageCount = pages.length,
+            currentPage = this.currentPage + scrollBy,
+            clipHeight = this.clipHeight,
+            navOptions = this.options.navigation,
+            pager = this.pager,
+            padding = this.padding;
+          // When resizing while looking at the last page
+          if (currentPage > pageCount) {
+            currentPage = pageCount;
+          }
+          if (currentPage > 0) {
+            if (typeof animation !== "undefined") {
+              setAnimation(animation, chart);
+            }
+            this.nav.attr({
+              translateX: padding,
+              translateY: clipHeight + this.padding + 7 + this.titleHeight,
+              visibility: "visible",
             });
-            return result;
-        };
-        // Extend the Chart prototype for dynamic methods
-        extend(Chart.prototype, /** @lends Highcharts.Chart.prototype */ {
-            /**
-             * Add a series to the chart after render time. Note that this method should
-             * never be used when adding data synchronously at chart render time, as it
-             * adds expense to the calculations and rendering. When adding data at the
-             * same time as the chart is initialized, add the series as a configuration
-             * option instead. With multiple axes, the `offset` is dynamically adjusted.
-             *
-             * @sample highcharts/members/chart-addseries/
-             *         Add a series from a button
-             * @sample stock/members/chart-addseries/
-             *         Add a series in Highstock
-             *
-             * @function Highcharts.Chart#addSeries
-             *
-             * @param {Highcharts.SeriesOptionsType} options
-             *        The config options for the series.
-             *
-             * @param {boolean} [redraw=true]
-             *        Whether to redraw the chart after adding.
-             *
-             * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation]
-             *        Whether to apply animation, and optionally animation
-             *        configuration.
-             *
-             * @return {Highcharts.Series}
-             *         The newly created series object.
-             *
-             * @fires Highcharts.Chart#event:addSeries
-             * @fires Highcharts.Chart#event:afterAddSeries
-             */
-            addSeries: function (options, redraw, animation) {
-                var series,
-                    chart = this;
-                if (options) { // <- not necessary
-                    redraw = pick(redraw, true); // defaults to true
-                    fireEvent(chart, 'addSeries', { options: options }, function () {
-                        series = chart.initSeries(options);
-                        chart.isDirtyLegend = true;
-                        chart.linkSeries();
-                        if (series.enabledDataSorting) {
-                            // We need to call `setData` after `linkSeries`
-                            series.setData(options.data, false);
-                        }
-                        fireEvent(chart, 'afterAddSeries', { series: series });
-                        if (redraw) {
-                            chart.redraw(animation);
-                        }
-                    });
-                }
-                return series;
-            },
-            /**
-             * Add an axis to the chart after render time. Note that this method should
-             * never be used when adding data synchronously at chart render time, as it
-             * adds expense to the calculations and rendering. When adding data at the
-             * same time as the chart is initialized, add the axis as a configuration
-             * option instead.
-             *
-             * @sample highcharts/members/chart-addaxis/
-             *         Add and remove axes
-             *
-             * @function Highcharts.Chart#addAxis
-             *
-             * @param {Highcharts.AxisOptions} options
-             *        The axis options.
-             *
-             * @param {boolean} [isX=false]
-             *        Whether it is an X axis or a value axis.
-             *
-             * @param {boolean} [redraw=true]
-             *        Whether to redraw the chart after adding.
-             *
-             * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation=true]
-             *        Whether and how to apply animation in the redraw.
-             *
-             * @return {Highcharts.Axis}
-             *         The newly generated Axis object.
-             */
-            addAxis: function (options, isX, redraw, animation) {
-                return this.createAxis(isX ? 'xAxis' : 'yAxis', { axis: options, redraw: redraw, animation: animation });
-            },
-            /**
-             * Add a color axis to the chart after render time. Note that this method
-             * should never be used when adding data synchronously at chart render time,
-             * as it adds expense to the calculations and rendering. When adding data at
-             * the same time as the chart is initialized, add the axis as a
-             * configuration option instead.
-             *
-             * @sample highcharts/members/chart-addaxis/
-             *         Add and remove axes
-             *
-             * @function Highcharts.Chart#addColorAxis
-             *
-             * @param {Highcharts.ColorAxisOptions} options
-             *        The axis options.
-             *
-             * @param {boolean} [redraw=true]
-             *        Whether to redraw the chart after adding.
-             *
-             * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation=true]
-             *        Whether and how to apply animation in the redraw.
-             *
-             * @return {Highcharts.ColorAxis}
-             *         The newly generated Axis object.
-             */
-            addColorAxis: function (options, redraw, animation) {
-                return this.createAxis('colorAxis', { axis: options, redraw: redraw, animation: animation });
-            },
-            /**
-             * Factory for creating different axis types.
-             *
-             * @private
-             * @function Highcharts.Chart#createAxis
-             *
-             * @param {string} type
-             *        An axis type.
-             *
-             * @param {...Array<*>} arguments
-             *        All arguments for the constructor.
-             *
-             * @return {Highcharts.Axis | Highcharts.ColorAxis}
-             *         The newly generated Axis object.
-             */
-            createAxis: function (type, options) {
-                var chartOptions = this.options,
-                    isColorAxis = type === 'colorAxis',
-                    axisOptions = options.axis,
-                    redraw = options.redraw,
-                    animation = options.animation,
-                    userOptions = merge(axisOptions, {
-                        index: this[type].length,
-                        isX: type === 'xAxis'
-                    }),
-                    axis;
-                if (isColorAxis) {
-                    axis = new H.ColorAxis(this, userOptions);
-                }
-                else {
-                    axis = new Axis(this, userOptions);
-                }
-                // Push the new axis options to the chart options
-                chartOptions[type] = splat(chartOptions[type] || {});
-                chartOptions[type].push(userOptions);
-                if (isColorAxis) {
-                    this.isDirtyLegend = true;
-                    // Clear before 'bindAxes' (#11924)
-                    this.axes.forEach(function (axis) {
-                        axis.series = [];
-                    });
-                    this.series.forEach(function (series) {
-                        series.bindAxes();
-                        series.isDirtyData = true;
-                    });
-                }
-                if (pick(redraw, true)) {
-                    this.redraw(animation);
-                }
-                return axis;
-            },
-            /**
-             * Dim the chart and show a loading text or symbol. Options for the loading
-             * screen are defined in {@link
-             * https://api.highcharts.com/highcharts/loading|the loading options}.
-             *
-             * @sample highcharts/members/chart-hideloading/
-             *         Show and hide loading from a button
-             * @sample highcharts/members/chart-showloading/
-             *         Apply different text labels
-             * @sample stock/members/chart-show-hide-loading/
-             *         Toggle loading in Highstock
-             *
-             * @function Highcharts.Chart#showLoading
-             *
-             * @param {string} [str]
-             *        An optional text to show in the loading label instead of the
-             *        default one. The default text is set in
-             *        [lang.loading](https://api.highcharts.com/highcharts/lang.loading).
-             */
-            showLoading: function (str) {
-                var chart = this,
-                    options = chart.options,
-                    loadingDiv = chart.loadingDiv,
-                    loadingOptions = options.loading,
-                    setLoadingSize = function () {
-                        if (loadingDiv) {
-                            css(loadingDiv, {
-                                left: chart.plotLeft + 'px',
-                                top: chart.plotTop + 'px',
-                                width: chart.plotWidth + 'px',
-                                height: chart.plotHeight + 'px'
-                            });
-                    }
-                };
-                // create the layer at the first call
-                if (!loadingDiv) {
-                    chart.loadingDiv = loadingDiv = createElement('div', {
-                        className: 'highcharts-loading highcharts-loading-hidden'
-                    }, null, chart.container);
-                    chart.loadingSpan = createElement('span', { className: 'highcharts-loading-inner' }, null, loadingDiv);
-                    addEvent(chart, 'redraw', setLoadingSize); // #1080
-                }
-                loadingDiv.className = 'highcharts-loading';
-                // Update text
-                chart.loadingSpan.innerHTML =
-                    pick(str, options.lang.loading, '');
-                if (!chart.styledMode) {
-                    // Update visuals
-                    css(loadingDiv, extend(loadingOptions.style, {
-                        zIndex: 10
-                    }));
-                    css(chart.loadingSpan, loadingOptions.labelStyle);
-                    // Show it
-                    if (!chart.loadingShown) {
-                        css(loadingDiv, {
-                            opacity: 0,
-                            display: ''
-                        });
-                        animate(loadingDiv, {
-                            opacity: loadingOptions.style.opacity || 0.5
-                        }, {
-                            duration: loadingOptions.showDuration || 0
-                        });
-                    }
-                }
-                chart.loadingShown = true;
-                setLoadingSize();
-            },
-            /**
-             * Hide the loading layer.
-             *
-             * @see Highcharts.Chart#showLoading
-             *
-             * @sample highcharts/members/chart-hideloading/
-             *         Show and hide loading from a button
-             * @sample stock/members/chart-show-hide-loading/
-             *         Toggle loading in Highstock
-             *
-             * @function Highcharts.Chart#hideLoading
-             */
-            hideLoading: function () {
-                var options = this.options,
-                    loadingDiv = this.loadingDiv;
-                if (loadingDiv) {
-                    loadingDiv.className =
-                        'highcharts-loading highcharts-loading-hidden';
-                    if (!this.styledMode) {
-                        animate(loadingDiv, {
-                            opacity: 0
-                        }, {
-                            duration: options.loading.hideDuration || 100,
-                            complete: function () {
-                                css(loadingDiv, { display: 'none' });
-                            }
-                        });
-                    }
-                }
-                this.loadingShown = false;
-            },
-            /**
-             * These properties cause isDirtyBox to be set to true when updating. Can be
-             * extended from plugins.
-             */
-            propsRequireDirtyBox: [
-                'backgroundColor',
-                'borderColor',
-                'borderWidth',
-                'borderRadius',
-                'plotBackgroundColor',
-                'plotBackgroundImage',
-                'plotBorderColor',
-                'plotBorderWidth',
-                'plotShadow',
-                'shadow'
-            ],
-            /**
-             * These properties require a full reflow of chart elements, best
-             * implemented through running `Chart.setSize` internally (#8190).
-             * @type {Array}
-             */
-            propsRequireReflow: [
-                'margin',
-                'marginTop',
-                'marginRight',
-                'marginBottom',
-                'marginLeft',
-                'spacing',
-                'spacingTop',
-                'spacingRight',
-                'spacingBottom',
-                'spacingLeft'
-            ],
-            /**
-             * These properties cause all series to be updated when updating. Can be
-             * extended from plugins.
-             */
-            propsRequireUpdateSeries: [
-                'chart.inverted',
-                'chart.polar',
-                'chart.ignoreHiddenSeries',
-                'chart.type',
-                'colors',
-                'plotOptions',
-                'time',
-                'tooltip'
-            ],
-            /**
-             * These collections (arrays) implement update() methods with support for
-             * one-to-one option.
-             */
-            collectionsWithUpdate: [
-                'xAxis',
-                'yAxis',
-                'zAxis',
-                'series'
-            ],
-            /**
-             * A generic function to update any element of the chart. Elements can be
-             * enabled and disabled, moved, re-styled, re-formatted etc.
-             *
-             * A special case is configuration objects that take arrays, for example
-             * [xAxis](https://api.highcharts.com/highcharts/xAxis),
-             * [yAxis](https://api.highcharts.com/highcharts/yAxis) or
-             * [series](https://api.highcharts.com/highcharts/series). For these
-             * collections, an `id` option is used to map the new option set to an
-             * existing object. If an existing object of the same id is not found, the
-             * corresponding item is updated. So for example, running `chart.update`
-             * with a series item without an id, will cause the existing chart's series
-             * with the same index in the series array to be updated. When the
-             * `oneToOne` parameter is true, `chart.update` will also take care of
-             * adding and removing items from the collection. Read more under the
-             * parameter description below.
-             *
-             * Note that when changing series data, `chart.update` may mutate the passed
-             * data options.
-             *
-             * See also the
-             * [responsive option set](https://api.highcharts.com/highcharts/responsive).
-             * Switching between `responsive.rules` basically runs `chart.update` under
-             * the hood.
-             *
-             * @sample highcharts/members/chart-update/
-             *         Update chart geometry
-             *
-             * @function Highcharts.Chart#update
-             *
-             * @param {Highcharts.Options} options
-             *        A configuration object for the new chart options.
-             *
-             * @param {boolean} [redraw=true]
-             *        Whether to redraw the chart.
-             *
-             * @param {boolean} [oneToOne=false]
-             *        When `true`, the `series`, `xAxis`, `yAxis` and `annotations`
-             *        collections will be updated one to one, and items will be either
-             *        added or removed to match the new updated options. For example,
-             *        if the chart has two series and we call `chart.update` with a
-             *        configuration containing three series, one will be added. If we
-             *        call `chart.update` with one series, one will be removed. Setting
-             *        an empty `series` array will remove all series, but leaving out
-             *        the`series` property will leave all series untouched. If the
-             *        series have id's, the new series options will be matched by id,
-             *        and the remaining ones removed.
-             *
-             * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation=true]
-             *        Whether to apply animation, and optionally animation
-             *        configuration.
-             *
-             * @fires Highcharts.Chart#event:update
-             * @fires Highcharts.Chart#event:afterUpdate
-             */
-            update: function (options, redraw, oneToOne, animation) {
-                var chart = this,
-                    adders = {
-                        credits: 'addCredits',
-                        title: 'setTitle',
-                        subtitle: 'setSubtitle',
-                        caption: 'setCaption'
-                    },
-                    optionsChart,
-                    updateAllAxes,
-                    updateAllSeries,
-                    newWidth,
-                    newHeight,
-                    runSetSize,
-                    isResponsiveOptions = options.isResponsiveOptions,
-                    itemsForRemoval = [];
-                fireEvent(chart, 'update', { options: options });
-                // If there are responsive rules in action, undo the responsive rules
-                // before we apply the updated options and replay the responsive rules
-                // on top from the chart.redraw function (#9617).
-                if (!isResponsiveOptions) {
-                    chart.setResponsive(false, true);
-                }
-                options = H.cleanRecursively(options, chart.options);
-                merge(true, chart.userOptions, options);
-                // If the top-level chart option is present, some special updates are
-                // required
-                optionsChart = options.chart;
-                if (optionsChart) {
-                    merge(true, chart.options.chart, optionsChart);
-                    // Setter function
-                    if ('className' in optionsChart) {
-                        chart.setClassName(optionsChart.className);
-                    }
-                    if ('reflow' in optionsChart) {
-                        chart.setReflow(optionsChart.reflow);
-                    }
-                    if ('inverted' in optionsChart ||
-                        'polar' in optionsChart ||
-                        'type' in optionsChart) {
-                        // Parse options.chart.inverted and options.chart.polar together
-                        // with the available series.
-                        chart.propFromSeries();
-                        updateAllAxes = true;
-                    }
-                    if ('alignTicks' in optionsChart) { // #6452
-                        updateAllAxes = true;
-                    }
-                    objectEach(optionsChart, function (val, key) {
-                        if (chart.propsRequireUpdateSeries.indexOf('chart.' + key) !==
-                            -1) {
-                            updateAllSeries = true;
-                        }
-                        // Only dirty box
-                        if (chart.propsRequireDirtyBox.indexOf(key) !== -1) {
-                            chart.isDirtyBox = true;
-                        }
-                        // Chart setSize
-                        if (chart.propsRequireReflow.indexOf(key) !== -1) {
-                            if (isResponsiveOptions) {
-                                chart.isDirtyBox = true;
-                            }
-                            else {
-                                runSetSize = true;
-                            }
-                        }
-                    });
-                    if (!chart.styledMode && 'style' in optionsChart) {
-                        chart.renderer.setStyle(optionsChart.style);
-                    }
-                }
-                // Moved up, because tooltip needs updated plotOptions (#6218)
-                if (!chart.styledMode && options.colors) {
-                    this.options.colors = options.colors;
-                }
-                if (options.time) {
-                    // Maintaining legacy global time. If the chart is instanciated
-                    // first with global time, then updated with time options, we need
-                    // to create a new Time instance to avoid mutating the global time
-                    // (#10536).
-                    if (this.time === time) {
-                        this.time = new Time(options.time);
-                    }
-                    // If we're updating, the time class is different from other chart
-                    // classes (chart.legend, chart.tooltip etc) in that it doesn't know
-                    // about the chart. The other chart[something].update functions also
-                    // set the chart.options[something]. For the time class however we
-                    // need to update the chart options separately. #14230.
-                    merge(true, chart.options.time, options.time);
-                }
-                // Some option stuctures correspond one-to-one to chart objects that
-                // have update methods, for example
-                // options.credits => chart.credits
-                // options.legend => chart.legend
-                // options.title => chart.title
-                // options.tooltip => chart.tooltip
-                // options.subtitle => chart.subtitle
-                // options.mapNavigation => chart.mapNavigation
-                // options.navigator => chart.navigator
-                // options.scrollbar => chart.scrollbar
-                objectEach(options, function (val, key) {
-                    if (chart[key] &&
-                        typeof chart[key].update === 'function') {
-                        chart[key].update(val, false);
-                        // If a one-to-one object does not exist, look for an adder function
-                    }
-                    else if (typeof chart[adders[key]] === 'function') {
-                        chart[adders[key]](val);
-                        // Else, just merge the options. For nodes like loading, noData,
-                        // plotOptions
-                    }
-                    else if (key !== 'color' &&
-                        chart.collectionsWithUpdate.indexOf(key) === -1) {
-                        merge(true, chart.options[key], options[key]);
-                    }
-                    if (key !== 'chart' &&
-                        chart.propsRequireUpdateSeries.indexOf(key) !== -1) {
-                        updateAllSeries = true;
-                    }
-                });
-                // Setters for collections. For axes and series, each item is referred
-                // by an id. If the id is not found, it defaults to the corresponding
-                // item in the collection, so setting one series without an id, will
-                // update the first series in the chart. Setting two series without
-                // an id will update the first and the second respectively (#6019)
-                // chart.update and responsive.
-                this.collectionsWithUpdate.forEach(function (coll) {
-                    var indexMap;
-                    if (options[coll]) {
-                        // In stock charts, the navigator series are also part of the
-                        // chart.series array, but those series should not be handled
-                        // here (#8196).
-                        if (coll === 'series') {
-                            indexMap = [];
-                            chart[coll].forEach(function (s, i) {
-                                if (!s.options.isInternal) {
-                                    indexMap.push(pick(s.options.index, i));
-                                }
-                            });
-                        }
-                        splat(options[coll]).forEach(function (newOptions, i) {
-                            var hasId = defined(newOptions.id);
-                            var item;
-                            // Match by id
-                            if (hasId) {
-                                item = chart.get(newOptions.id);
-                            }
-                            // No match by id found, match by index instead
-                            if (!item) {
-                                item = chart[coll][indexMap ? indexMap[i] : i];
-                                // Check if we grabbed an item with an exising but
-                                // different id (#13541)
-                                if (item && hasId && defined(item.options.id)) {
-                                    item = void 0;
-                                }
-                            }
-                            if (item && item.coll === coll) {
-                                item.update(newOptions, false);
-                                if (oneToOne) {
-                                    item.touched = true;
-                                }
-                            }
-                            // If oneToOne and no matching item is found, add one
-                            if (!item && oneToOne && chart.collectionsWithInit[coll]) {
-                                chart.collectionsWithInit[coll][0].apply(chart, 
-                                // [newOptions, ...extraArguments, redraw=false]
-                                [
-                                    newOptions
-                                ].concat(
-                                // Not all initializers require extra args
-                                chart.collectionsWithInit[coll][1] || []).concat([
-                                    false
-                                ])).touched = true;
-                            }
-                        });
-                        // Add items for removal
-                        if (oneToOne) {
-                            chart[coll].forEach(function (item) {
-                                if (!item.touched && !item.options.isInternal) {
-                                    itemsForRemoval.push(item);
-                                }
-                                else {
-                                    delete item.touched;
-                                }
-                            });
-                        }
-                    }
-                });
-                itemsForRemoval.forEach(function (item) {
-                    if (item.remove) {
-                        item.remove(false);
-                    }
-                });
-                if (updateAllAxes) {
-                    chart.axes.forEach(function (axis) {
-                        axis.update({}, false);
-                    });
-                }
-                // Certain options require the whole series structure to be thrown away
-                // and rebuilt
-                if (updateAllSeries) {
-                    chart.getSeriesOrderByLinks().forEach(function (series) {
-                        // Avoid removed navigator series
-                        if (series.chart) {
-                            series.update({}, false);
-                        }
-                    }, this);
-                }
-                // Update size. Redraw is forced.
-                newWidth = optionsChart && optionsChart.width;
-                newHeight = optionsChart && optionsChart.height;
-                if (isString(newHeight)) {
-                    newHeight = relativeLength(newHeight, newWidth || chart.chartWidth);
-                }
-                if (
-                // In this case, run chart.setSize with newWidth and newHeight which
-                // are undefined, only for reflowing chart elements because margin
-                // or spacing has been set (#8190)
-                runSetSize ||
-                    // In this case, the size is actually set
-                    (isNumber(newWidth) && newWidth !== chart.chartWidth) ||
-                    (isNumber(newHeight) && newHeight !== chart.chartHeight)) {
-                    chart.setSize(newWidth, newHeight, animation);
-                }
-                else if (pick(redraw, true)) {
-                    chart.redraw(animation);
-                }
-                fireEvent(chart, 'afterUpdate', {
-                    options: options,
-                    redraw: redraw,
-                    animation: animation
-                });
-            },
-            /**
-             * Shortcut to set the subtitle options. This can also be done from {@link
-             * Chart#update} or {@link Chart#setTitle}.
-             *
-             * @function Highcharts.Chart#setSubtitle
-             *
-             * @param {Highcharts.SubtitleOptions} options
-             *        New subtitle options. The subtitle text itself is set by the
-             *        `options.text` property.
-             */
-            setSubtitle: function (options, redraw) {
-                this.applyDescription('subtitle', options);
-                this.layOutTitles(redraw);
-            },
-            /**
-             * Set the caption options. This can also be done from {@link
-             * Chart#update}.
-             *
-             * @function Highcharts.Chart#setCaption
-             *
-             * @param {Highcharts.CaptionOptions} options
-             *        New caption options. The caption text itself is set by the
-             *        `options.text` property.
-             */
-            setCaption: function (options, redraw) {
-                this.applyDescription('caption', options);
-                this.layOutTitles(redraw);
+            [this.up, this.upTracker].forEach(function (elem) {
+              elem.attr({
+                class:
+                  currentPage === 1
+                    ? "highcharts-legend-nav-inactive"
+                    : "highcharts-legend-nav-active",
+              });
+            });
+            pager.attr({
+              text: currentPage + "/" + pageCount,
+            });
+            [this.down, this.downTracker].forEach(function (elem) {
+              elem.attr({
+                // adjust to text width
+                x: 18 + this.pager.getBBox().width,
+                class:
+                  currentPage === pageCount
+                    ? "highcharts-legend-nav-inactive"
+                    : "highcharts-legend-nav-active",
+              });
+            }, this);
+            if (!chart.styledMode) {
+              this.up.attr({
+                fill:
+                  currentPage === 1
+                    ? navOptions.inactiveColor
+                    : navOptions.activeColor,
+              });
+              this.upTracker.css({
+                cursor: currentPage === 1 ? "default" : "pointer",
+              });
+              this.down.attr({
+                fill:
+                  currentPage === pageCount
+                    ? navOptions.inactiveColor
+                    : navOptions.activeColor,
+              });
+              this.downTracker.css({
+                cursor: currentPage === pageCount ? "default" : "pointer",
+              });
             }
+            this.scrollOffset = -pages[currentPage - 1] + this.initialItemY;
+            this.scrollGroup.animate({
+              translateY: this.scrollOffset,
+            });
+            this.currentPage = currentPage;
+            this.positionCheckboxes();
+            // Fire event after scroll animation is complete
+            var animOptions = animObject(
+              pick(animation, chart.renderer.globalAnimation, true)
+            );
+            syncTimeout(function () {
+              fireEvent(_this, "afterScroll", { currentPage: currentPage });
+            }, animOptions.duration);
+          }
+        };
+        return Legend;
+      })();
+      // Workaround for #2030, horizontal legend items not displaying in IE11 Preview,
+      // and for #2580, a similar drawing flaw in Firefox 26.
+      // Explore if there's a general cause for this. The problem may be related
+      // to nested group elements, as the legend item texts are within 4 group
+      // elements.
+      if (
+        /Trident\/7\.0/.test(win.navigator && win.navigator.userAgent) ||
+        isFirefox
+      ) {
+        wrap(Legend.prototype, "positionItem", function (proceed, item) {
+          var legend = this,
+            // If chart destroyed in sync, this is undefined (#2030)
+            runPositionItem = function () {
+              if (item._legendItemPos) {
+                proceed.call(legend, item);
+              }
+            };
+          // Do it now, for export and to get checkbox placement
+          runPositionItem();
+          // Do it after to work around the core issue
+          if (!legend.bubbleLegend) {
+            setTimeout(runPositionItem);
+          }
         });
+      }
+      H.Legend = Legend;
+
+      return H.Legend;
+    }
+  );
+  _registerModule(
+    _modules,
+    "Core/Series/Point.js",
+    [
+      _modules["Core/Animation/AnimationUtilities.js"],
+      _modules["Core/Globals.js"],
+      _modules["Core/Utilities.js"],
+    ],
+    function (A, H, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      var animObject = A.animObject;
+      var defined = U.defined,
+        erase = U.erase,
+        extend = U.extend,
+        fireEvent = U.fireEvent,
+        format = U.format,
+        getNestedProperty = U.getNestedProperty,
+        isArray = U.isArray,
+        isNumber = U.isNumber,
+        isObject = U.isObject,
+        syncTimeout = U.syncTimeout,
+        pick = U.pick,
+        removeEvent = U.removeEvent,
+        uniqueKey = U.uniqueKey;
+      /**
+       * Function callback when a series point is clicked. Return false to cancel the
+       * action.
+       *
+       * @callback Highcharts.PointClickCallbackFunction
+       *
+       * @param {Highcharts.Point} this
+       *        The point where the event occured.
+       *
+       * @param {Highcharts.PointClickEventObject} event
+       *        Event arguments.
+       */
+      /**
+       * Common information for a click event on a series point.
+       *
+       * @interface Highcharts.PointClickEventObject
+       * @extends Highcharts.PointerEventObject
+       */ /**
+       * Clicked point.
+       * @name Highcharts.PointClickEventObject#point
+       * @type {Highcharts.Point}
+       */
+      /**
+       * Configuration hash for the data label and tooltip formatters.
+       *
+       * @interface Highcharts.PointLabelObject
+       */ /**
+       * The point's current color.
+       * @name Highcharts.PointLabelObject#color
+       * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject|undefined}
+       */ /**
+       * The point's current color index, used in styled mode instead of `color`. The
+       * color index is inserted in class names used for styling.
+       * @name Highcharts.PointLabelObject#colorIndex
+       * @type {number}
+       */ /**
+       * The name of the related point.
+       * @name Highcharts.PointLabelObject#key
+       * @type {string|undefined}
+       */ /**
+       * The percentage for related points in a stacked series or pies.
+       * @name Highcharts.PointLabelObject#percentage
+       * @type {number}
+       */ /**
+       * The related point. The point name, if defined, is available through
+       * `this.point.name`.
+       * @name Highcharts.PointLabelObject#point
+       * @type {Highcharts.Point}
+       */ /**
+       * The related series. The series name is available through `this.series.name`.
+       * @name Highcharts.PointLabelObject#series
+       * @type {Highcharts.Series}
+       */ /**
+       * The total of values in either a stack for stacked series, or a pie in a pie
+       * series.
+       * @name Highcharts.PointLabelObject#total
+       * @type {number|undefined}
+       */ /**
+       * For categorized axes this property holds the category name for the point. For
+       * other axes it holds the X value.
+       * @name Highcharts.PointLabelObject#x
+       * @type {number|string|undefined}
+       */ /**
+       * The y value of the point.
+       * @name Highcharts.PointLabelObject#y
+       * @type {number|undefined}
+       */
+      /**
+       * Gets fired when the mouse leaves the area close to the point.
+       *
+       * @callback Highcharts.PointMouseOutCallbackFunction
+       *
+       * @param {Highcharts.Point} this
+       *        Point where the event occured.
+       *
+       * @param {global.PointerEvent} event
+       *        Event that occured.
+       */
+      /**
+       * Gets fired when the mouse enters the area close to the point.
+       *
+       * @callback Highcharts.PointMouseOverCallbackFunction
+       *
+       * @param {Highcharts.Point} this
+       *        Point where the event occured.
+       *
+       * @param {global.Event} event
+       *        Event that occured.
+       */
+      /**
+       * The generic point options for all series.
+       *
+       * In TypeScript you have to extend `PointOptionsObject` with an additional
+       * declaration to allow custom data options:
+       *
+       * ```
+       * declare interface PointOptionsObject {
+       *     customProperty: string;
+       * }
+       * ```
+       *
+       * @interface Highcharts.PointOptionsObject
+       */
+      /**
+       * Possible option types for a data point. Use `null` to indicate a gap.
+       *
+       * @typedef {number|string|Highcharts.PointOptionsObject|Array<(number|string|null)>|null} Highcharts.PointOptionsType
+       */
+      /**
+       * Gets fired when the point is removed using the `.remove()` method.
+       *
+       * @callback Highcharts.PointRemoveCallbackFunction
+       *
+       * @param {Highcharts.Point} this
+       *        Point where the event occured.
+       *
+       * @param {global.Event} event
+       *        Event that occured.
+       */
+      /**
+       * Possible key values for the point state options.
+       *
+       * @typedef {"hover"|"inactive"|"normal"|"select"} Highcharts.PointStateValue
+       */
+      /**
+       * Gets fired when the point is updated programmatically through the `.update()`
+       * method.
+       *
+       * @callback Highcharts.PointUpdateCallbackFunction
+       *
+       * @param {Highcharts.Point} this
+       *        Point where the event occured.
+       *
+       * @param {Highcharts.PointUpdateEventObject} event
+       *        Event that occured.
+       */
+      /**
+       * Information about the update event.
+       *
+       * @interface Highcharts.PointUpdateEventObject
+       * @extends global.Event
+       */ /**
+       * Options data of the update event.
+       * @name Highcharts.PointUpdateEventObject#options
+       * @type {Highcharts.PointOptionsType}
+       */
+      (""); // detach doclet above
+      /* eslint-disable no-invalid-this, valid-jsdoc */
+      /**
+       * The Point object. The point objects are generated from the `series.data`
+       * configuration objects or raw numbers. They can be accessed from the
+       * `Series.points` array. Other ways to instantiate points are through {@link
+       * Highcharts.Series#addPoint} or {@link Highcharts.Series#setData}.
+       *
+       * @class
+       * @name Highcharts.Point
+       */
+      var Point = /** @class */ (function () {
+        function Point() {
+          /* *
+           *
+           *  Properties
+           *
+           * */
+          /**
+           * For categorized axes this property holds the category name for the
+           * point. For other axes it holds the X value.
+           *
+           * @name Highcharts.Point#category
+           * @type {string}
+           */
+          this.category = void 0;
+          /**
+           * The point's current color index, used in styled mode instead of
+           * `color`. The color index is inserted in class names used for styling.
+           *
+           * @name Highcharts.Point#colorIndex
+           * @type {number}
+           */
+          this.colorIndex = void 0;
+          this.formatPrefix = "point";
+          this.id = void 0;
+          this.isNull = false;
+          /**
+           * The name of the point. The name can be given as the first position of the
+           * point configuration array, or as a `name` property in the configuration:
+           *
+           * @example
+           * // Array config
+           * data: [
+           *     ['John', 1],
+           *     ['Jane', 2]
+           * ]
+           *
+           * // Object config
+           * data: [{
+           *        name: 'John',
+           *        y: 1
+           * }, {
+           *     name: 'Jane',
+           *     y: 2
+           * }]
+           *
+           * @name Highcharts.Point#name
+           * @type {string}
+           */
+          this.name = void 0;
+          /**
+           * The point's options as applied in the initial configuration, or
+           * extended through `Point.update`.
+           *
+           * In TypeScript you have to extend `PointOptionsObject` via an
+           * additional interface to allow custom data options:
+           *
+           * ```
+           * declare interface PointOptionsObject {
+           *     customProperty: string;
+           * }
+           * ```
+           *
+           * @name Highcharts.Point#options
+           * @type {Highcharts.PointOptionsObject}
+           */
+          this.options = void 0;
+          /**
+           * The percentage for points in a stacked series or pies.
+           *
+           * @name Highcharts.Point#percentage
+           * @type {number|undefined}
+           */
+          this.percentage = void 0;
+          this.selected = false;
+          /**
+           * The series object associated with the point.
+           *
+           * @name Highcharts.Point#series
+           * @type {Highcharts.Series}
+           */
+          this.series = void 0;
+          /**
+           * The total of values in either a stack for stacked series, or a pie in a
+           * pie series.
+           *
+           * @name Highcharts.Point#total
+           * @type {number|undefined}
+           */
+          this.total = void 0;
+          /**
+           * For certain series types, like pie charts, where individual points can
+           * be shown or hidden.
+           *
+           * @name Highcharts.Point#visible
+           * @type {boolean}
+           * @default true
+           */
+          this.visible = true;
+          this.x = void 0;
+        }
+        /* *
+         *
+         *  Functions
+         *
+         * */
+        /**
+         * Animate SVG elements associated with the point.
+         *
+         * @private
+         * @function Highcharts.Point#animateBeforeDestroy
+         */
+        Point.prototype.animateBeforeDestroy = function () {
+          var point = this,
+            animateParams = { x: point.startXPos, opacity: 0 },
+            isDataLabel,
+            graphicalProps = point.getGraphicalProps();
+          graphicalProps.singular.forEach(function (prop) {
+            isDataLabel = prop === "dataLabel";
+            point[prop] = point[prop].animate(
+              isDataLabel
+                ? {
+                    x: point[prop].startXPos,
+                    y: point[prop].startYPos,
+                    opacity: 0,
+                  }
+                : animateParams
+            );
+          });
+          graphicalProps.plural.forEach(function (plural) {
+            point[plural].forEach(function (item) {
+              if (item.element) {
+                item.animate(
+                  extend(
+                    { x: point.startXPos },
+                    item.startYPos
+                      ? {
+                          x: item.startXPos,
+                          y: item.startYPos,
+                        }
+                      : {}
+                  )
+                );
+              }
+            });
+          });
+        };
+        /**
+         * Apply the options containing the x and y data and possible some extra
+         * properties. Called on point init or from point.update.
+         *
+         * @private
+         * @function Highcharts.Point#applyOptions
+         *
+         * @param {Highcharts.PointOptionsType} options
+         *        The point options as defined in series.data.
+         *
+         * @param {number} [x]
+         *        Optionally, the x value.
+         *
+         * @return {Highcharts.Point}
+         *         The Point instance.
+         */
+        Point.prototype.applyOptions = function (options, x) {
+          var point = this,
+            series = point.series,
+            pointValKey = series.options.pointValKey || series.pointValKey;
+          options = Point.prototype.optionsToObject.call(this, options);
+          // copy options directly to point
+          extend(point, options);
+          point.options = point.options
+            ? extend(point.options, options)
+            : options;
+          // Since options are copied into the Point instance, some accidental
+          // options must be shielded (#5681)
+          if (options.group) {
+            delete point.group;
+          }
+          if (options.dataLabels) {
+            delete point.dataLabels;
+          }
+          /**
+           * The y value of the point.
+           * @name Highcharts.Point#y
+           * @type {number|undefined}
+           */
+          // For higher dimension series types. For instance, for ranges, point.y
+          // is mapped to point.low.
+          if (pointValKey) {
+            point.y = Point.prototype.getNestedProperty.call(
+              point,
+              pointValKey
+            );
+          }
+          point.isNull = pick(
+            point.isValid && !point.isValid(),
+            point.x === null || !isNumber(point.y)
+          ); // #3571, check for NaN
+          point.formatPrefix = point.isNull ? "null" : "point"; // #9233, #10874
+          // The point is initially selected by options (#5777)
+          if (point.selected) {
+            point.state = "select";
+          }
+          /**
+           * The x value of the point.
+           * @name Highcharts.Point#x
+           * @type {number}
+           */
+          // If no x is set by now, get auto incremented value. All points must
+          // have an x value, however the y value can be null to create a gap in
+          // the series
+          if (
+            "name" in point &&
+            typeof x === "undefined" &&
+            series.xAxis &&
+            series.xAxis.hasNames
+          ) {
+            point.x = series.xAxis.nameToX(point);
+          }
+          if (typeof point.x === "undefined" && series) {
+            if (typeof x === "undefined") {
+              point.x = series.autoIncrement(point);
+            } else {
+              point.x = x;
+            }
+          }
+          return point;
+        };
         /**
-         * These collections (arrays) implement `Chart.addSomethig` method used in
-         * chart.update() to create new object in the collection. Equivalent for
-         * deleting is resolved by simple `Somethig.remove()`.
+         * Destroy a point to clear memory. Its reference still stays in
+         * `series.data`.
          *
-         * Note: We need to define these references after initializers are bound to
-         * chart's prototype.
+         * @private
+         * @function Highcharts.Point#destroy
          */
-        Chart.prototype.collectionsWithInit = {
-            // collectionName: [ initializingMethod, [extraArguments] ]
-            xAxis: [Chart.prototype.addAxis, [true]],
-            yAxis: [Chart.prototype.addAxis, [false]],
-            series: [Chart.prototype.addSeries]
+        Point.prototype.destroy = function () {
+          var point = this,
+            series = point.series,
+            chart = series.chart,
+            dataSorting = series.options.dataSorting,
+            hoverPoints = chart.hoverPoints,
+            globalAnimation = point.series.chart.renderer.globalAnimation,
+            animation = animObject(globalAnimation),
+            prop;
+          /**
+           * Allow to call after animation.
+           * @private
+           */
+          function destroyPoint() {
+            // Remove all events and elements
+            if (point.graphic || point.dataLabel || point.dataLabels) {
+              removeEvent(point);
+              point.destroyElements();
+            }
+            for (prop in point) {
+              // eslint-disable-line guard-for-in
+              point[prop] = null;
+            }
+          }
+          if (point.legendItem) {
+            // pies have legend items
+            chart.legend.destroyItem(point);
+          }
+          if (hoverPoints) {
+            point.setState();
+            erase(hoverPoints, point);
+            if (!hoverPoints.length) {
+              chart.hoverPoints = null;
+            }
+          }
+          if (point === chart.hoverPoint) {
+            point.onMouseOut();
+          }
+          // Remove properties after animation
+          if (!dataSorting || !dataSorting.enabled) {
+            destroyPoint();
+          } else {
+            this.animateBeforeDestroy();
+            syncTimeout(destroyPoint, animation.duration);
+          }
+          chart.pointCount--;
         };
-        // extend the Point prototype for dynamic methods
-        extend(Point.prototype, /** @lends Highcharts.Point.prototype */ {
-            /**
-             * Update point with new options (typically x/y data) and optionally redraw
-             * the series.
-             *
-             * @sample highcharts/members/point-update-column/
-             *         Update column value
-             * @sample highcharts/members/point-update-pie/
-             *         Update pie slice
-             * @sample maps/members/point-update/
-             *         Update map area value in Highmaps
-             *
-             * @function Highcharts.Point#update
-             *
-             * @param {Highcharts.PointOptionsType} options
-             *        The point options. Point options are handled as described under
-             *        the `series.type.data` item for each series type. For example
-             *        for a line series, if options is a single number, the point will
-             *        be given that number as the marin y value. If it is an array, it
-             *        will be interpreted as x and y values respectively. If it is an
-             *        object, advanced options are applied.
-             *
-             * @param {boolean} [redraw=true]
-             *        Whether to redraw the chart after the point is updated. If doing
-             *        more operations on the chart, it is best practice to set
-             *        `redraw` to false and call `chart.redraw()` after.
-             *
-             * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation=true]
-             *        Whether to apply animation, and optionally animation
-             *        configuration.
-             *
-             * @return {void}
-             *
-             * @fires Highcharts.Point#event:update
-             */
-            update: function (options, redraw, animation, runEvent) {
-                var point = this,
-                    series = point.series,
-                    graphic = point.graphic,
-                    i,
-                    chart = series.chart,
-                    seriesOptions = series.options;
-                redraw = pick(redraw, true);
-                /**
-                 * @private
-                 */
-                function update() {
-                    point.applyOptions(options);
-                    // Update visuals, #4146
-                    // Handle dummy graphic elements for a11y, #12718
-                    var hasDummyGraphic = graphic && point.hasDummyGraphic;
-                    var shouldDestroyGraphic = point.y === null ? !hasDummyGraphic : hasDummyGraphic;
-                    if (graphic && shouldDestroyGraphic) {
-                        point.graphic = graphic.destroy();
-                        delete point.hasDummyGraphic;
-                    }
-                    if (isObject(options, true)) {
-                        // Destroy so we can get new elements
-                        if (graphic && graphic.element) {
-                            // "null" is also a valid symbol
-                            if (options &&
-                                options.marker &&
-                                typeof options.marker.symbol !== 'undefined') {
-                                point.graphic = graphic.destroy();
-                            }
-                        }
-                        if (options && options.dataLabels && point.dataLabel) {
-                            point.dataLabel = point.dataLabel.destroy(); // #2468
-                        }
-                        if (point.connector) {
-                            point.connector = point.connector.destroy(); // #7243
-                        }
-                    }
-                    // record changes in the parallel arrays
-                    i = point.index;
-                    series.updateParallelArrays(point, i);
-                    // Record the options to options.data. If the old or the new config
-                    // is an object, use point options, otherwise use raw options
-                    // (#4701, #4916).
-                    seriesOptions.data[i] = (isObject(seriesOptions.data[i], true) ||
-                        isObject(options, true)) ?
-                        point.options :
-                        pick(options, seriesOptions.data[i]);
-                    // redraw
-                    series.isDirty = series.isDirtyData = true;
-                    if (!series.fixedBox && series.hasCartesianSeries) { // #1906, #2320
-                        chart.isDirtyBox = true;
-                    }
-                    if (seriesOptions.legendType === 'point') { // #1831, #1885
-                        chart.isDirtyLegend = true;
-                    }
-                    if (redraw) {
-                        chart.redraw(animation);
-                    }
-                }
-                // Fire the event with a default handler of doing the update
-                if (runEvent === false) { // When called from setData
-                    update();
-                }
-                else {
-                    point.firePointEvent('update', { options: options }, update);
-                }
-            },
-            /**
-             * Remove a point and optionally redraw the series and if necessary the axes
-             *
-             * @sample highcharts/plotoptions/series-point-events-remove/
-             *         Remove point and confirm
-             * @sample highcharts/members/point-remove/
-             *         Remove pie slice
-             * @sample maps/members/point-remove/
-             *         Remove selected points in Highmaps
-             *
-             * @function Highcharts.Point#remove
-             *
-             * @param {boolean} [redraw=true]
-             *        Whether to redraw the chart or wait for an explicit call. When
-             *        doing more operations on the chart, for example running
-             *        `point.remove()` in a loop, it is best practice to set `redraw`
-             *        to false and call `chart.redraw()` after.
-             *
-             * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation=false]
-             *        Whether to apply animation, and optionally animation
-             *        configuration.
-             *
-             * @return {void}
-             */
-            remove: function (redraw, animation) {
-                this.series.removePoint(this.series.data.indexOf(this), redraw, animation);
+        /**
+         * Destroy SVG elements associated with the point.
+         *
+         * @private
+         * @function Highcharts.Point#destroyElements
+         * @param {Highcharts.Dictionary<number>} [kinds]
+         */
+        Point.prototype.destroyElements = function (kinds) {
+          var point = this,
+            props = point.getGraphicalProps(kinds);
+          props.singular.forEach(function (prop) {
+            point[prop] = point[prop].destroy();
+          });
+          props.plural.forEach(function (plural) {
+            point[plural].forEach(function (item) {
+              if (item.element) {
+                item.destroy();
+              }
+            });
+            delete point[plural];
+          });
+        };
+        /**
+         * Fire an event on the Point object.
+         *
+         * @private
+         * @function Highcharts.Point#firePointEvent
+         *
+         * @param {string} eventType
+         *        Type of the event.
+         *
+         * @param {Highcharts.Dictionary<any>|Event} [eventArgs]
+         *        Additional event arguments.
+         *
+         * @param {Highcharts.EventCallbackFunction<Highcharts.Point>|Function} [defaultFunction]
+         *        Default event handler.
+         *
+         * @fires Highcharts.Point#event:*
+         */
+        Point.prototype.firePointEvent = function (
+          eventType,
+          eventArgs,
+          defaultFunction
+        ) {
+          var point = this,
+            series = this.series,
+            seriesOptions = series.options;
+          // load event handlers on demand to save time on mouseover/out
+          if (
+            seriesOptions.point.events[eventType] ||
+            (point.options &&
+              point.options.events &&
+              point.options.events[eventType])
+          ) {
+            point.importEvents();
+          }
+          // add default handler if in selection mode
+          if (eventType === "click" && seriesOptions.allowPointSelect) {
+            defaultFunction = function (event) {
+              // Control key is for Windows, meta (= Cmd key) for Mac, Shift
+              // for Opera.
+              if (point.select) {
+                // #2911
+                point.select(
+                  null,
+                  event.ctrlKey || event.metaKey || event.shiftKey
+                );
+              }
+            };
+          }
+          fireEvent(point, eventType, eventArgs, defaultFunction);
+        };
+        /**
+         * Get the CSS class names for individual points. Used internally where the
+         * returned value is set on every point.
+         *
+         * @function Highcharts.Point#getClassName
+         *
+         * @return {string}
+         *         The class names.
+         */
+        Point.prototype.getClassName = function () {
+          var point = this;
+          return (
+            "highcharts-point" +
+            (point.selected ? " highcharts-point-select" : "") +
+            (point.negative ? " highcharts-negative" : "") +
+            (point.isNull ? " highcharts-null-point" : "") +
+            (typeof point.colorIndex !== "undefined"
+              ? " highcharts-color-" + point.colorIndex
+              : "") +
+            (point.options.className ? " " + point.options.className : "") +
+            (point.zone && point.zone.className
+              ? " " + point.zone.className.replace("highcharts-negative", "")
+              : "")
+          );
+        };
+        /**
+         * Get props of all existing graphical point elements.
+         *
+         * @private
+         * @function Highcharts.Point#getGraphicalProps
+         * @param {Highcharts.Dictionary<number>} [kinds]
+         * @return {Highcharts.PointGraphicalProps}
+         */
+        Point.prototype.getGraphicalProps = function (kinds) {
+          var point = this,
+            props = [],
+            prop,
+            i,
+            graphicalProps = { singular: [], plural: [] };
+          kinds = kinds || { graphic: 1, dataLabel: 1 };
+          if (kinds.graphic) {
+            props.push("graphic", "shadowGroup");
+          }
+          if (kinds.dataLabel) {
+            props.push("dataLabel", "dataLabelUpper", "connector");
+          }
+          i = props.length;
+          while (i--) {
+            prop = props[i];
+            if (point[prop]) {
+              graphicalProps.singular.push(prop);
             }
-        });
-        // Extend the series prototype for dynamic methods
-        extend(LineSeries.prototype, /** @lends Series.prototype */ {
-            /**
-             * Add a point to the series after render time. The point can be added at
-             * the end, or by giving it an X value, to the start or in the middle of the
-             * series.
-             *
-             * @sample highcharts/members/series-addpoint-append/
-             *         Append point
-             * @sample highcharts/members/series-addpoint-append-and-shift/
-             *         Append and shift
-             * @sample highcharts/members/series-addpoint-x-and-y/
-             *         Both X and Y values given
-             * @sample highcharts/members/series-addpoint-pie/
-             *         Append pie slice
-             * @sample stock/members/series-addpoint/
-             *         Append 100 points in Highstock
-             * @sample stock/members/series-addpoint-shift/
-             *         Append and shift in Highstock
-             * @sample maps/members/series-addpoint/
-             *         Add a point in Highmaps
-             *
-             * @function Highcharts.Series#addPoint
-             *
-             * @param {Highcharts.PointOptionsType} options
-             *        The point options. If options is a single number, a point with
-             *        that y value is appended to the series. If it is an array, it will
-             *        be interpreted as x and y values respectively. If it is an
-             *        object, advanced options as outlined under `series.data` are
-             *        applied.
-             *
-             * @param {boolean} [redraw=true]
-             *        Whether to redraw the chart after the point is added. When adding
-             *        more than one point, it is highly recommended that the redraw
-             *        option be set to false, and instead {@link Chart#redraw} is
-             *        explicitly called after the adding of points is finished.
-             *        Otherwise, the chart will redraw after adding each point.
-             *
-             * @param {boolean} [shift=false]
-             *        If true, a point is shifted off the start of the series as one is
-             *        appended to the end.
-             *
-             * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation]
-             *        Whether to apply animation, and optionally animation
-             *        configuration.
-             *
-             * @param {boolean} [withEvent=true]
-             *        Used internally, whether to fire the series `addPoint` event.
-             *
-             * @return {void}
-             *
-             * @fires Highcharts.Series#event:addPoint
-             */
-            addPoint: function (options, redraw, shift, animation, withEvent) {
-                var series = this,
-                    seriesOptions = series.options,
-                    data = series.data,
-                    chart = series.chart,
-                    xAxis = series.xAxis,
-                    names = xAxis && xAxis.hasNames && xAxis.names,
-                    dataOptions = seriesOptions.data,
-                    point,
-                    xData = series.xData,
-                    isInTheMiddle,
-                    i,
-                    x;
-                // Optional redraw, defaults to true
-                redraw = pick(redraw, true);
-                // Get options and push the point to xData, yData and series.options. In
-                // series.generatePoints the Point instance will be created on demand
-                // and pushed to the series.data array.
-                point = { series: series };
-                series.pointClass.prototype.applyOptions.apply(point, [options]);
-                x = point.x;
-                // Get the insertion point
-                i = xData.length;
-                if (series.requireSorting && x < xData[i - 1]) {
-                    isInTheMiddle = true;
-                    while (i && xData[i - 1] > x) {
-                        i--;
-                    }
-                }
-                // Insert undefined item
-                series.updateParallelArrays(point, 'splice', i, 0, 0);
-                // Update it
-                series.updateParallelArrays(point, i);
-                if (names && point.name) {
-                    names[x] = point.name;
-                }
-                dataOptions.splice(i, 0, options);
-                if (isInTheMiddle) {
-                    series.data.splice(i, 0, null);
-                    series.processData();
-                }
-                // Generate points to be added to the legend (#1329)
-                if (seriesOptions.legendType === 'point') {
-                    series.generatePoints();
-                }
-                // Shift the first point off the parallel arrays
-                if (shift) {
-                    if (data[0] && data[0].remove) {
-                        data[0].remove(false);
-                    }
-                    else {
-                        data.shift();
-                        series.updateParallelArrays(point, 'shift');
-                        dataOptions.shift();
-                    }
-                }
-                // Fire event
-                if (withEvent !== false) {
-                    fireEvent(series, 'addPoint', { point: point });
-                }
-                // redraw
-                series.isDirty = true;
-                series.isDirtyData = true;
-                if (redraw) {
-                    chart.redraw(animation); // Animation is set anyway on redraw, #5665
-                }
-            },
-            /**
-             * Remove a point from the series. Unlike the
-             * {@link Highcharts.Point#remove} method, this can also be done on a point
-             * that is not instanciated because it is outside the view or subject to
-             * Highstock data grouping.
-             *
-             * @sample highcharts/members/series-removepoint/
-             *         Remove cropped point
-             *
-             * @function Highcharts.Series#removePoint
-             *
-             * @param {number} i
-             *        The index of the point in the {@link Highcharts.Series.data|data}
-             *        array.
-             *
-             * @param {boolean} [redraw=true]
-             *        Whether to redraw the chart after the point is added. When
-             *        removing more than one point, it is highly recommended that the
-             *        `redraw` option be set to `false`, and instead {@link
-             *        Highcharts.Chart#redraw} is explicitly called after the adding of
-             *        points is finished.
-             *
-             * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation]
-             *        Whether and optionally how the series should be animated.
-             *
-             * @return {void}
-             *
-             * @fires Highcharts.Point#event:remove
-             */
-            removePoint: function (i, redraw, animation) {
-                var series = this,
-                    data = series.data,
-                    point = data[i],
-                    points = series.points,
-                    chart = series.chart,
-                    remove = function () {
-                        if (points && points.length === data.length) { // #4935
-                            points.splice(i, 1);
-                    }
-                    data.splice(i, 1);
-                    series.options.data.splice(i, 1);
-                    series.updateParallelArrays(point || { series: series }, 'splice', i, 1);
-                    if (point) {
-                        point.destroy();
-                    }
-                    // redraw
-                    series.isDirty = true;
-                    series.isDirtyData = true;
-                    if (redraw) {
-                        chart.redraw();
-                    }
-                };
-                setAnimation(animation, chart);
-                redraw = pick(redraw, true);
-                // Fire the event with a default handler of removing the point
-                if (point) {
-                    point.firePointEvent('remove', null, remove);
-                }
-                else {
-                    remove();
-                }
-            },
-            /**
-             * Remove a series and optionally redraw the chart.
-             *
-             * @sample highcharts/members/series-remove/
-             *         Remove first series from a button
-             *
-             * @function Highcharts.Series#remove
-             *
-             * @param {boolean} [redraw=true]
-             *        Whether to redraw the chart or wait for an explicit call to
-             *        {@link Highcharts.Chart#redraw}.
-             *
-             * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation]
-             *        Whether to apply animation, and optionally animation
-             *        configuration.
-             *
-             * @param {boolean} [withEvent=true]
-             *        Used internally, whether to fire the series `remove` event.
-             *
-             * @return {void}
-             *
-             * @fires Highcharts.Series#event:remove
-             */
-            remove: function (redraw, animation, withEvent, keepEvents) {
-                var series = this,
-                    chart = series.chart;
-                /**
-                 * @private
-                 */
-                function remove() {
-                    // Destroy elements
-                    series.destroy(keepEvents);
-                    series.remove = null; // Prevent from doing again (#9097)
-                    // Redraw
-                    chart.isDirtyLegend = chart.isDirtyBox = true;
-                    chart.linkSeries();
-                    if (pick(redraw, true)) {
-                        chart.redraw(animation);
-                    }
-                }
-                // Fire the event with a default handler of removing the point
-                if (withEvent !== false) {
-                    fireEvent(series, 'remove', null, remove);
-                }
-                else {
-                    remove();
-                }
-            },
-            /**
-             * Update the series with a new set of options. For a clean and precise
-             * handling of new options, all methods and elements from the series are
-             * removed, and it is initialized from scratch. Therefore, this method is
-             * more performance expensive than some other utility methods like {@link
-             * Series#setData} or {@link Series#setVisible}.
-             *
-             * Note that `Series.update` may mutate the passed `data` options.
-             *
-             * @sample highcharts/members/series-update/
-             *         Updating series options
-             * @sample maps/members/series-update/
-             *         Update series options in Highmaps
-             *
-             * @function Highcharts.Series#update
-             *
-             * @param {Highcharts.SeriesOptionsType} options
-             *        New options that will be merged with the series' existing options.
-             *
-             * @param {boolean} [redraw=true]
-             *        Whether to redraw the chart after the series is altered. If doing
-             *        more operations on the chart, it is a good idea to set redraw to
-             *        false and call {@link Chart#redraw} after.
-             *
-             * @return {void}
-             *
-             * @fires Highcharts.Series#event:update
-             * @fires Highcharts.Series#event:afterUpdate
-             */
-            update: function (options, redraw) {
-                options = H.cleanRecursively(options, this.userOptions);
-                fireEvent(this, 'update', { options: options });
-                var series = this,
-                    chart = series.chart, 
-                    // must use user options when changing type because series.options
-                    // is merged in with type specific plotOptions
-                    oldOptions = series.userOptions,
-                    seriesOptions,
-                    initialType = series.initialType || series.type,
-                    plotOptions = chart.options.plotOptions,
-                    newType = (options.type ||
-                        oldOptions.type ||
-                        chart.options.chart.type),
-                    keepPoints = !(
-                    // Indicators, histograms etc recalculate the data. It should be
-                    // possible to omit this.
-                    this.hasDerivedData ||
-                        // New type requires new point classes
-                        (newType && newType !== this.type) ||
-                        // New options affecting how the data points are built
-                        typeof options.pointStart !== 'undefined' ||
-                        typeof options.pointInterval !== 'undefined' ||
-                        // Changes to data grouping requires new points in new group
-                        series.hasOptionChanged('dataGrouping') ||
-                        series.hasOptionChanged('pointStart') ||
-                        series.hasOptionChanged('pointInterval') ||
-                        series.hasOptionChanged('pointIntervalUnit') ||
-                        series.hasOptionChanged('keys')),
-                    initialSeriesProto = seriesTypes[initialType].prototype,
-                    n,
-                    groups = [
-                        'group',
-                        'markerGroup',
-                        'dataLabelsGroup',
-                        'transformGroup'
-                    ],
-                    preserve = [
-                        'eventOptions',
-                        'navigatorSeries',
-                        'baseSeries'
-                    ], 
-                    // Animation must be enabled when calling update before the initial
-                    // animation has first run. This happens when calling update
-                    // directly after chart initialization, or when applying responsive
-                    // rules (#6912).
-                    animation = series.finishedAnimating && { animation: false },
-                    kinds = {};
-                if (keepPoints) {
-                    preserve.push('data', 'isDirtyData', 'points', 'processedXData', 'processedYData', 'xIncrement', 'cropped', '_hasPointMarkers', '_hasPointLabels', 
-                    // Map specific, consider moving it to series-specific preserve-
-                    // properties (#10617)
-                    'mapMap', 'mapData', 'minY', 'maxY', 'minX', 'maxX');
-                    if (options.visible !== false) {
-                        preserve.push('area', 'graph');
-                    }
-                    series.parallelArrays.forEach(function (key) {
-                        preserve.push(key + 'Data');
-                    });
-                    if (options.data) {
-                        // setData uses dataSorting options so we need to update them
-                        // earlier
-                        if (options.dataSorting) {
-                            extend(series.options.dataSorting, options.dataSorting);
-                        }
-                        this.setData(options.data, false);
-                    }
-                }
-                // Do the merge, with some forced options
-                options = merge(oldOptions, animation, {
-                    // When oldOptions.index is null it should't be cleared.
-                    // Otherwise navigator series will have wrong indexes (#10193).
-                    index: typeof oldOptions.index === 'undefined' ?
-                        series.index : oldOptions.index,
-                    pointStart: pick(
-                    // when updating from blank (#7933)
-                    plotOptions && plotOptions.series && plotOptions.series.pointStart, oldOptions.pointStart, 
-                    // when updating after addPoint
-                    series.xData[0])
-                }, (!keepPoints && { data: series.options.data }), options);
-                // Merge does not merge arrays, but replaces them. Since points were
-                // updated, `series.options.data` has correct merged options, use it:
-                if (keepPoints && options.data) {
-                    options.data = series.options.data;
-                }
-                // Make sure preserved properties are not destroyed (#3094)
-                preserve = groups.concat(preserve);
-                preserve.forEach(function (prop) {
-                    preserve[prop] = series[prop];
-                    delete series[prop];
-                });
-                // Destroy the series and delete all properties. Reinsert all
-                // methods and properties from the new type prototype (#2270,
-                // #3719).
-                series.remove(false, null, false, true);
-                for (n in initialSeriesProto) { // eslint-disable-line guard-for-in
-                    series[n] = void 0;
-                }
-                if (seriesTypes[newType || initialType]) {
-                    extend(series, seriesTypes[newType || initialType].prototype);
-                }
-                else {
-                    error(17, true, chart, { missingModuleFor: (newType || initialType) });
-                }
-                // Re-register groups (#3094) and other preserved properties
-                preserve.forEach(function (prop) {
-                    series[prop] = preserve[prop];
-                });
-                series.init(chart, options);
-                // Remove particular elements of the points. Check `series.options`
-                // because we need to consider the options being set on plotOptions as
-                // well.
-                if (keepPoints && this.points) {
-                    seriesOptions = series.options;
-                    // What kind of elements to destroy
-                    if (seriesOptions.visible === false) {
-                        kinds.graphic = 1;
-                        kinds.dataLabel = 1;
-                    }
-                    else if (!series._hasPointLabels) {
-                        var marker = seriesOptions.marker,
-                            dataLabels = seriesOptions.dataLabels;
-                        if (marker && (marker.enabled === false ||
-                            'symbol' in marker // #10870
-                        )) {
-                            kinds.graphic = 1;
-                        }
-                        if (dataLabels &&
-                            dataLabels.enabled === false) {
-                            kinds.dataLabel = 1;
-                        }
-                    }
-                    this.points.forEach(function (point) {
-                        if (point && point.series) {
-                            point.resolveColor();
-                            // Destroy elements in order to recreate based on updated
-                            // series options.
-                            if (Object.keys(kinds).length) {
-                                point.destroyElements(kinds);
-                            }
-                            if (seriesOptions.showInLegend === false &&
-                                point.legendItem) {
-                                chart.legend.destroyItem(point);
-                            }
-                        }
-                    }, this);
-                }
-                series.initialType = initialType;
-                chart.linkSeries(); // Links are lost in series.remove (#3028)
-                fireEvent(this, 'afterUpdate');
-                if (pick(redraw, true)) {
-                    chart.redraw(keepPoints ? void 0 : false);
-                }
-            },
-            /**
-             * Used from within series.update
-             *
-             * @private
-             * @function Highcharts.Series#setName
-             *
-             * @param {string} name
-             *
-             * @return {void}
-             */
-            setName: function (name) {
-                this.name = this.options.name = this.userOptions.name = name;
-                this.chart.isDirtyLegend = true;
-            },
-            /**
-             * Check if the option has changed.
-             *
-             * @private
-             * @function Highcharts.Series#hasOptionChanged
-             *
-             * @param {string} option
-             *
-             * @return {boolean}
-             */
-            hasOptionChanged: function (optionName) {
-                var chart = this.chart,
-                    option = this.options[optionName],
-                    plotOptions = chart.options.plotOptions,
-                    oldOption = this.userOptions[optionName];
-                if (oldOption) {
-                    return option !== oldOption;
-                }
-                return option !==
-                    pick(plotOptions && plotOptions[this.type] && plotOptions[this.type][optionName], plotOptions && plotOptions.series && plotOptions.series[optionName], option);
+          }
+          ["dataLabel", "connector"].forEach(function (prop) {
+            var plural = prop + "s";
+            if (kinds[prop] && point[plural]) {
+              graphicalProps.plural.push(plural);
             }
-        });
-        // Extend the Axis.prototype for dynamic methods
-        extend(Axis.prototype, /** @lends Highcharts.Axis.prototype */ {
-            /**
-             * Update an axis object with a new set of options. The options are merged
-             * with the existing options, so only new or altered options need to be
-             * specified.
-             *
-             * @sample highcharts/members/axis-update/
-             *         Axis update demo
-             *
-             * @function Highcharts.Axis#update
-             *
-             * @param {Highcharts.AxisOptions} options
-             *        The new options that will be merged in with existing options on
-             *        the axis.
-             *
-             * @param {boolean} [redraw=true]
-             *        Whether to redraw the chart after the axis is altered. If doing
-             *        more operations on the chart, it is a good idea to set redraw to
-             *        false and call {@link Chart#redraw} after.
-             *
-             * @return {void}
-             */
-            update: function (options, redraw) {
-                var chart = this.chart,
-                    newEvents = ((options && options.events) || {});
-                options = merge(this.userOptions, options);
-                // Color Axis is not an array,
-                // This change is applied in the ColorAxis wrapper
-                if (chart.options[this.coll].indexOf) {
-                    // Don't use this.options.index,
-                    // StockChart has Axes in navigator too
-                    chart.options[this.coll][chart.options[this.coll].indexOf(this.userOptions)] = options;
-                }
-                // Remove old events, if no new exist (#8161)
-                objectEach(chart.options[this.coll].events, function (fn, ev) {
-                    if (typeof newEvents[ev] === 'undefined') {
-                        newEvents[ev] = void 0;
-                    }
-                });
-                this.destroy(true);
-                this.init(chart, extend(options, { events: newEvents }));
-                chart.isDirtyBox = true;
-                if (pick(redraw, true)) {
-                    chart.redraw();
-                }
-            },
-            /**
-             * Remove the axis from the chart.
-             *
-             * @sample highcharts/members/chart-addaxis/
-             *         Add and remove axes
-             *
-             * @function Highcharts.Axis#remove
-             *
-             * @param {boolean} [redraw=true]
-             *        Whether to redraw the chart following the remove.
-             *
-             * @return {void}
-             */
-            remove: function (redraw) {
-                var chart = this.chart,
-                    key = this.coll, // xAxis or yAxis
-                    axisSeries = this.series,
-                    i = axisSeries.length;
-                // Remove associated series (#2687)
-                while (i--) {
-                    if (axisSeries[i]) {
-                        axisSeries[i].remove(false);
-                    }
-                }
-                // Remove the axis
-                erase(chart.axes, this);
-                erase(chart[key], this);
-                if (isArray(chart.options[key])) {
-                    chart.options[key].splice(this.options.index, 1);
-                }
-                else { // color axis, #6488
-                    delete chart.options[key];
-                }
-                chart[key].forEach(function (axis, i) {
-                    // Re-index, #1706, #8075
-                    axis.options.index = axis.userOptions.index = i;
-                });
-                this.destroy();
-                chart.isDirtyBox = true;
-                if (pick(redraw, true)) {
-                    chart.redraw();
-                }
-            },
-            /**
-             * Update the axis title by options after render time.
-             *
-             * @sample highcharts/members/axis-settitle/
-             *         Set a new Y axis title
-             *
-             * @function Highcharts.Axis#setTitle
-             *
-             * @param {Highcharts.AxisTitleOptions} titleOptions
-             *        The additional title options.
-             *
-             * @param {boolean} [redraw=true]
-             *        Whether to redraw the chart after setting the title.
-             *
-             * @return {void}
-             */
-            setTitle: function (titleOptions, redraw) {
-                this.update({ title: titleOptions }, redraw);
-            },
-            /**
-             * Set new axis categories and optionally redraw.
-             *
-             * @sample highcharts/members/axis-setcategories/
-             *         Set categories by click on a button
-             *
-             * @function Highcharts.Axis#setCategories
-             *
-             * @param {Array<string>} categories
-             *        The new categories.
-             *
-             * @param {boolean} [redraw=true]
-             *        Whether to redraw the chart.
-             *
-             * @return {void}
-             */
-            setCategories: function (categories, redraw) {
-                this.update({ categories: categories }, redraw);
+          });
+          return graphicalProps;
+        };
+        /**
+         * Return the configuration hash needed for the data label and tooltip
+         * formatters.
+         *
+         * @function Highcharts.Point#getLabelConfig
+         *
+         * @return {Highcharts.PointLabelObject}
+         *         Abstract object used in formatters and formats.
+         */
+        Point.prototype.getLabelConfig = function () {
+          return {
+            x: this.category,
+            y: this.y,
+            color: this.color,
+            colorIndex: this.colorIndex,
+            key: this.name || this.category,
+            series: this.series,
+            point: this,
+            percentage: this.percentage,
+            total: this.total || this.stackTotal,
+          };
+        };
+        /**
+         * Returns the value of the point property for a given value.
+         * @private
+         */
+        Point.prototype.getNestedProperty = function (key) {
+          if (!key) {
+            return;
+          }
+          if (key.indexOf("custom.") === 0) {
+            return getNestedProperty(key, this.options);
+          }
+          return this[key];
+        };
+        /**
+         * In a series with `zones`, return the zone that the point belongs to.
+         *
+         * @function Highcharts.Point#getZone
+         *
+         * @return {Highcharts.SeriesZonesOptionsObject}
+         *         The zone item.
+         */
+        Point.prototype.getZone = function () {
+          var series = this.series,
+            zones = series.zones,
+            zoneAxis = series.zoneAxis || "y",
+            i = 0,
+            zone;
+          zone = zones[i];
+          while (this[zoneAxis] >= zone.value) {
+            zone = zones[++i];
+          }
+          // For resetting or reusing the point (#8100)
+          if (!this.nonZonedColor) {
+            this.nonZonedColor = this.color;
+          }
+          if (zone && zone.color && !this.options.color) {
+            this.color = zone.color;
+          } else {
+            this.color = this.nonZonedColor;
+          }
+          return zone;
+        };
+        /**
+         * Utility to check if point has new shape type. Used in column series and
+         * all others that are based on column series.
+         *
+         * @return boolean|undefined
+         */
+        Point.prototype.hasNewShapeType = function () {
+          var point = this;
+          var oldShapeType =
+            point.graphic &&
+            (point.graphic.symbolName || point.graphic.element.nodeName);
+          return oldShapeType !== this.shapeType;
+        };
+        /**
+         * Initialize the point. Called internally based on the `series.data`
+         * option.
+         *
+         * @function Highcharts.Point#init
+         *
+         * @param {Highcharts.Series} series
+         *        The series object containing this point.
+         *
+         * @param {Highcharts.PointOptionsType} options
+         *        The data in either number, array or object format.
+         *
+         * @param {number} [x]
+         *        Optionally, the X value of the point.
+         *
+         * @return {Highcharts.Point}
+         *         The Point instance.
+         *
+         * @fires Highcharts.Point#event:afterInit
+         */
+        Point.prototype.init = function (series, options, x) {
+          this.series = series;
+          this.applyOptions(options, x);
+          // Add a unique ID to the point if none is assigned
+          this.id = defined(this.id) ? this.id : uniqueKey();
+          this.resolveColor();
+          series.chart.pointCount++;
+          fireEvent(this, "afterInit");
+          return this;
+        };
+        /**
+         * Transform number or array configs into objects. Also called for object
+         * configs. Used internally to unify the different configuration formats for
+         * points. For example, a simple number `10` in a line series will be
+         * transformed to `{ y: 10 }`, and an array config like `[1, 10]` in a
+         * scatter series will be transformed to `{ x: 1, y: 10 }`.
+         *
+         * @function Highcharts.Point#optionsToObject
+         *
+         * @param {Highcharts.PointOptionsType} options
+         *        The input option.
+         *
+         * @return {Highcharts.Dictionary<*>}
+         *         Transformed options.
+         */
+        Point.prototype.optionsToObject = function (options) {
+          var ret = {},
+            series = this.series,
+            keys = series.options.keys,
+            pointArrayMap = keys || series.pointArrayMap || ["y"],
+            valueCount = pointArrayMap.length,
+            firstItemType,
+            i = 0,
+            j = 0;
+          if (isNumber(options) || options === null) {
+            ret[pointArrayMap[0]] = options;
+          } else if (isArray(options)) {
+            // with leading x value
+            if (!keys && options.length > valueCount) {
+              firstItemType = typeof options[0];
+              if (firstItemType === "string") {
+                ret.name = options[0];
+              } else if (firstItemType === "number") {
+                ret.x = options[0];
+              }
+              i++;
+            }
+            while (j < valueCount) {
+              // Skip undefined positions for keys
+              if (!keys || typeof options[i] !== "undefined") {
+                if (pointArrayMap[j].indexOf(".") > 0) {
+                  // Handle nested keys, e.g. ['color.pattern.image']
+                  // Avoid function call unless necessary.
+                  Point.prototype.setNestedProperty(
+                    ret,
+                    options[i],
+                    pointArrayMap[j]
+                  );
+                } else {
+                  ret[pointArrayMap[j]] = options[i];
+                }
+              }
+              i++;
+              j++;
+            }
+          } else if (typeof options === "object") {
+            ret = options;
+            // This is the fastest way to detect if there are individual point
+            // dataLabels that need to be considered in drawDataLabels. These
+            // can only occur in object configs.
+            if (options.dataLabels) {
+              series._hasPointLabels = true;
+            }
+            // Same approach as above for markers
+            if (options.marker) {
+              series._hasPointMarkers = true;
+            }
+          }
+          return ret;
+        };
+        /**
+         * @private
+         * @function Highcharts.Point#resolveColor
+         * @return {void}
+         */
+        Point.prototype.resolveColor = function () {
+          var series = this.series,
+            colors,
+            optionsChart = series.chart.options.chart,
+            colorCount = optionsChart.colorCount,
+            styledMode = series.chart.styledMode,
+            colorIndex;
+          // remove points nonZonedColor for later recalculation
+          delete this.nonZonedColor;
+          /**
+           * The point's current color.
+           *
+           * @name Highcharts.Point#color
+           * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject|undefined}
+           */
+          if (!styledMode && !this.options.color) {
+            this.color = series.color; // #3445
+          }
+          if (series.options.colorByPoint) {
+            if (!styledMode) {
+              colors = series.options.colors || series.chart.options.colors;
+              this.color = this.color || colors[series.colorCounter];
+              colorCount = colors.length;
+            }
+            colorIndex = series.colorCounter;
+            series.colorCounter++;
+            // loop back to zero
+            if (series.colorCounter === colorCount) {
+              series.colorCounter = 0;
+            }
+          } else {
+            colorIndex = series.colorIndex;
+          }
+          this.colorIndex = pick(this.colorIndex, colorIndex);
+        };
+        /**
+         * Set a value in an object, on the property defined by key. The key
+         * supports nested properties using dot notation. The function modifies the
+         * input object and does not make a copy.
+         *
+         * @function Highcharts.Point#setNestedProperty<T>
+         *
+         * @param {T} object
+         *        The object to set the value on.
+         *
+         * @param {*} value
+         *        The value to set.
+         *
+         * @param {string} key
+         *        Key to the property to set.
+         *
+         * @return {T}
+         *         The modified object.
+         */
+        Point.prototype.setNestedProperty = function (object, value, key) {
+          var nestedKeys = key.split(".");
+          nestedKeys.reduce(function (result, key, i, arr) {
+            var isLastKey = arr.length - 1 === i;
+            result[key] = isLastKey
+              ? value
+              : isObject(result[key], true)
+              ? result[key]
+              : {};
+            return result[key];
+          }, object);
+          return object;
+        };
+        /**
+         * Extendable method for formatting each point's tooltip line.
+         *
+         * @function Highcharts.Point#tooltipFormatter
+         *
+         * @param {string} pointFormat
+         *        The point format.
+         *
+         * @return {string}
+         *         A string to be concatenated in to the common tooltip text.
+         */
+        Point.prototype.tooltipFormatter = function (pointFormat) {
+          // Insert options for valueDecimals, valuePrefix, and valueSuffix
+          var series = this.series,
+            seriesTooltipOptions = series.tooltipOptions,
+            valueDecimals = pick(seriesTooltipOptions.valueDecimals, ""),
+            valuePrefix = seriesTooltipOptions.valuePrefix || "",
+            valueSuffix = seriesTooltipOptions.valueSuffix || "";
+          // Replace default point style with class name
+          if (series.chart.styledMode) {
+            pointFormat = series.chart.tooltip.styledModeFormat(pointFormat);
+          }
+          // Loop over the point array map and replace unformatted values with
+          // sprintf formatting markup
+          (series.pointArrayMap || ["y"]).forEach(function (key) {
+            key = "{point." + key; // without the closing bracket
+            if (valuePrefix || valueSuffix) {
+              pointFormat = pointFormat.replace(
+                RegExp(key + "}", "g"),
+                valuePrefix + key + "}" + valueSuffix
+              );
             }
-        });
+            pointFormat = pointFormat.replace(
+              RegExp(key + "}", "g"),
+              key + ":,." + valueDecimals + "f}"
+            );
+          });
+          return format(
+            pointFormat,
+            {
+              point: this,
+              series: this.series,
+            },
+            series.chart
+          );
+        };
+        return Point;
+      })();
+      H.Point = Point;
 
-    });
-    _registerModule(_modules, 'Series/AreaSeries.js', [_modules['Core/Series/Series.js'], _modules['Core/Color/Color.js'], _modules['Core/Globals.js'], _modules['Mixins/LegendSymbol.js'], _modules['Core/Utilities.js']], function (BaseSeries, Color, H, LegendSymbolMixin, U) {
+      return Point;
+    }
+  );
+  _registerModule(
+    _modules,
+    "Core/Series/Series.js",
+    [
+      _modules["Core/Globals.js"],
+      _modules["Core/Series/Point.js"],
+      _modules["Core/Utilities.js"],
+    ],
+    function (H, Point, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      var error = U.error,
+        extendClass = U.extendClass,
+        fireEvent = U.fireEvent,
+        getOptions = U.getOptions,
+        isObject = U.isObject,
+        merge = U.merge,
+        objectEach = U.objectEach;
+      /**
+       * @class
+       * @name Highcharts.Series
+       */
+      var BaseSeries = /** @class */ (function () {
         /* *
          *
-         *  (c) 2010-2020 Torstein Honsi
+         *  Constructor
          *
-         *  License: www.highcharts.com/license
+         * */
+        function BaseSeries(chart, options) {
+          var mergedOptions = merge(BaseSeries.defaultOptions, options);
+          this.chart = chart;
+          this._i = chart.series.length;
+          chart.series.push(this);
+          this.options = mergedOptions;
+          this.userOptions = merge(options);
+        }
+        /* *
          *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+         *  Static Functions
          *
          * */
-        var color = Color.parse;
-        var objectEach = U.objectEach,
-            pick = U.pick;
-        var Series = H.Series;
+        BaseSeries.addSeries = function (seriesName, seriesType) {
+          BaseSeries.seriesTypes[seriesName] = seriesType;
+        };
+        BaseSeries.cleanRecursively = function (toClean, reference) {
+          var clean = {};
+          objectEach(toClean, function (_val, key) {
+            var ob;
+            // Dive into objects (except DOM nodes)
+            if (
+              isObject(toClean[key], true) &&
+              !toClean.nodeType && // #10044
+              reference[key]
+            ) {
+              ob = BaseSeries.cleanRecursively(toClean[key], reference[key]);
+              if (Object.keys(ob).length) {
+                clean[key] = ob;
+              }
+              // Arrays, primitives and DOM nodes are copied directly
+            } else if (
+              isObject(toClean[key]) ||
+              toClean[key] !== reference[key]
+            ) {
+              clean[key] = toClean[key];
+            }
+          });
+          return clean;
+        };
+        // eslint-disable-next-line valid-jsdoc
         /**
-         * Area series type.
-         *
+         * Internal function to initialize an individual series.
          * @private
-         * @class
-         * @name Highcharts.seriesTypes.area
-         *
-         * @augments Highcharts.Series
          */
-        BaseSeries.seriesType('area', 'line', 
+        BaseSeries.getSeries = function (chart, options) {
+          if (options === void 0) {
+            options = {};
+          }
+          var optionsChart = chart.options.chart,
+            type =
+              options.type ||
+              optionsChart.type ||
+              optionsChart.defaultSeriesType ||
+              "",
+            Series = BaseSeries.seriesTypes[type];
+          // No such series type
+          if (!Series) {
+            error(17, true, chart, { missingModuleFor: type });
+          }
+          return new Series(chart, options);
+        };
         /**
-         * The area series type.
-         *
-         * @sample {highcharts} highcharts/demo/area-basic/
-         *         Area chart
-         * @sample {highstock} stock/demo/area/
-         *         Area chart
+         * Factory to create new series prototypes.
          *
-         * @extends      plotOptions.line
-         * @excluding    useOhlcData
-         * @product      highcharts highstock
-         * @optionparent plotOptions.area
-         */
-        {
-            /**
-             * @see [fillColor](#plotOptions.area.fillColor)
-             * @see [fillOpacity](#plotOptions.area.fillOpacity)
-             *
-             * @apioption plotOptions.area.color
-             */
-            /**
-             * Fill color or gradient for the area. When `null`, the series' `color`
-             * is used with the series' `fillOpacity`.
-             *
-             * In styled mode, the fill color can be set with the `.highcharts-area`
-             * class name.
-             *
-             * @see [color](#plotOptions.area.color)
-             * @see [fillOpacity](#plotOptions.area.fillOpacity)
-             *
-             * @sample {highcharts} highcharts/plotoptions/area-fillcolor-default/
-             *         Null by default
-             * @sample {highcharts} highcharts/plotoptions/area-fillcolor-gradient/
-             *         Gradient
-             *
-             * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-             * @product   highcharts highstock
-             * @apioption plotOptions.area.fillColor
-             */
-            /**
-             * Fill opacity for the area. When you set an explicit `fillColor`,
-             * the `fillOpacity` is not applied. Instead, you should define the
-             * opacity in the `fillColor` with an rgba color definition. The
-             * `fillOpacity` setting, also the default setting, overrides the alpha
-             * component of the `color` setting.
-             *
-             * In styled mode, the fill opacity can be set with the
-             * `.highcharts-area` class name.
-             *
-             * @see [color](#plotOptions.area.color)
-             * @see [fillColor](#plotOptions.area.fillColor)
-             *
-             * @sample {highcharts} highcharts/plotoptions/area-fillopacity/
-             *         Automatic fill color and fill opacity of 0.1
-             *
-             * @type      {number}
-             * @default   {highcharts} 0.75
-             * @default   {highstock} 0.75
-             * @product   highcharts highstock
-             * @apioption plotOptions.area.fillOpacity
-             */
-            /**
-             * A separate color for the graph line. By default the line takes the
-             * `color` of the series, but the lineColor setting allows setting a
-             * separate color for the line without altering the `fillColor`.
-             *
-             * In styled mode, the line stroke can be set with the
-             * `.highcharts-graph` class name.
-             *
-             * @sample {highcharts} highcharts/plotoptions/area-linecolor/
-             *         Dark gray line
-             *
-             * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-             * @product   highcharts highstock
-             * @apioption plotOptions.area.lineColor
-             */
-            /**
-             * A separate color for the negative part of the area.
-             *
-             * In styled mode, a negative color is set with the
-             * `.highcharts-negative` class name.
-             *
-             * @see [negativeColor](#plotOptions.area.negativeColor)
-             *
-             * @sample {highcharts} highcharts/css/series-negative-color/
-             *         Negative color in styled mode
-             *
-             * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-             * @since     3.0
-             * @product   highcharts
-             * @apioption plotOptions.area.negativeFillColor
-             */
-            /**
-             * Whether the whole area or just the line should respond to mouseover
-             * tooltips and other mouse or touch events.
-             *
-             * @sample {highcharts|highstock} highcharts/plotoptions/area-trackbyarea/
-             *         Display the tooltip when the area is hovered
-             *
-             * @type      {boolean}
-             * @default   false
-             * @since     1.1.6
-             * @product   highcharts highstock
-             * @apioption plotOptions.area.trackByArea
-             */
-            /**
-             * The Y axis value to serve as the base for the area, for
-             * distinguishing between values above and below a threshold. The area
-             * between the graph and the threshold is filled.
-             *
-             * * If a number is given, the Y axis will scale to the threshold.
-             * * If `null`, the scaling behaves like a line series with fill between
-             *   the graph and the Y axis minimum.
-             * * If `Infinity` or `-Infinity`, the area between the graph and the
-             *   corresponding Y axis extreme is filled (since v6.1.0).
-             *
-             * @sample {highcharts} highcharts/plotoptions/area-threshold/
-             *         A threshold of 100
-             * @sample {highcharts} highcharts/plotoptions/area-threshold-infinity/
-             *         A threshold of Infinity
-             *
-             * @type    {number|null}
-             * @since   2.0
-             * @product highcharts highstock
-             */
-            threshold: 0
-        }, 
-        /* eslint-disable valid-jsdoc */
-        /**
-         * @lends seriesTypes.area.prototype
-         */
-        {
-            singleStacks: false,
-            /**
-             * Return an array of stacked points, where null and missing points are
-             * replaced by dummy points in order for gaps to be drawn correctly in
-             * stacks.
-             * @private
-             */
-            getStackPoints: function (points) {
-                var series = this,
-                    segment = [],
-                    keys = [],
-                    xAxis = this.xAxis,
-                    yAxis = this.yAxis,
-                    stack = yAxis.stacking.stacks[this.stackKey],
-                    pointMap = {},
-                    seriesIndex = series.index,
-                    yAxisSeries = yAxis.series,
-                    seriesLength = yAxisSeries.length,
-                    visibleSeries,
-                    upOrDown = pick(yAxis.options.reversedStacks,
-                    true) ? 1 : -1,
-                    i;
-                points = points || this.points;
-                if (this.options.stacking) {
-                    for (i = 0; i < points.length; i++) {
-                        // Reset after point update (#7326)
-                        points[i].leftNull = points[i].rightNull = void 0;
-                        // Create a map where we can quickly look up the points by
-                        // their X values.
-                        pointMap[points[i].x] = points[i];
-                    }
-                    // Sort the keys (#1651)
-                    objectEach(stack, function (stackX, x) {
-                        // nulled after switching between
-                        // grouping and not (#1651, #2336)
-                        if (stackX.total !== null) {
-                            keys.push(x);
-                        }
-                    });
-                    keys.sort(function (a, b) {
-                        return a - b;
-                    });
-                    visibleSeries = yAxisSeries.map(function (s) {
-                        return s.visible;
-                    });
-                    keys.forEach(function (x, idx) {
-                        var y = 0,
-                            stackPoint,
-                            stackedValues;
-                        if (pointMap[x] && !pointMap[x].isNull) {
-                            segment.push(pointMap[x]);
-                            // Find left and right cliff. -1 goes left, 1 goes
-                            // right.
-                            [-1, 1].forEach(function (direction) {
-                                var nullName = direction === 1 ?
-                                        'rightNull' :
-                                        'leftNull',
-                                    cliffName = direction === 1 ?
-                                        'rightCliff' :
-                                        'leftCliff',
-                                    cliff = 0,
-                                    otherStack = stack[keys[idx + direction]];
-                                // If there is a stack next to this one,
-                                // to the left or to the right...
-                                if (otherStack) {
-                                    i = seriesIndex;
-                                    // Can go either up or down,
-                                    // depending on reversedStacks
-                                    while (i >= 0 && i < seriesLength) {
-                                        stackPoint = otherStack.points[i];
-                                        if (!stackPoint) {
-                                            // If the next point in this series
-                                            // is missing, mark the point
-                                            // with point.leftNull or
-                                            // point.rightNull = true.
-                                            if (i === seriesIndex) {
-                                                pointMap[x][nullName] =
-                                                    true;
-                                                // If there are missing points in
-                                                // the next stack in any of the
-                                                // series below this one, we need
-                                                // to substract the missing values
-                                                // and add a hiatus to the left or
-                                                // right.
-                                            }
-                                            else if (visibleSeries[i]) {
-                                                stackedValues =
-                                                    stack[x].points[i];
-                                                if (stackedValues) {
-                                                    cliff -=
-                                                        stackedValues[1] -
-                                                            stackedValues[0];
-                                                }
-                                            }
-                                        }
-                                        // When reversedStacks is true, loop up,
-                                        // else loop down
-                                        i += upOrDown;
-                                    }
-                                }
-                                pointMap[x][cliffName] = cliff;
-                            });
-                            // There is no point for this X value in this series, so we
-                            // insert a dummy point in order for the areas to be drawn
-                            // correctly.
-                        }
-                        else {
-                            // Loop down the stack to find the series below this
-                            // one that has a value (#1991)
-                            i = seriesIndex;
-                            while (i >= 0 && i < seriesLength) {
-                                stackPoint = stack[x].points[i];
-                                if (stackPoint) {
-                                    y = stackPoint[1];
-                                    break;
-                                }
-                                // When reversedStacks is true, loop up, else loop
-                                // down
-                                i += upOrDown;
-                            }
-                            y = yAxis.translate(// #6272
-                            y, 0, 1, 0, 1);
-                            segment.push({
-                                isNull: true,
-                                plotX: xAxis.translate(// #6272
-                                x, 0, 0, 0, 1),
-                                x: x,
-                                plotY: y,
-                                yBottom: y
-                            });
-                        }
-                    });
-                }
-                return segment;
-            },
-            /**
-             * @private
-             */
-            getGraphPath: function (points) {
-                var getGraphPath = Series.prototype.getGraphPath, graphPath, options = this.options, stacking = options.stacking, yAxis = this.yAxis, topPath, bottomPath, bottomPoints = [], graphPoints = [], seriesIndex = this.index, i, areaPath, plotX, stacks = yAxis.stacking.stacks[this.stackKey], threshold = options.threshold, translatedThreshold = Math.round(// #10909
-                    yAxis.getThreshold(options.threshold)), isNull, yBottom, connectNulls = pick(// #10574
-                    options.connectNulls, stacking === 'percent'), 
-                    // To display null points in underlying stacked series, this
-                    // series graph must be broken, and the area also fall down to
-                    // fill the gap left by the null point. #2069
-                    addDummyPoints = function (i, otherI, side) {
-                        var point = points[i], stackedValues = stacking &&
-                            stacks[point.x].points[seriesIndex], nullVal = point[side + 'Null'] || 0, cliffVal = point[side + 'Cliff'] || 0, top, bottom, isNull = true;
-                    if (cliffVal || nullVal) {
-                        top = (nullVal ?
-                            stackedValues[0] :
-                            stackedValues[1]) + cliffVal;
-                        bottom = stackedValues[0] + cliffVal;
-                        isNull = !!nullVal;
-                    }
-                    else if (!stacking &&
-                        points[otherI] &&
-                        points[otherI].isNull) {
-                        top = bottom = threshold;
-                    }
-                    // Add to the top and bottom line of the area
-                    if (typeof top !== 'undefined') {
-                        graphPoints.push({
-                            plotX: plotX,
-                            plotY: top === null ?
-                                translatedThreshold :
-                                yAxis.getThreshold(top),
-                            isNull: isNull,
-                            isCliff: true
-                        });
-                        bottomPoints.push({
-                            plotX: plotX,
-                            plotY: bottom === null ?
-                                translatedThreshold :
-                                yAxis.getThreshold(bottom),
-                            doCurve: false // #1041, gaps in areaspline areas
-                        });
-                    }
-                };
-                // Find what points to use
-                points = points || this.points;
-                // Fill in missing points
-                if (stacking) {
-                    points = this.getStackPoints(points);
-                }
-                for (i = 0; i < points.length; i++) {
-                    // Reset after series.update of stacking property (#12033)
-                    if (!stacking) {
-                        points[i].leftCliff = points[i].rightCliff =
-                            points[i].leftNull = points[i].rightNull = void 0;
-                    }
-                    isNull = points[i].isNull;
-                    plotX = pick(points[i].rectPlotX, points[i].plotX);
-                    yBottom = stacking ? points[i].yBottom : translatedThreshold;
-                    if (!isNull || connectNulls) {
-                        if (!connectNulls) {
-                            addDummyPoints(i, i - 1, 'left');
-                        }
-                        // Skip null point when stacking is false and connectNulls
-                        // true
-                        if (!(isNull && !stacking && connectNulls)) {
-                            graphPoints.push(points[i]);
-                            bottomPoints.push({
-                                x: i,
-                                plotX: plotX,
-                                plotY: yBottom
-                            });
-                        }
-                        if (!connectNulls) {
-                            addDummyPoints(i, i + 1, 'right');
-                        }
-                    }
-                }
-                topPath = getGraphPath.call(this, graphPoints, true, true);
-                bottomPoints.reversed = true;
-                bottomPath = getGraphPath.call(this, bottomPoints, true, true);
-                var firstBottomPoint = bottomPath[0];
-                if (firstBottomPoint && firstBottomPoint[0] === 'M') {
-                    bottomPath[0] = ['L', firstBottomPoint[1], firstBottomPoint[2]];
-                }
-                areaPath = topPath.concat(bottomPath);
-                // TODO: don't set leftCliff and rightCliff when connectNulls?
-                graphPath = getGraphPath
-                    .call(this, graphPoints, false, connectNulls);
-                areaPath.xMap = topPath.xMap;
-                this.areaPath = areaPath;
-                return graphPath;
-            },
-            /**
-             * Draw the graph and the underlying area. This method calls the Series
-             * base function and adds the area. The areaPath is calculated in the
-             * getSegmentPath method called from Series.prototype.drawGraph.
-             * @private
-             */
-            drawGraph: function () {
-                // Define or reset areaPath
-                this.areaPath = [];
-                // Call the base method
-                Series.prototype.drawGraph.apply(this);
-                // Define local variables
-                var series = this,
-                    areaPath = this.areaPath,
-                    options = this.options,
-                    zones = this.zones,
-                    props = [[
-                            'area',
-                            'highcharts-area',
-                            this.color,
-                            options.fillColor
-                        ]]; // area name, main color, fill color
-                    zones.forEach(function (zone,
-                    i) {
-                        props.push([
-                            'zone-area-' + i,
-                            'highcharts-area highcharts-zone-area-' + i + ' ' +
-                                zone.className,
-                            zone.color || series.color,
-                            zone.fillColor || options.fillColor
-                        ]);
-                });
-                props.forEach(function (prop) {
-                    var areaKey = prop[0],
-                        area = series[areaKey],
-                        verb = area ? 'animate' : 'attr',
-                        attribs = {};
-                    // Create or update the area
-                    if (area) { // update
-                        area.endX = series.preventGraphAnimation ?
-                            null :
-                            areaPath.xMap;
-                        area.animate({ d: areaPath });
-                    }
-                    else { // create
-                        attribs.zIndex = 0; // #1069
-                        area = series[areaKey] = series.chart.renderer
-                            .path(areaPath)
-                            .addClass(prop[1])
-                            .add(series.group);
-                        area.isArea = true;
-                    }
-                    if (!series.chart.styledMode) {
-                        attribs.fill = pick(prop[3], color(prop[2])
-                            .setOpacity(pick(options.fillOpacity, 0.75))
-                            .get());
-                    }
-                    area[verb](attribs);
-                    area.startX = areaPath.xMap;
-                    area.shiftUnit = options.step ? 2 : 1;
-                });
-            },
-            drawLegendSymbol: LegendSymbolMixin.drawRectangle
-        });
-        /* eslint-enable valid-jsdoc */
-        /**
-         * A `area` series. If the [type](#series.area.type) option is not
-         * specified, it is inherited from [chart.type](#chart.type).
+         * @function Highcharts.seriesType
          *
-         * @extends   series,plotOptions.area
-         * @excluding dataParser, dataURL, useOhlcData
-         * @product   highcharts highstock
-         * @apioption series.area
-         */
-        /**
-         * @see [fillColor](#series.area.fillColor)
-         * @see [fillOpacity](#series.area.fillOpacity)
-         *
-         * @apioption series.area.color
-         */
-        /**
-         * An array of data points for the series. For the `area` series type,
-         * points can be given in the following ways:
-         *
-         * 1. An array of numerical values. In this case, the numerical values will be
-         *    interpreted as `y` options. The `x` values will be automatically
-         *    calculated, either starting at 0 and incremented by 1, or from
-         *    `pointStart` * and `pointInterval` given in the series options. If the
-         *    axis has categories, these will be used. Example:
-         *    ```js
-         *    data: [0, 5, 3, 5]
-         *    ```
-         *
-         * 2. An array of arrays with 2 values. In this case, the values correspond to
-         *    `x,y`. If the first value is a string, it is applied as the name of the
-         *    point, and the `x` value is inferred.
-         *    ```js
-         *    data: [
-         *        [0, 9],
-         *        [1, 7],
-         *        [2, 6]
-         *    ]
-         *    ```
-         *
-         * 3. An array of objects with named values. The following snippet shows only a
-         *    few settings, see the complete options set below. If the total number of
-         *    data points exceeds the series'
-         *    [turboThreshold](#series.area.turboThreshold), this option is not
-         *    available.
-         *    ```js
-         *    data: [{
-         *        x: 1,
-         *        y: 9,
-         *        name: "Point2",
-         *        color: "#00FF00"
-         *    }, {
-         *        x: 1,
-         *        y: 6,
-         *        name: "Point1",
-         *        color: "#FF00FF"
-         *    }]
-         *    ```
-         *
-         * @sample {highcharts} highcharts/chart/reflow-true/
-         *         Numerical values
-         * @sample {highcharts} highcharts/series/data-array-of-arrays/
-         *         Arrays of numeric x and y
-         * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
-         *         Arrays of datetime x and y
-         * @sample {highcharts} highcharts/series/data-array-of-name-value/
-         *         Arrays of point.name and y
-         * @sample {highcharts} highcharts/series/data-array-of-objects/
-         *         Config objects
-         *
-         * @type      {Array<number|Array<(number|string),(number|null)>|null|*>}
-         * @extends   series.line.data
-         * @product   highcharts highstock
-         * @apioption series.area.data
-         */
-        /**
-         * @see [color](#series.area.color)
-         * @see [fillOpacity](#series.area.fillOpacity)
+         * @param {string} type
+         * The series type name.
+         *
+         * @param {string} parent
+         * The parent series type name. Use `line` to inherit from the basic
+         * {@link Series} object.
+         *
+         * @param {Highcharts.SeriesOptionsType|Highcharts.Dictionary<*>} options
+         * The additional default options that are merged with the parent's options.
+         *
+         * @param {Highcharts.Dictionary<*>} [props]
+         * The properties (functions and primitives) to set on the new prototype.
+         *
+         * @param {Highcharts.Dictionary<*>} [pointProps]
+         * Members for a series-specific extension of the {@link Point} prototype if
+         * needed.
+         *
+         * @return {Highcharts.Series}
+         * The newly created prototype as extended from {@link Series} or its
+         * derivatives.
+         */
+        // docs: add to API + extending Highcharts
+        BaseSeries.seriesType = function (
+          type,
+          parent,
+          options,
+          seriesProto,
+          pointProto
+        ) {
+          var defaultOptions = getOptions().plotOptions || {},
+            seriesTypes = BaseSeries.seriesTypes;
+          parent = parent || "";
+          // Merge the options
+          defaultOptions[type] = merge(defaultOptions[parent], options);
+          // Create the class
+          BaseSeries.addSeries(
+            type,
+            extendClass(seriesTypes[parent] || function () {}, seriesProto)
+          );
+          seriesTypes[type].prototype.type = type;
+          // Create the point class if needed
+          if (pointProto) {
+            seriesTypes[type].prototype.pointClass = extendClass(
+              Point,
+              pointProto
+            );
+          }
+          return seriesTypes[type];
+        };
+        BaseSeries.prototype.update = function (newOptions, redraw) {
+          if (redraw === void 0) {
+            redraw = true;
+          }
+          var series = this;
+          newOptions = BaseSeries.cleanRecursively(
+            newOptions,
+            this.userOptions
+          );
+          var newType = newOptions.type;
+          if (typeof newType !== "undefined" && newType !== series.type) {
+            series = BaseSeries.getSeries(series.chart, newOptions);
+          }
+          fireEvent(series, "update", { newOptions: newOptions });
+          series.userOptions = merge(newOptions);
+          fireEvent(series, "afterUpdate", { newOptions: newOptions });
+          if (redraw) {
+            series.chart.redraw();
+          }
+          return series;
+        };
+        /* *
          *
-         * @apioption series.area.fillColor
-         */
-        /**
-         * @see [color](#series.area.color)
-         * @see [fillColor](#series.area.fillColor)
+         *  Static Properties
          *
-         * @default   {highcharts} 0.75
-         * @default   {highstock} 0.75
-         * @apioption series.area.fillOpacity
-         */
-        ''; // adds doclets above to transpilat
+         * */
+        BaseSeries.defaultOptions = {
+          type: "base",
+        };
+        BaseSeries.seriesTypes = {};
+        return BaseSeries;
+      })();
+      BaseSeries.prototype.pointClass = Point;
+      // backwards compatibility
+      H.seriesType = BaseSeries.seriesType;
+      H.seriesTypes = BaseSeries.seriesTypes;
+      /* *
+       *
+       *  Export
+       *
+       * */
 
-    });
-    _registerModule(_modules, 'Series/SplineSeries.js', [_modules['Core/Series/Series.js'], _modules['Core/Utilities.js']], function (BaseSeries, U) {
+      return BaseSeries;
+    }
+  );
+  _registerModule(
+    _modules,
+    "Core/Chart/Chart.js",
+    [
+      _modules["Core/Animation/AnimationUtilities.js"],
+      _modules["Core/Axis/Axis.js"],
+      _modules["Core/Series/Series.js"],
+      _modules["Core/Globals.js"],
+      _modules["Core/Legend.js"],
+      _modules["Core/MSPointer.js"],
+      _modules["Core/Options.js"],
+      _modules["Core/Pointer.js"],
+      _modules["Core/Time.js"],
+      _modules["Core/Utilities.js"],
+    ],
+    function (A, Axis, BaseSeries, H, Legend, MSPointer, O, Pointer, Time, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      var animate = A.animate,
+        animObject = A.animObject,
+        setAnimation = A.setAnimation;
+      var charts = H.charts,
+        doc = H.doc,
+        win = H.win;
+      var defaultOptions = O.defaultOptions;
+      var addEvent = U.addEvent,
+        attr = U.attr,
+        createElement = U.createElement,
+        css = U.css,
+        defined = U.defined,
+        discardElement = U.discardElement,
+        erase = U.erase,
+        error = U.error,
+        extend = U.extend,
+        find = U.find,
+        fireEvent = U.fireEvent,
+        getStyle = U.getStyle,
+        isArray = U.isArray,
+        isFunction = U.isFunction,
+        isNumber = U.isNumber,
+        isObject = U.isObject,
+        isString = U.isString,
+        merge = U.merge,
+        numberFormat = U.numberFormat,
+        objectEach = U.objectEach,
+        pick = U.pick,
+        pInt = U.pInt,
+        relativeLength = U.relativeLength,
+        removeEvent = U.removeEvent,
+        splat = U.splat,
+        syncTimeout = U.syncTimeout,
+        uniqueKey = U.uniqueKey;
+      /**
+       * Callback for chart constructors.
+       *
+       * @callback Highcharts.ChartCallbackFunction
+       *
+       * @param {Highcharts.Chart} chart
+       *        Created chart.
+       */
+      /**
+       * Format a number and return a string based on input settings.
+       *
+       * @callback Highcharts.NumberFormatterCallbackFunction
+       *
+       * @param {number} number
+       *        The input number to format.
+       *
+       * @param {number} decimals
+       *        The amount of decimals. A value of -1 preserves the amount in the
+       *        input number.
+       *
+       * @param {string} [decimalPoint]
+       *        The decimal point, defaults to the one given in the lang options, or
+       *        a dot.
+       *
+       * @param {string} [thousandsSep]
+       *        The thousands separator, defaults to the one given in the lang
+       *        options, or a space character.
+       *
+       * @return {string} The formatted number.
+       */
+      /**
+       * The chart title. The title has an `update` method that allows modifying the
+       * options directly or indirectly via `chart.update`.
+       *
+       * @interface Highcharts.TitleObject
+       * @extends Highcharts.SVGElement
+       */ /**
+       * Modify options for the title.
+       *
+       * @function Highcharts.TitleObject#update
+       *
+       * @param {Highcharts.TitleOptions} titleOptions
+       *        Options to modify.
+       *
+       * @param {boolean} [redraw=true]
+       *        Whether to redraw the chart after the title is altered. If doing more
+       *        operations on the chart, it is a good idea to set redraw to false and
+       *        call {@link Chart#redraw} after.
+       */
+      /**
+       * The chart subtitle. The subtitle has an `update` method that
+       * allows modifying the options directly or indirectly via
+       * `chart.update`.
+       *
+       * @interface Highcharts.SubtitleObject
+       * @extends Highcharts.SVGElement
+       */ /**
+       * Modify options for the subtitle.
+       *
+       * @function Highcharts.SubtitleObject#update
+       *
+       * @param {Highcharts.SubtitleOptions} subtitleOptions
+       *        Options to modify.
+       *
+       * @param {boolean} [redraw=true]
+       *        Whether to redraw the chart after the subtitle is altered. If doing
+       *        more operations on the chart, it is a good idea to set redraw to false
+       *        and call {@link Chart#redraw} after.
+       */
+      /**
+       * The chart caption. The caption has an `update` method that
+       * allows modifying the options directly or indirectly via
+       * `chart.update`.
+       *
+       * @interface Highcharts.CaptionObject
+       * @extends Highcharts.SVGElement
+       */ /**
+       * Modify options for the caption.
+       *
+       * @function Highcharts.CaptionObject#update
+       *
+       * @param {Highcharts.CaptionOptions} captionOptions
+       *        Options to modify.
+       *
+       * @param {boolean} [redraw=true]
+       *        Whether to redraw the chart after the caption is altered. If doing
+       *        more operations on the chart, it is a good idea to set redraw to false
+       *        and call {@link Chart#redraw} after.
+       */
+      var marginNames = H.marginNames;
+      /* eslint-disable no-invalid-this, valid-jsdoc */
+      /**
+       * The Chart class. The recommended constructor is {@link Highcharts#chart}.
+       *
+       * @example
+       * var chart = Highcharts.chart('container', {
+       *        title: {
+       *               text: 'My chart'
+       *        },
+       *        series: [{
+       *            data: [1, 3, 2, 4]
+       *        }]
+       * })
+       *
+       * @class
+       * @name Highcharts.Chart
+       *
+       * @param {string|Highcharts.HTMLDOMElement} [renderTo]
+       *        The DOM element to render to, or its id.
+       *
+       * @param {Highcharts.Options} options
+       *        The chart options structure.
+       *
+       * @param {Highcharts.ChartCallbackFunction} [callback]
+       *        Function to run when the chart has loaded and and all external images
+       *        are loaded. Defining a
+       *        [chart.events.load](https://api.highcharts.com/highcharts/chart.events.load)
+       *        handler is equivalent.
+       */
+      var Chart = /** @class */ (function () {
+        function Chart(a, b, c) {
+          this.axes = void 0;
+          this.axisOffset = void 0;
+          this.bounds = void 0;
+          this.chartHeight = void 0;
+          this.chartWidth = void 0;
+          this.clipBox = void 0;
+          this.colorCounter = void 0;
+          this.container = void 0;
+          this.index = void 0;
+          this.isResizing = void 0;
+          this.labelCollectors = void 0;
+          this.legend = void 0;
+          this.margin = void 0;
+          this.numberFormatter = void 0;
+          this.options = void 0;
+          this.plotBox = void 0;
+          this.plotHeight = void 0;
+          this.plotLeft = void 0;
+          this.plotTop = void 0;
+          this.plotWidth = void 0;
+          this.pointCount = void 0;
+          this.pointer = void 0;
+          this.renderer = void 0;
+          this.renderTo = void 0;
+          this.series = void 0;
+          this.spacing = void 0;
+          this.spacingBox = void 0;
+          this.symbolCounter = void 0;
+          this.time = void 0;
+          this.titleOffset = void 0;
+          this.userOptions = void 0;
+          this.xAxis = void 0;
+          this.yAxis = void 0;
+          this.getArgs(a, b, c);
+        }
         /* *
          *
-         *  (c) 2010-2020 Torstein Honsi
-         *
-         *  License: www.highcharts.com/license
-         *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+         *  Functions
          *
          * */
-        var pick = U.pick;
         /**
-         * Spline series type.
+         * Handle the arguments passed to the constructor.
          *
          * @private
-         * @class
-         * @name Highcharts.seriesTypes.spline
-         *
-         * @augments Highcarts.Series
-         */
-        BaseSeries.seriesType('spline', 'line', 
+         * @function Highcharts.Chart#getArgs
+         *
+         * @param {...Array<*>} arguments
+         * All arguments for the constructor.
+         *
+         * @fires Highcharts.Chart#event:init
+         * @fires Highcharts.Chart#event:afterInit
+         */
+        Chart.prototype.getArgs = function (a, b, c) {
+          // Remove the optional first argument, renderTo, and
+          // set it on this.
+          if (isString(a) || a.nodeName) {
+            this.renderTo = a;
+            this.init(b, c);
+          } else {
+            this.init(a, b);
+          }
+        };
         /**
-         * A spline series is a special type of line series, where the segments
-         * between the data points are smoothed.
+         * Overridable function that initializes the chart. The constructor's
+         * arguments are passed on directly.
          *
-         * @sample {highcharts} highcharts/demo/spline-irregular-time/
-         *         Spline chart
-         * @sample {highstock} stock/demo/spline/
-         *         Spline chart
+         * @function Highcharts.Chart#init
          *
-         * @extends      plotOptions.series
-         * @excluding    step, boostThreshold, boostBlending
-         * @product      highcharts highstock
-         * @optionparent plotOptions.spline
-         */
-        {}, 
-        /**
-         * @lends seriesTypes.spline.prototype
-         */
-        {
-            /* eslint-disable valid-jsdoc */
+         * @param {Highcharts.Options} userOptions
+         *        Custom options.
+         *
+         * @param {Function} [callback]
+         *        Function to run when the chart has loaded and and all external
+         *        images are loaded.
+         *
+         * @return {void}
+         *
+         * @fires Highcharts.Chart#event:init
+         * @fires Highcharts.Chart#event:afterInit
+         */
+        Chart.prototype.init = function (userOptions, callback) {
+          // Handle regular options
+          var options,
+            // skip merging data points to increase performance
+            seriesOptions = userOptions.series,
+            userPlotOptions = userOptions.plotOptions || {};
+          // Fire the event with a default function
+          fireEvent(this, "init", { args: arguments }, function () {
+            userOptions.series = null;
+            options = merge(defaultOptions, userOptions); // do the merge
+            var optionsChart = options.chart || {};
+            // Override (by copy of user options) or clear tooltip options
+            // in chart.options.plotOptions (#6218)
+            objectEach(options.plotOptions, function (typeOptions, type) {
+              if (isObject(typeOptions)) {
+                // #8766
+                typeOptions.tooltip =
+                  (userPlotOptions[type] && // override by copy:
+                    merge(userPlotOptions[type].tooltip)) ||
+                  void 0; // or clear
+              }
+            });
+            // User options have higher priority than default options
+            // (#6218). In case of exporting: path is changed
+            options.tooltip.userOptions =
+              (userOptions.chart &&
+                userOptions.chart.forExport &&
+                userOptions.tooltip.userOptions) ||
+              userOptions.tooltip;
+            // set back the series data
+            options.series = userOptions.series = seriesOptions;
             /**
-             * Get the spline segment from a given point's previous neighbour to the
-             * given point.
+             * The original options given to the constructor or a chart factory
+             * like {@link Highcharts.chart} and {@link Highcharts.stockChart}.
              *
-             * @private
-             * @function Highcharts.seriesTypes.spline#getPointSpline
+             * @name Highcharts.Chart#userOptions
+             * @type {Highcharts.Options}
+             */
+            this.userOptions = userOptions;
+            var chartEvents = optionsChart.events;
+            this.margin = [];
+            this.spacing = [];
+            // Pixel data bounds for touch zoom
+            this.bounds = { h: {}, v: {} };
+            // An array of functions that returns labels that should be
+            // considered for anti-collision
+            this.labelCollectors = [];
+            this.callback = callback;
+            this.isResizing = 0;
+            /**
+             * The options structure for the chart after merging
+             * {@link #defaultOptions} and {@link #userOptions}. It contains
+             * members for the sub elements like series, legend, tooltip etc.
+             *
+             * @name Highcharts.Chart#options
+             * @type {Highcharts.Options}
+             */
+            this.options = options;
+            /**
+             * All the axes in the chart.
              *
-             * @param {Array<Highcharts.Point>}
+             * @see  Highcharts.Chart.xAxis
+             * @see  Highcharts.Chart.yAxis
              *
-             * @param {Highcharts.Point} point
+             * @name Highcharts.Chart#axes
+             * @type {Array<Highcharts.Axis>}
+             */
+            this.axes = [];
+            /**
+             * All the current series in the chart.
              *
-             * @param {number} i
+             * @name Highcharts.Chart#series
+             * @type {Array<Highcharts.Series>}
+             */
+            this.series = [];
+            /**
+             * The `Time` object associated with the chart. Since v6.0.5,
+             * time settings can be applied individually for each chart. If
+             * no individual settings apply, the `Time` object is shared by
+             * all instances.
              *
-             * @return {Highcharts.SVGPathArray}
+             * @name Highcharts.Chart#time
+             * @type {Highcharts.Time}
              */
-            getPointSpline: function (points, point, i) {
-                var 
-                    // 1 means control points midway between points, 2 means 1/3
-                    // from the point, 3 is 1/4 etc
-                    smoothing = 1.5,
-                    denom = smoothing + 1,
-                    plotX = point.plotX || 0,
-                    plotY = point.plotY || 0,
-                    lastPoint = points[i - 1],
-                    nextPoint = points[i + 1],
-                    leftContX,
-                    leftContY,
-                    rightContX,
-                    rightContY,
-                    ret;
-                /**
-                 * @private
-                 */
-                function doCurve(otherPoint) {
-                    return otherPoint &&
-                        !otherPoint.isNull &&
-                        otherPoint.doCurve !== false &&
-                        // #6387, area splines next to null:
-                        !point.isCliff;
-                }
-                // Find control points
-                if (doCurve(lastPoint) && doCurve(nextPoint)) {
-                    var lastX = lastPoint.plotX || 0,
-                        lastY = lastPoint.plotY || 0,
-                        nextX = nextPoint.plotX || 0,
-                        nextY = nextPoint.plotY || 0,
-                        correction = 0;
-                    leftContX = (smoothing * plotX + lastX) / denom;
-                    leftContY = (smoothing * plotY + lastY) / denom;
-                    rightContX = (smoothing * plotX + nextX) / denom;
-                    rightContY = (smoothing * plotY + nextY) / denom;
-                    // Have the two control points make a straight line through main
-                    // point
-                    if (rightContX !== leftContX) { // #5016, division by zero
-                        correction = (((rightContY - leftContY) *
-                            (rightContX - plotX)) /
-                            (rightContX - leftContX) + plotY - rightContY);
-                    }
-                    leftContY += correction;
-                    rightContY += correction;
-                    // to prevent false extremes, check that control points are
-                    // between neighbouring points' y values
-                    if (leftContY > lastY && leftContY > plotY) {
-                        leftContY = Math.max(lastY, plotY);
-                        // mirror of left control point
-                        rightContY = 2 * plotY - leftContY;
-                    }
-                    else if (leftContY < lastY && leftContY < plotY) {
-                        leftContY = Math.min(lastY, plotY);
-                        rightContY = 2 * plotY - leftContY;
-                    }
-                    if (rightContY > nextY && rightContY > plotY) {
-                        rightContY = Math.max(nextY, plotY);
-                        leftContY = 2 * plotY - rightContY;
-                    }
-                    else if (rightContY < nextY && rightContY < plotY) {
-                        rightContY = Math.min(nextY, plotY);
-                        leftContY = 2 * plotY - rightContY;
-                    }
-                    // record for drawing in next point
-                    point.rightContX = rightContX;
-                    point.rightContY = rightContY;
-                }
-                // Visualize control points for debugging
-                /*
-            if (leftContX) {
-                this.chart.renderer.circle(
-                        leftContX + this.chart.plotLeft,
-                        leftContY + this.chart.plotTop,
-                        2
-                    )
-                    .attr({
-                        stroke: 'red',
-                        'stroke-width': 2,
-                        fill: 'none',
-                        zIndex: 9
-                    })
-                    .add();
-                this.chart.renderer.path(['M', leftContX + this.chart.plotLeft,
-                    leftContY + this.chart.plotTop,
-                    'L', plotX + this.chart.plotLeft, plotY + this.chart.plotTop])
-                    .attr({
-                        stroke: 'red',
-                        'stroke-width': 2,
-                        zIndex: 9
-                    })
-                    .add();
-            }
-            if (rightContX) {
-                this.chart.renderer.circle(
-                        rightContX + this.chart.plotLeft,
-                        rightContY + this.chart.plotTop,
-                        2
-                    )
-                    .attr({
-                        stroke: 'green',
-                        'stroke-width': 2,
-                        fill: 'none',
-                        zIndex: 9
-                    })
-                    .add();
-                this.chart.renderer.path(['M', rightContX + this.chart.plotLeft,
-                    rightContY + this.chart.plotTop,
-                    'L', plotX + this.chart.plotLeft, plotY + this.chart.plotTop])
-                    .attr({
-                        stroke: 'green',
-                        'stroke-width': 2,
-                        zIndex: 9
-                    })
-                    .add();
+            this.time =
+              userOptions.time && Object.keys(userOptions.time).length
+                ? new Time(userOptions.time)
+                : H.time;
+            /**
+             * Callback function to override the default function that formats
+             * all the numbers in the chart. Returns a string with the formatted
+             * number.
+             *
+             * @name Highcharts.Chart#numberFormatter
+             * @type {Highcharts.NumberFormatterCallbackFunction}
+             */
+            this.numberFormatter = optionsChart.numberFormatter || numberFormat;
+            /**
+             * Whether the chart is in styled mode, meaning all presentatinoal
+             * attributes are avoided.
+             *
+             * @name Highcharts.Chart#styledMode
+             * @type {boolean}
+             */
+            this.styledMode = optionsChart.styledMode;
+            this.hasCartesianSeries = optionsChart.showAxes;
+            var chart = this;
+            /**
+             * Index position of the chart in the {@link Highcharts#charts}
+             * property.
+             *
+             * @name Highcharts.Chart#index
+             * @type {number}
+             * @readonly
+             */
+            chart.index = charts.length; // Add the chart to the global lookup
+            charts.push(chart);
+            H.chartCount++;
+            // Chart event handlers
+            if (chartEvents) {
+              objectEach(chartEvents, function (event, eventType) {
+                if (isFunction(event)) {
+                  addEvent(chart, eventType, event);
+                }
+              });
             }
-                // */
-                ret = [
-                    'C',
-                    pick(lastPoint.rightContX, lastPoint.plotX, 0),
-                    pick(lastPoint.rightContY, lastPoint.plotY, 0),
-                    pick(leftContX, plotX, 0),
-                    pick(leftContY, plotY, 0),
-                    plotX,
-                    plotY
-                ];
-                // reset for updating series later
-                lastPoint.rightContX = lastPoint.rightContY = void 0;
-                return ret;
+            /**
+             * A collection of the X axes in the chart.
+             *
+             * @name Highcharts.Chart#xAxis
+             * @type {Array<Highcharts.Axis>}
+             */
+            chart.xAxis = [];
+            /**
+             * A collection of the Y axes in the chart.
+             *
+             * @name Highcharts.Chart#yAxis
+             * @type {Array<Highcharts.Axis>}
+             *
+             * @todo
+             * Make events official: Fire the event `afterInit`.
+             */
+            chart.yAxis = [];
+            chart.pointCount = chart.colorCounter = chart.symbolCounter = 0;
+            // Fire after init but before first render, before axes and series
+            // have been initialized.
+            fireEvent(chart, "afterInit");
+            chart.firstRender();
+          });
+        };
+        /**
+         * Internal function to unitialize an individual series.
+         *
+         * @private
+         * @function Highcharts.Chart#initSeries
+         */
+        Chart.prototype.initSeries = function (options) {
+          var chart = this,
+            optionsChart = chart.options.chart,
+            type =
+              options.type ||
+              optionsChart.type ||
+              optionsChart.defaultSeriesType,
+            series,
+            Constr = BaseSeries.seriesTypes[type];
+          // No such series type
+          if (!Constr) {
+            error(17, true, chart, { missingModuleFor: type });
+          }
+          series = new Constr(chart, options);
+          if (typeof series.init === "function") {
+            series.init(this, options);
+          }
+          return series;
+        };
+        /**
+         * Internal function to set data for all series with enabled sorting.
+         *
+         * @private
+         * @function Highcharts.Chart#setSeriesData
+         */
+        Chart.prototype.setSeriesData = function () {
+          this.getSeriesOrderByLinks().forEach(function (series) {
+            // We need to set data for series with sorting after series init
+            if (!series.points && !series.data && series.enabledDataSorting) {
+              series.setData(series.options.data, false);
             }
-            /* eslint-enable valid-jsdoc */
-        });
+          });
+        };
         /**
-         * A `spline` series. If the [type](#series.spline.type) option is
-         * not specified, it is inherited from [chart.type](#chart.type).
+         * Sort and return chart series in order depending on the number of linked
+         * series.
          *
-         * @extends   series,plotOptions.spline
-         * @excluding dataParser, dataURL, step, boostThreshold, boostBlending
-         * @product   highcharts highstock
-         * @apioption series.spline
-         */
-        /**
-         * An array of data points for the series. For the `spline` series type,
-         * points can be given in the following ways:
-         *
-         * 1. An array of numerical values. In this case, the numerical values will be
-         *    interpreted as `y` options. The `x` values will be automatically
-         *    calculated, either starting at 0 and incremented by 1, or from
-         *    `pointStart` and `pointInterval` given in the series options. If the axis
-         *    has categories, these will be used. Example:
-         *    ```js
-         *    data: [0, 5, 3, 5]
-         *    ```
-         *
-         * 2. An array of arrays with 2 values. In this case, the values correspond to
-         *    `x,y`. If the first value is a string, it is applied as the name of the
-         *    point, and the `x` value is inferred.
-         *    ```js
-         *    data: [
-         *        [0, 9],
-         *        [1, 2],
-         *        [2, 8]
-         *    ]
-         *    ```
-         *
-         * 3. An array of objects with named values. The following snippet shows only a
-         *    few settings, see the complete options set below. If the total number of
-         *    data points exceeds the series'
-         *    [turboThreshold](#series.spline.turboThreshold),
-         *    this option is not available.
-         *    ```js
-         *    data: [{
-         *        x: 1,
-         *        y: 9,
-         *        name: "Point2",
-         *        color: "#00FF00"
-         *    }, {
-         *        x: 1,
-         *        y: 0,
-         *        name: "Point1",
-         *        color: "#FF00FF"
-         *    }]
-         *    ```
-         *
-         * @sample {highcharts} highcharts/chart/reflow-true/
-         *         Numerical values
-         * @sample {highcharts} highcharts/series/data-array-of-arrays/
-         *         Arrays of numeric x and y
-         * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
-         *         Arrays of datetime x and y
-         * @sample {highcharts} highcharts/series/data-array-of-name-value/
-         *         Arrays of point.name and y
-         * @sample {highcharts} highcharts/series/data-array-of-objects/
-         *         Config objects
-         *
-         * @type      {Array<number|Array<(number|string),(number|null)>|null|*>}
-         * @extends   series.line.data
-         * @product   highcharts highstock
-         * @apioption series.spline.data
+         * @private
+         * @function Highcharts.Series#getSeriesOrderByLinks
+         * @return {Array<Highcharts.Series>}
          */
-        ''; // adds doclets above intro transpilat
-
-    });
-    _registerModule(_modules, 'Series/AreaSplineSeries.js', [_modules['Core/Series/Series.js'], _modules['Mixins/LegendSymbol.js'], _modules['Core/Options.js']], function (BaseSeries, LegendSymbolMixin, O) {
-        /* *
+        Chart.prototype.getSeriesOrderByLinks = function () {
+          return this.series.concat().sort(function (a, b) {
+            if (a.linkedSeries.length || b.linkedSeries.length) {
+              return b.linkedSeries.length - a.linkedSeries.length;
+            }
+            return 0;
+          });
+        };
+        /**
+         * Order all series above a given index. When series are added and ordered
+         * by configuration, only the last series is handled (#248, #1123, #2456,
+         * #6112). This function is called on series initialization and destroy.
          *
-         *  (c) 2010-2020 Torstein Honsi
+         * @private
+         * @function Highcharts.Series#orderSeries
+         * @param {number} [fromIndex]
+         * If this is given, only the series above this index are handled.
+         */
+        Chart.prototype.orderSeries = function (fromIndex) {
+          var series = this.series,
+            i = fromIndex || 0;
+          for (; i < series.length; i++) {
+            if (series[i]) {
+              /**
+               * Contains the series' index in the `Chart.series` array.
+               *
+               * @name Highcharts.Series#index
+               * @type {number}
+               * @readonly
+               */
+              series[i].index = i;
+              series[i].name = series[i].getName();
+            }
+          }
+        };
+        /**
+         * Check whether a given point is within the plot area.
          *
-         *  License: www.highcharts.com/license
+         * @function Highcharts.Chart#isInsidePlot
          *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+         * @param {number} plotX
+         * Pixel x relative to the plot area.
          *
-         * */
-        var defaultOptions = O.defaultOptions;
-        var areaProto = BaseSeries.seriesTypes.area.prototype;
-        /**
-         * AreaSpline series type.
+         * @param {number} plotY
+         * Pixel y relative to the plot area.
          *
-         * @private
-         * @class
-         * @name Highcharts.seriesTypes.areaspline
+         * @param {boolean} [inverted]
+         * Whether the chart is inverted.
          *
-         * @augments Highcharts.Series
-         */
-        BaseSeries.seriesType('areaspline', 'spline', 
+         * @return {boolean}
+         * Returns true if the given point is inside the plot area.
+         */
+        Chart.prototype.isInsidePlot = function (plotX, plotY, inverted) {
+          var x = inverted ? plotY : plotX,
+            y = inverted ? plotX : plotY,
+            e = {
+              x: x,
+              y: y,
+              isInsidePlot:
+                x >= 0 && x <= this.plotWidth && y >= 0 && y <= this.plotHeight,
+            };
+          fireEvent(this, "afterIsInsidePlot", e);
+          return e.isInsidePlot;
+        };
         /**
-         * The area spline series is an area series where the graph between the
-         * points is smoothed into a spline.
+         * Redraw the chart after changes have been done to the data, axis extremes
+         * chart size or chart elements. All methods for updating axes, series or
+         * points have a parameter for redrawing the chart. This is `true` by
+         * default. But in many cases you want to do more than one operation on the
+         * chart before redrawing, for example add a number of points. In those
+         * cases it is a waste of resources to redraw the chart for each new point
+         * added. So you add the points and call `chart.redraw()` after.
+         *
+         * @function Highcharts.Chart#redraw
+         *
+         * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation]
+         * If or how to apply animation to the redraw.
+         *
+         * @fires Highcharts.Chart#event:afterSetExtremes
+         * @fires Highcharts.Chart#event:beforeRedraw
+         * @fires Highcharts.Chart#event:predraw
+         * @fires Highcharts.Chart#event:redraw
+         * @fires Highcharts.Chart#event:render
+         * @fires Highcharts.Chart#event:updatedData
+         */
+        Chart.prototype.redraw = function (animation) {
+          fireEvent(this, "beforeRedraw");
+          var chart = this,
+            axes = chart.axes,
+            series = chart.series,
+            pointer = chart.pointer,
+            legend = chart.legend,
+            legendUserOptions = chart.userOptions.legend,
+            redrawLegend = chart.isDirtyLegend,
+            hasStackedSeries,
+            hasDirtyStacks,
+            hasCartesianSeries = chart.hasCartesianSeries,
+            isDirtyBox = chart.isDirtyBox,
+            i,
+            serie,
+            renderer = chart.renderer,
+            isHiddenChart = renderer.isHidden(),
+            afterRedraw = [];
+          // Handle responsive rules, not only on resize (#6130)
+          if (chart.setResponsive) {
+            chart.setResponsive(false);
+          }
+          // Set the global animation. When chart.hasRendered is not true, the
+          // redraw call comes from a responsive rule and animation should not
+          // occur.
+          setAnimation(chart.hasRendered ? animation : false, chart);
+          if (isHiddenChart) {
+            chart.temporaryDisplay();
+          }
+          // Adjust title layout (reflow multiline text)
+          chart.layOutTitles();
+          // link stacked series
+          i = series.length;
+          while (i--) {
+            serie = series[i];
+            if (serie.options.stacking) {
+              hasStackedSeries = true;
+              if (serie.isDirty) {
+                hasDirtyStacks = true;
+                break;
+              }
+            }
+          }
+          if (hasDirtyStacks) {
+            // mark others as dirty
+            i = series.length;
+            while (i--) {
+              serie = series[i];
+              if (serie.options.stacking) {
+                serie.isDirty = true;
+              }
+            }
+          }
+          // Handle updated data in the series
+          series.forEach(function (serie) {
+            if (serie.isDirty) {
+              if (serie.options.legendType === "point") {
+                if (typeof serie.updateTotals === "function") {
+                  serie.updateTotals();
+                }
+                redrawLegend = true;
+              } else if (
+                legendUserOptions &&
+                (legendUserOptions.labelFormatter ||
+                  legendUserOptions.labelFormat)
+              ) {
+                redrawLegend = true; // #2165
+              }
+            }
+            if (serie.isDirtyData) {
+              fireEvent(serie, "updatedData");
+            }
+          });
+          // handle added or removed series
+          if (redrawLegend && legend && legend.options.enabled) {
+            // draw legend graphics
+            legend.render();
+            chart.isDirtyLegend = false;
+          }
+          // reset stacks
+          if (hasStackedSeries) {
+            chart.getStacks();
+          }
+          if (hasCartesianSeries) {
+            // set axes scales
+            axes.forEach(function (axis) {
+              // Don't do setScale again if we're only resizing. Regression
+              // #13507. But we need it after chart.update (responsive), as
+              // axis is initialized again (#12137).
+              if (!chart.isResizing || !isNumber(axis.min)) {
+                axis.updateNames();
+                axis.setScale();
+              }
+            });
+          }
+          chart.getMargins(); // #3098
+          if (hasCartesianSeries) {
+            // If one axis is dirty, all axes must be redrawn (#792, #2169)
+            axes.forEach(function (axis) {
+              if (axis.isDirty) {
+                isDirtyBox = true;
+              }
+            });
+            // redraw axes
+            axes.forEach(function (axis) {
+              // Fire 'afterSetExtremes' only if extremes are set
+              var key = axis.min + "," + axis.max;
+              if (axis.extKey !== key) {
+                // #821, #4452
+                axis.extKey = key;
+                // prevent a recursive call to chart.redraw() (#1119)
+                afterRedraw.push(function () {
+                  fireEvent(
+                    axis,
+                    "afterSetExtremes",
+                    extend(axis.eventArgs, axis.getExtremes())
+                  ); // #747, #751
+                  delete axis.eventArgs;
+                });
+              }
+              if (isDirtyBox || hasStackedSeries) {
+                axis.redraw();
+              }
+            });
+          }
+          // the plot areas size has changed
+          if (isDirtyBox) {
+            chart.drawChartBox();
+          }
+          // Fire an event before redrawing series, used by the boost module to
+          // clear previous series renderings.
+          fireEvent(chart, "predraw");
+          // redraw affected series
+          series.forEach(function (serie) {
+            if ((isDirtyBox || serie.isDirty) && serie.visible) {
+              serie.redraw();
+            }
+            // Set it here, otherwise we will have unlimited 'updatedData' calls
+            // for a hidden series after setData(). Fixes #6012
+            serie.isDirtyData = false;
+          });
+          // move tooltip or reset
+          if (pointer) {
+            pointer.reset(true);
+          }
+          // redraw if canvas
+          renderer.draw();
+          // Fire the events
+          fireEvent(chart, "redraw");
+          fireEvent(chart, "render");
+          if (isHiddenChart) {
+            chart.temporaryDisplay(true);
+          }
+          // Fire callbacks that are put on hold until after the redraw
+          afterRedraw.forEach(function (callback) {
+            callback.call();
+          });
+        };
+        /**
+         * Get an axis, series or point object by `id` as given in the configuration
+         * options. Returns `undefined` if no item is found.
          *
-         * @sample {highcharts} highcharts/demo/areaspline/
-         *         Area spline chart
-         * @sample {highstock} stock/demo/areaspline/
-         *         Area spline chart
+         * @sample highcharts/plotoptions/series-id/
+         *         Get series by id
          *
-         * @extends   plotOptions.area
-         * @excluding step, boostThreshold, boostBlending
-         * @product   highcharts highstock
-         * @apioption plotOptions.areaspline
-         */
-        /**
-         * @see [fillColor](#plotOptions.areaspline.fillColor)
-         * @see [fillOpacity](#plotOptions.areaspline.fillOpacity)
+         * @function Highcharts.Chart#get
          *
-         * @apioption plotOptions.areaspline.color
-         */
-        /**
-         * @see [color](#plotOptions.areaspline.color)
-         * @see [fillOpacity](#plotOptions.areaspline.fillOpacity)
+         * @param {string} id
+         * The id as given in the configuration options.
          *
-         * @apioption plotOptions.areaspline.fillColor
+         * @return {Highcharts.Axis|Highcharts.Series|Highcharts.Point|undefined}
+         * The retrieved item.
          */
+        Chart.prototype.get = function (id) {
+          var ret,
+            series = this.series,
+            i;
+          /**
+           * @private
+           * @param {Highcharts.Axis|Highcharts.Series} item
+           * @return {boolean}
+           */
+          function itemById(item) {
+            return item.id === id || (item.options && item.options.id === id);
+          }
+          ret =
+            // Search axes
+            find(this.axes, itemById) ||
+            // Search series
+            find(this.series, itemById);
+          // Search points
+          for (i = 0; !ret && i < series.length; i++) {
+            ret = find(series[i].points || [], itemById);
+          }
+          return ret;
+        };
         /**
-         * @see [color](#plotOptions.areaspline.color)
-         * @see [fillColor](#plotOptions.areaspline.fillColor)
+         * Create the Axis instances based on the config options.
          *
-         * @default   {highcharts} 0.75
-         * @default   {highstock} 0.75
-         * @apioption plotOptions.areaspline.fillOpacity
-         */
-        defaultOptions.plotOptions.area, {
-            getStackPoints: areaProto.getStackPoints,
-            getGraphPath: areaProto.getGraphPath,
-            drawGraph: areaProto.drawGraph,
-            drawLegendSymbol: LegendSymbolMixin.drawRectangle
-        });
+         * @private
+         * @function Highcharts.Chart#getAxes
+         * @fires Highcharts.Chart#event:afterGetAxes
+         * @fires Highcharts.Chart#event:getAxes
+         */
+        Chart.prototype.getAxes = function () {
+          var chart = this,
+            options = this.options,
+            xAxisOptions = (options.xAxis = splat(options.xAxis || {})),
+            yAxisOptions = (options.yAxis = splat(options.yAxis || {})),
+            optionsArray;
+          fireEvent(this, "getAxes");
+          // make sure the options are arrays and add some members
+          xAxisOptions.forEach(function (axis, i) {
+            axis.index = i;
+            axis.isX = true;
+          });
+          yAxisOptions.forEach(function (axis, i) {
+            axis.index = i;
+          });
+          // concatenate all axis options into one array
+          optionsArray = xAxisOptions.concat(yAxisOptions);
+          optionsArray.forEach(function (axisOptions) {
+            new Axis(chart, axisOptions); // eslint-disable-line no-new
+          });
+          fireEvent(this, "afterGetAxes");
+        };
         /**
-         * A `areaspline` series. If the [type](#series.areaspline.type) option
-         * is not specified, it is inherited from [chart.type](#chart.type).
+         * Returns an array of all currently selected points in the chart. Points
+         * can be selected by clicking or programmatically by the
+         * {@link Highcharts.Point#select}
+         * function.
          *
+         * @sample highcharts/plotoptions/series-allowpointselect-line/
+         *         Get selected points
          *
-         * @extends   series,plotOptions.areaspline
-         * @excluding dataParser, dataURL, step, boostThreshold, boostBlending
-         * @product   highcharts highstock
-         * @apioption series.areaspline
-         */
-        /**
-         * @see [fillColor](#series.areaspline.fillColor)
-         * @see [fillOpacity](#series.areaspline.fillOpacity)
-         *
-         * @apioption series.areaspline.color
-         */
-        /**
-         * An array of data points for the series. For the `areaspline` series
-         * type, points can be given in the following ways:
-         *
-         * 1. An array of numerical values. In this case, the numerical values will be
-         *    interpreted as `y` options. The `x` values will be automatically
-         *    calculated, either starting at 0 and incremented by 1, or from
-         *    `pointStart` and `pointInterval` given in the series options. If the axis
-         *    has categories, these will be used. Example:
-         *    ```js
-         *    data: [0, 5, 3, 5]
-         *    ```
-         *
-         * 2. An array of arrays with 2 values. In this case, the values correspond to
-         *    `x,y`. If the first value is a string, it is applied as the name of the
-         *    point, and the `x` value is inferred.
-         *    ```js
-         *    data: [
-         *        [0, 10],
-         *        [1, 9],
-         *        [2, 3]
-         *    ]
-         *    ```
-         *
-         * 3. An array of objects with named values. The following snippet shows only a
-         *    few settings, see the complete options set below. If the total number of
-         *    data points exceeds the series'
-         *    [turboThreshold](#series.areaspline.turboThreshold), this option is not
-         *    available.
-         *    ```js
-         *    data: [{
-         *        x: 1,
-         *        y: 4,
-         *        name: "Point2",
-         *        color: "#00FF00"
-         *    }, {
-         *        x: 1,
-         *        y: 4,
-         *        name: "Point1",
-         *        color: "#FF00FF"
-         *    }]
-         *    ```
-         *
-         * @sample {highcharts} highcharts/chart/reflow-true/
-         *         Numerical values
-         * @sample {highcharts} highcharts/series/data-array-of-arrays/
-         *         Arrays of numeric x and y
-         * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
-         *         Arrays of datetime x and y
-         * @sample {highcharts} highcharts/series/data-array-of-name-value/
-         *         Arrays of point.name and y
-         * @sample {highcharts} highcharts/series/data-array-of-objects/
-         *         Config objects
-         *
-         * @type      {Array<number|Array<(number|string),(number|null)>|null|*>}
-         * @extends   series.line.data
-         * @product   highcharts highstock
-         * @apioption series.areaspline.data
-         */
-        /**
-         * @see [color](#series.areaspline.color)
-         * @see [fillOpacity](#series.areaspline.fillOpacity)
+         * @function Highcharts.Chart#getSelectedPoints
          *
-         * @apioption series.areaspline.fillColor
+         * @return {Array<Highcharts.Point>}
+         *         The currently selected points.
          */
+        Chart.prototype.getSelectedPoints = function () {
+          var points = [];
+          this.series.forEach(function (serie) {
+            // For one-to-one points inspect series.data in order to retrieve
+            // points outside the visible range (#6445). For grouped data,
+            // inspect the generated series.points.
+            points = points.concat(
+              serie.getPointsCollection().filter(function (point) {
+                return pick(point.selectedStaging, point.selected);
+              })
+            );
+          });
+          return points;
+        };
         /**
-         * @see [color](#series.areaspline.color)
-         * @see [fillColor](#series.areaspline.fillColor)
+         * Returns an array of all currently selected series in the chart. Series
+         * can be selected either programmatically by the
+         * {@link Highcharts.Series#select}
+         * function or by checking the checkbox next to the legend item if
+         * [series.showCheckBox](https://api.highcharts.com/highcharts/plotOptions.series.showCheckbox)
+         * is true.
          *
-         * @default   {highcharts} 0.75
-         * @default   {highstock} 0.75
-         * @apioption series.areaspline.fillOpacity
-         */
-        ''; // adds doclets above into transpilat
-
-    });
-    _registerModule(_modules, 'Series/ColumnSeries.js', [_modules['Core/Animation/AnimationUtilities.js'], _modules['Core/Series/Series.js'], _modules['Core/Color/Color.js'], _modules['Core/Globals.js'], _modules['Mixins/LegendSymbol.js'], _modules['Series/LineSeries.js'], _modules['Core/Utilities.js']], function (A, BaseSeries, Color, H, LegendSymbolMixin, LineSeries, U) {
-        /* *
+         * @sample highcharts/members/chart-getselectedseries/
+         *         Get selected series
          *
-         *  (c) 2010-2020 Torstein Honsi
+         * @function Highcharts.Chart#getSelectedSeries
          *
-         *  License: www.highcharts.com/license
+         * @return {Array<Highcharts.Series>}
+         *         The currently selected series.
+         */
+        Chart.prototype.getSelectedSeries = function () {
+          return this.series.filter(function (serie) {
+            return serie.selected;
+          });
+        };
+        /**
+         * Set a new title or subtitle for the chart.
          *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+         * @sample highcharts/members/chart-settitle/
+         *         Set title text and styles
          *
-         * */
-        var animObject = A.animObject;
-        var color = Color.parse;
-        var noop = H.noop;
-        var clamp = U.clamp,
-            defined = U.defined,
-            extend = U.extend,
-            isArray = U.isArray,
-            isNumber = U.isNumber,
-            merge = U.merge,
-            pick = U.pick,
-            objectEach = U.objectEach;
-        /**
-         * Adjusted width and x offset of the columns for grouping.
+         * @function Highcharts.Chart#setTitle
          *
-         * @private
-         * @interface Highcharts.ColumnMetricsObject
-         */ /**
-        * Width of the columns.
-        * @name Highcharts.ColumnMetricsObject#width
-        * @type {number}
-        */ /**
-        * Offset of the columns.
-        * @name Highcharts.ColumnMetricsObject#offset
-        * @type {number}
-        */
-        ''; // detach doclets above
-        /**
-         * The column series type.
+         * @param {Highcharts.TitleOptions} [titleOptions]
+         *        New title options. The title text itself is set by the
+         *        `titleOptions.text` property.
          *
-         * @private
-         * @class
-         * @name Highcharts.seriesTypes.column
+         * @param {Highcharts.SubtitleOptions} [subtitleOptions]
+         *        New subtitle options. The subtitle text itself is set by the
+         *        `subtitleOptions.text` property.
          *
-         * @augments Highcharts.Series
+         * @param {boolean} [redraw]
+         *        Whether to redraw the chart or wait for a later call to
+         *        `chart.redraw()`.
          */
-        var ColumnSeries = BaseSeries.seriesType('column', 'line', 
-            /**
-             * Column series display one column per value along an X axis.
-             *
-             * @sample {highcharts} highcharts/demo/column-basic/
-             *         Column chart
-             * @sample {highstock} stock/demo/column/
-             *         Column chart
-             *
-             * @extends      plotOptions.line
-             * @excluding    connectEnds, connectNulls, gapSize, gapUnit, linecap,
-             *               lineWidth, marker, step, useOhlcData
-             * @product      highcharts highstock
-             * @optionparent plotOptions.column
-             */
-            {
-                /**
-                 * The corner radius of the border surrounding each column or bar.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/column-borderradius/
-                 *         Rounded columns
-                 *
-                 * @product highcharts highstock gantt
-                 *
-                 * @private
-                 */
-                borderRadius: 0,
-                /**
-                 * When using automatic point colors pulled from the global
-                 * [colors](colors) or series-specific
-                 * [plotOptions.column.colors](series.colors) collections, this option
-                 * determines whether the chart should receive one color per series or
-                 * one color per point.
-                 *
-                 * In styled mode, the `colors` or `series.colors` arrays are not
-                 * supported, and instead this option gives the points individual color
-                 * class names on the form `highcharts-color-{n}`.
-                 *
-                 * @see [series colors](#plotOptions.column.colors)
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/column-colorbypoint-false/
-                 *         False by default
-                 * @sample {highcharts} highcharts/plotoptions/column-colorbypoint-true/
-                 *         True
-                 *
-                 * @type      {boolean}
-                 * @default   false
-                 * @since     2.0
-                 * @product   highcharts highstock gantt
-                 * @apioption plotOptions.column.colorByPoint
-                 */
-                /**
-                 * A series specific or series type specific color set to apply instead
-                 * of the global [colors](#colors) when [colorByPoint](
-                 * #plotOptions.column.colorByPoint) is true.
-                 *
-                 * @type      {Array<Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject>}
-                 * @since     3.0
-                 * @product   highcharts highstock gantt
-                 * @apioption plotOptions.column.colors
-                 */
-                /**
-                 * When `true`, the columns will center in the category, ignoring null
-                 * or missing points. When `false`, space will be reserved for null or
-                 * missing points.
-                 *
-                 * @sample {highcharts} highcharts/series-column/centerincategory/
-                 *         Center in category
-                 *
-                 * @since   8.0.1
-                 * @product highcharts highstock gantt
-                 *
-                 * @private
-                 */
-                centerInCategory: false,
-                /**
-                 * Padding between each value groups, in x axis units.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/column-grouppadding-default/
-                 *         0.2 by default
-                 * @sample {highcharts} highcharts/plotoptions/column-grouppadding-none/
-                 *         No group padding - all columns are evenly spaced
-                 *
-                 * @product highcharts highstock gantt
-                 *
-                 * @private
-                 */
-                groupPadding: 0.2,
-                /**
-                 * Whether to group non-stacked columns or to let them render
-                 * independent of each other. Non-grouped columns will be laid out
-                 * individually and overlap each other.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/column-grouping-false/
-                 *         Grouping disabled
-                 * @sample {highstock} highcharts/plotoptions/column-grouping-false/
-                 *         Grouping disabled
-                 *
-                 * @type      {boolean}
-                 * @default   true
-                 * @since     2.3.0
-                 * @product   highcharts highstock gantt
-                 * @apioption plotOptions.column.grouping
-                 */
-                /**
-                 * @ignore-option
-                 * @private
-                 */
-                marker: null,
-                /**
-                 * The maximum allowed pixel width for a column, translated to the
-                 * height of a bar in a bar chart. This prevents the columns from
-                 * becoming too wide when there is a small number of points in the
-                 * chart.
-                 *
-                 * @see [pointWidth](#plotOptions.column.pointWidth)
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/column-maxpointwidth-20/
-                 *         Limited to 50
-                 * @sample {highstock} highcharts/plotoptions/column-maxpointwidth-20/
-                 *         Limited to 50
-                 *
-                 * @type      {number}
-                 * @since     4.1.8
-                 * @product   highcharts highstock gantt
-                 * @apioption plotOptions.column.maxPointWidth
-                 */
-                /**
-                 * Padding between each column or bar, in x axis units.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/column-pointpadding-default/
-                 *         0.1 by default
-                 * @sample {highcharts} highcharts/plotoptions/column-pointpadding-025/
-                 *          0.25
-                 * @sample {highcharts} highcharts/plotoptions/column-pointpadding-none/
-                 *         0 for tightly packed columns
-                 *
-                 * @product highcharts highstock gantt
-                 *
-                 * @private
-                 */
-                pointPadding: 0.1,
-                /**
-                 * A pixel value specifying a fixed width for each column or bar point.
-                 * When `null`, the width is calculated from the `pointPadding` and
-                 * `groupPadding`. The width effects the dimension that is not based on
-                 * the point value. For column series it is the hoizontal length and for
-                 * bar series it is the vertical length.
-                 *
-                 * @see [maxPointWidth](#plotOptions.column.maxPointWidth)
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/column-pointwidth-20/
-                 *         20px wide columns regardless of chart width or the amount of
-                 *         data points
-                 *
-                 * @type      {number}
-                 * @since     1.2.5
-                 * @product   highcharts highstock gantt
-                 * @apioption plotOptions.column.pointWidth
-                 */
-                /**
-                 * A pixel value specifying a fixed width for the column or bar.
-                 * Overrides pointWidth on the series.
-                 *
-                 * @see [series.pointWidth](#plotOptions.column.pointWidth)
-                 *
-                 * @type      {number}
-                 * @default   undefined
-                 * @since     7.0.0
-                 * @product   highcharts highstock gantt
-                 * @apioption series.column.data.pointWidth
-                 */
-                /**
-                 * The minimal height for a column or width for a bar. By default,
-                 * 0 values are not shown. To visualize a 0 (or close to zero) point,
-                 * set the minimal point length to a pixel value like 3\. In stacked
-                 * column charts, minPointLength might not be respected for tightly
-                 * packed values.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/column-minpointlength/
-                 *         Zero base value
-                 * @sample {highcharts} highcharts/plotoptions/column-minpointlength-pos-and-neg/
-                 *         Positive and negative close to zero values
-                 *
-                 * @product highcharts highstock gantt
-                 *
-                 * @private
-                 */
-                minPointLength: 0,
-                /**
-                 * When the series contains less points than the crop threshold, all
-                 * points are drawn, event if the points fall outside the visible plot
-                 * area at the current zoom. The advantage of drawing all points
-                 * (including markers and columns), is that animation is performed on
-                 * updates. On the other hand, when the series contains more points than
-                 * the crop threshold, the series data is cropped to only contain points
-                 * that fall within the plot area. The advantage of cropping away
-                 * invisible points is to increase performance on large series.
-                 *
-                 * @product highcharts highstock gantt
-                 *
-                 * @private
-                 */
-                cropThreshold: 50,
-                /**
-                 * The X axis range that each point is valid for. This determines the
-                 * width of the column. On a categorized axis, the range will be 1
-                 * by default (one category unit). On linear and datetime axes, the
-                 * range will be computed as the distance between the two closest data
-                 * points.
-                 *
-                 * The default `null` means it is computed automatically, but this
-                 * option can be used to override the automatic value.
-                 *
-                 * This option is set by default to 1 if data sorting is enabled.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/column-pointrange/
-                 *         Set the point range to one day on a data set with one week
-                 *         between the points
-                 *
-                 * @type    {number|null}
-                 * @since   2.3
-                 * @product highcharts highstock gantt
-                 *
-                 * @private
-                 */
-                pointRange: null,
-                states: {
-                    /**
-                     * Options for the hovered point. These settings override the normal
-                     * state options when a point is moused over or touched.
-                     *
-                     * @extends   plotOptions.series.states.hover
-                     * @excluding halo, lineWidth, lineWidthPlus, marker
-                     * @product   highcharts highstock gantt
-                     */
-                    hover: {
-                        /** @ignore-option */
-                        halo: false,
-                        /**
-                         * A specific border color for the hovered point. Defaults to
-                         * inherit the normal state border color.
-                         *
-                         * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-                         * @product   highcharts gantt
-                         * @apioption plotOptions.column.states.hover.borderColor
-                         */
-                        /**
-                         * A specific color for the hovered point.
-                         *
-                         * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-                         * @product   highcharts gantt
-                         * @apioption plotOptions.column.states.hover.color
-                         */
-                        /**
-                         * How much to brighten the point on interaction. Requires the
-                         * main color to be defined in hex or rgb(a) format.
-                         *
-                         * In styled mode, the hover brightening is by default replaced
-                         * with a fill-opacity set in the `.highcharts-point:hover`
-                         * rule.
-                         *
-                         * @sample {highcharts} highcharts/plotoptions/column-states-hover-brightness/
-                         *         Brighten by 0.5
-                         *
-                         * @product highcharts highstock gantt
-                         */
-                        brightness: 0.1
-                    },
-                    /**
-                     * Options for the selected point. These settings override the
-                     * normal state options when a point is selected.
-                     *
-                     * @extends   plotOptions.series.states.select
-                     * @excluding halo, lineWidth, lineWidthPlus, marker
-                     * @product   highcharts highstock gantt
-                     */
-                    select: {
-                        /**
-                         * A specific color for the selected point.
-                         *
-                         * @type    {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-                         * @default #cccccc
-                         * @product highcharts highstock gantt
-                         */
-                        color: '#cccccc',
-                        /**
-                         * A specific border color for the selected point.
-                         *
-                         * @type    {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-                         * @default #000000
-                         * @product highcharts highstock gantt
-                         */
-                        borderColor: '#000000'
-                    }
-                },
-                dataLabels: {
-                    align: void 0,
-                    verticalAlign: void 0,
-                    /**
-                     * The y position offset of the label relative to the point in
-                     * pixels.
-                     *
-                     * @type {number}
-                     */
-                    y: void 0
-                },
-                // false doesn't work well: https://jsfiddle.net/highcharts/hz8fopan/14/
-                /**
-                 * @ignore-option
-                 * @private
-                 */
-                startFromThreshold: true,
-                stickyTracking: false,
-                tooltip: {
-                    distance: 6
-                },
-                /**
-                 * The Y axis value to serve as the base for the columns, for
-                 * distinguishing between values above and below a threshold. If `null`,
-                 * the columns extend from the padding Y axis minimum.
-                 *
-                 * @type    {number|null}
-                 * @since   2.0
-                 * @product highcharts
-                 *
-                 * @private
-                 */
-                threshold: 0,
-                /**
-                 * The width of the border surrounding each column or bar. Defaults to
-                 * `1` when there is room for a border, but to `0` when the columns are
-                 * so dense that a border would cover the next column.
-                 *
-                 * In styled mode, the stroke width can be set with the
-                 * `.highcharts-point` rule.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/column-borderwidth/
-                 *         2px black border
-                 *
-                 * @type      {number}
-                 * @default   undefined
-                 * @product   highcharts highstock gantt
-                 * @apioption plotOptions.column.borderWidth
-                 */
-                /**
-                 * The color of the border surrounding each column or bar.
-                 *
-                 * In styled mode, the border stroke can be set with the
-                 * `.highcharts-point` rule.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/column-bordercolor/
-                 *         Dark gray border
-                 *
-                 * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-                 * @default   #ffffff
-                 * @product   highcharts highstock gantt
-                 *
-                 * @private
-                 */
-                borderColor: '#ffffff'
-            }, 
-            /**
-             * @lends seriesTypes.column.prototype
-             */
-            {
-                cropShoulder: 0,
-                // When tooltip is not shared, this series (and derivatives) requires
-                // direct touch/hover. KD-tree does not apply.
-                directTouch: true,
-                trackerGroups: ['group', 'dataLabelsGroup'],
-                // use separate negative stacks, unlike area stacks where a negative
-                // point is substracted from previous (#1910)
-                negStacks: true,
-                /* eslint-disable valid-jsdoc */
-                /**
-                 * Initialize the series. Extends the basic Series.init method by
-                 * marking other series of the same type as dirty.
-                 *
-                 * @private
-                 * @function Highcharts.seriesTypes.column#init
-                 * @return {void}
-                 */
-                init: function () {
-                    LineSeries.prototype.init.apply(this, arguments);
-                var series = this,
-                    chart = series.chart;
-                // if the series is added dynamically, force redraw of other
-                // series affected by a new column
-                if (chart.hasRendered) {
-                    chart.series.forEach(function (otherSeries) {
-                        if (otherSeries.type === series.type) {
-                            otherSeries.isDirty = true;
-                        }
-                    });
-                }
-            },
-            /**
-             * Return the width and x offset of the columns adjusted for grouping,
-             * groupPadding, pointPadding, pointWidth etc.
-             *
-             * @private
-             * @function Highcharts.seriesTypes.column#getColumnMetrics
-             * @return {Highcharts.ColumnMetricsObject}
-             */
-            getColumnMetrics: function () {
-                var series = this,
-                    options = series.options,
-                    xAxis = series.xAxis,
-                    yAxis = series.yAxis,
-                    reversedStacks = xAxis.options.reversedStacks, 
-                    // Keep backward compatibility: reversed xAxis had reversed
-                    // stacks
-                    reverseStacks = (xAxis.reversed && !reversedStacks) ||
-                        (!xAxis.reversed && reversedStacks),
-                    stackKey,
-                    stackGroups = {},
-                    columnCount = 0;
-                // Get the total number of column type series. This is called on
-                // every series. Consider moving this logic to a chart.orderStacks()
-                // function and call it on init, addSeries and removeSeries
-                if (options.grouping === false) {
-                    columnCount = 1;
-                }
-                else {
-                    series.chart.series.forEach(function (otherSeries) {
-                        var otherYAxis = otherSeries.yAxis,
-                            otherOptions = otherSeries.options,
-                            columnIndex;
-                        if (otherSeries.type === series.type &&
-                            (otherSeries.visible ||
-                                !series.chart.options.chart
-                                    .ignoreHiddenSeries) &&
-                            yAxis.len === otherYAxis.len &&
-                            yAxis.pos === otherYAxis.pos) { // #642, #2086
-                            if (otherOptions.stacking && otherOptions.stacking !== 'group') {
-                                stackKey = otherSeries.stackKey;
-                                if (typeof stackGroups[stackKey] ===
-                                    'undefined') {
-                                    stackGroups[stackKey] = columnCount++;
-                                }
-                                columnIndex = stackGroups[stackKey];
-                            }
-                            else if (otherOptions.grouping !== false) { // #1162
-                                columnIndex = columnCount++;
-                            }
-                            otherSeries.columnIndex = columnIndex;
-                        }
-                    });
-                }
-                var categoryWidth = Math.min(Math.abs(xAxis.transA) * ((xAxis.ordinal && xAxis.ordinal.slope) ||
-                        options.pointRange ||
-                        xAxis.closestPointRange ||
-                        xAxis.tickInterval ||
-                        1), // #2610
-                    xAxis.len // #1535
-                    ),
-                    groupPadding = categoryWidth * options.groupPadding,
-                    groupWidth = categoryWidth - 2 * groupPadding,
-                    pointOffsetWidth = groupWidth / (columnCount || 1),
-                    pointWidth = Math.min(options.maxPointWidth || xAxis.len,
-                    pick(options.pointWidth,
-                    pointOffsetWidth * (1 - 2 * options.pointPadding))),
-                    pointPadding = (pointOffsetWidth - pointWidth) / 2, 
-                    // #1251, #3737
-                    colIndex = (series.columnIndex || 0) + (reverseStacks ? 1 : 0),
-                    pointXOffset = pointPadding +
-                        (groupPadding +
-                            colIndex * pointOffsetWidth -
-                            (categoryWidth / 2)) * (reverseStacks ? -1 : 1);
-                // Save it for reading in linked series (Error bars particularly)
-                series.columnMetrics = {
-                    width: pointWidth,
-                    offset: pointXOffset,
-                    paddedWidth: pointOffsetWidth,
-                    columnCount: columnCount
-                };
-                return series.columnMetrics;
-            },
-            /**
-             * Make the columns crisp. The edges are rounded to the nearest full
-             * pixel.
-             *
-             * @private
-             * @function Highcharts.seriesTypes.column#crispCol
-             * @param {number} x
-             * @param {number} y
-             * @param {number} w
-             * @param {number} h
-             * @return {Highcharts.BBoxObject}
-             */
-            crispCol: function (x, y, w, h) {
-                var chart = this.chart,
-                    borderWidth = this.borderWidth,
-                    xCrisp = -(borderWidth % 2 ? 0.5 : 0),
-                    yCrisp = borderWidth % 2 ? 0.5 : 1,
-                    right,
-                    bottom,
-                    fromTop;
-                if (chart.inverted && chart.renderer.isVML) {
-                    yCrisp += 1;
-                }
-                // Horizontal. We need to first compute the exact right edge, then
-                // round it and compute the width from there.
-                if (this.options.crisp) {
-                    right = Math.round(x + w) + xCrisp;
-                    x = Math.round(x) + xCrisp;
-                    w = right - x;
-                }
-                // Vertical
-                bottom = Math.round(y + h) + yCrisp;
-                fromTop = Math.abs(y) <= 0.5 && bottom > 0.5; // #4504, #4656
-                y = Math.round(y) + yCrisp;
-                h = bottom - y;
-                // Top edges are exceptions
-                if (fromTop && h) { // #5146
-                    y -= 1;
-                    h += 1;
-                }
-                return {
-                    x: x,
-                    y: y,
-                    width: w,
-                    height: h
+        Chart.prototype.setTitle = function (
+          titleOptions,
+          subtitleOptions,
+          redraw
+        ) {
+          this.applyDescription("title", titleOptions);
+          this.applyDescription("subtitle", subtitleOptions);
+          // The initial call also adds the caption. On update, chart.update will
+          // relay to Chart.setCaption.
+          this.applyDescription("caption", void 0);
+          this.layOutTitles(redraw);
+        };
+        /**
+         * Apply a title, subtitle or caption for the chart
+         *
+         * @private
+         * @function Highcharts.Chart#applyDescription
+         * @param name {string}
+         * Either title, subtitle or caption
+         * @param {Highcharts.TitleOptions|Highcharts.SubtitleOptions|Highcharts.CaptionOptions|undefined} explicitOptions
+         * The options to set, will be merged with default options.
+         */
+        Chart.prototype.applyDescription = function (name, explicitOptions) {
+          var chart = this;
+          // Default style
+          var style =
+            name === "title"
+              ? {
+                  color: "#333333",
+                  fontSize: this.options.isStock ? "16px" : "18px", // #2944
+                }
+              : {
+                  color: "#666666",
                 };
-            },
-            /**
-             * Adjust for missing columns, according to the `centerInCategory`
-             * option. Missing columns are either single points or stacks where the
-             * point or points are either missing or null.
-             *
-             * @private
-             * @function Highcharts.seriesTypes.column#adjustForMissingColumns
-             * @param {number} x
-             *        The x coordinate of the column, left side
-             * @param {number} pointWidth
-             *        The pointWidth, already computed upstream
-             * @param {Highcharts.ColumnPoint} point
-             *        The point instance
-             * @param {Highcharts.ColumnMetricsObject} metrics
-             *        The series-wide column metrics
-             * @return {number}
-             *        The adjusted x position, or the original if not adjusted
-             */
-            adjustForMissingColumns: function (x, pointWidth, point, metrics) {
-                var _this = this;
-                var stacking = this.options.stacking;
-                if (!point.isNull && metrics.columnCount > 1) {
-                    var indexInCategory_1 = 0;
-                    var totalInCategory_1 = 0;
-                    // Loop over all the stacks on the Y axis. When stacking is
-                    // enabled, these are real point stacks. When stacking is not
-                    // enabled, but `centerInCategory` is true, there is one stack
-                    // handling the grouping of points in each category. This is
-                    // done in the `setGroupedPoints` function.
-                    objectEach(this.yAxis.stacking && this.yAxis.stacking.stacks, function (stack) {
-                        if (typeof point.x === 'number') {
-                            var stackItem = stack[point.x.toString()];
-                            if (stackItem) {
-                                var pointValues = stackItem.points[_this.index],
-                                    total = stackItem.total;
-                                // If true `stacking` is enabled, count the
-                                // total number of non-null stacks in the
-                                // category, and note which index this point is
-                                // within those stacks.
-                                if (stacking) {
-                                    if (pointValues) {
-                                        indexInCategory_1 = totalInCategory_1;
-                                    }
-                                    if (stackItem.hasValidPoints) {
-                                        totalInCategory_1++;
-                                    }
-                                    // If `stacking` is not enabled, look for the
-                                    // index and total of the `group` stack.
-                                }
-                                else if (isArray(pointValues)) {
-                                    indexInCategory_1 = pointValues[1];
-                                    totalInCategory_1 = total || 0;
-                                }
-                            }
-                        }
-                    });
-                    // Compute the adjusted x position
-                    var boxWidth = (totalInCategory_1 - 1) * metrics.paddedWidth +
-                            pointWidth;
-                    x = (point.plotX || 0) + boxWidth / 2 - pointWidth -
-                        indexInCategory_1 * metrics.paddedWidth;
-                }
-                return x;
-            },
-            /**
-             * Translate each point to the plot area coordinate system and find
-             * shape positions
-             *
-             * @private
-             * @function Highcharts.seriesTypes.column#translate
-             */
-            translate: function () {
-                var series = this,
-                    chart = series.chart,
-                    options = series.options,
-                    dense = series.dense =
-                        series.closestPointRange * series.xAxis.transA < 2,
-                    borderWidth = series.borderWidth = pick(options.borderWidth,
-                    dense ? 0 : 1 // #3635
-                    ),
-                    xAxis = series.xAxis,
-                    yAxis = series.yAxis,
-                    threshold = options.threshold,
-                    translatedThreshold = series.translatedThreshold =
-                        yAxis.getThreshold(threshold),
-                    minPointLength = pick(options.minPointLength, 5),
-                    metrics = series.getColumnMetrics(),
-                    seriesPointWidth = metrics.width, 
-                    // postprocessed for border width
-                    seriesBarW = series.barW =
-                        Math.max(seriesPointWidth, 1 + 2 * borderWidth),
-                    seriesXOffset = series.pointXOffset = metrics.offset,
-                    dataMin = series.dataMin,
-                    dataMax = series.dataMax;
-                if (chart.inverted) {
-                    translatedThreshold -= 0.5; // #3355
-                }
-                // When the pointPadding is 0, we want the columns to be packed
-                // tightly, so we allow individual columns to have individual sizes.
-                // When pointPadding is greater, we strive for equal-width columns
-                // (#2694).
-                if (options.pointPadding) {
-                    seriesBarW = Math.ceil(seriesBarW);
-                }
-                LineSeries.prototype.translate.apply(series);
-                // Record the new values
-                series.points.forEach(function (point) {
-                    var yBottom = pick(point.yBottom,
-                        translatedThreshold),
-                        safeDistance = 999 + Math.abs(yBottom),
-                        pointWidth = seriesPointWidth,
-                        plotX = point.plotX || 0, 
-                        // Don't draw too far outside plot area (#1303, #2241,
-                        // #4264)
-                        plotY = clamp(point.plotY, -safeDistance,
-                        yAxis.len + safeDistance),
-                        barX = plotX + seriesXOffset,
-                        barW = seriesBarW,
-                        barY = Math.min(plotY,
-                        yBottom),
-                        up,
-                        barH = Math.max(plotY,
-                        yBottom) - barY;
-                    // Handle options.minPointLength
-                    if (minPointLength && Math.abs(barH) < minPointLength) {
-                        barH = minPointLength;
-                        up = (!yAxis.reversed && !point.negative) ||
-                            (yAxis.reversed && point.negative);
-                        // Reverse zeros if there's no positive value in the series
-                        // in visible range (#7046)
-                        if (isNumber(threshold) &&
-                            isNumber(dataMax) &&
-                            point.y === threshold &&
-                            dataMax <= threshold &&
-                            // and if there's room for it (#7311)
-                            (yAxis.min || 0) < threshold &&
-                            // if all points are the same value (i.e zero) not draw
-                            // as negative points (#10646)
-                            dataMin !== dataMax) {
-                            up = !up;
-                        }
-                        // If stacked...
-                        barY = (Math.abs(barY - translatedThreshold) > minPointLength ?
-                            // ...keep position
-                            yBottom - minPointLength :
-                            // #1485, #4051
-                            translatedThreshold -
-                                (up ? minPointLength : 0));
-                    }
-                    // Handle point.options.pointWidth
-                    // @todo Handle grouping/stacking too. Calculate offset properly
-                    if (defined(point.options.pointWidth)) {
-                        pointWidth = barW =
-                            Math.ceil(point.options.pointWidth);
-                        barX -= Math.round((pointWidth - seriesPointWidth) / 2);
-                    }
-                    // Adjust for null or missing points
-                    if (options.centerInCategory) {
-                        barX = series.adjustForMissingColumns(barX, pointWidth, point, metrics);
-                    }
-                    // Cache for access in polar
-                    point.barX = barX;
-                    point.pointWidth = pointWidth;
-                    // Fix the tooltip on center of grouped columns (#1216, #424,
-                    // #3648)
-                    point.tooltipPos = chart.inverted ?
-                        [
-                            yAxis.len + yAxis.pos - chart.plotLeft - plotY,
-                            xAxis.len + xAxis.pos - chart.plotTop - (plotX || 0) - seriesXOffset - barW / 2,
-                            barH
-                        ] :
-                        [barX + barW / 2, plotY + yAxis.pos -
-                                chart.plotTop, barH];
-                    // Register shape type and arguments to be used in drawPoints
-                    // Allow shapeType defined on pointClass level
-                    point.shapeType =
-                        series.pointClass.prototype.shapeType || 'rect';
-                    point.shapeArgs = series.crispCol.apply(series, point.isNull ?
-                        // #3169, drilldown from null must have a position to work
-                        // from #6585, dataLabel should be placed on xAxis, not
-                        // floating in the middle of the chart
-                        [barX, translatedThreshold, barW, 0] :
-                        [barX, barY, barW, barH]);
-                });
-            },
-            getSymbol: noop,
+          // Merge default options with explicit options
+          var options = (this.options[name] = merge(
+            // Default styles
+            !this.styledMode && { style: style },
+            this.options[name],
+            explicitOptions
+          ));
+          var elem = this[name];
+          if (elem && explicitOptions) {
+            this[name] = elem = elem.destroy(); // remove old
+          }
+          if (options && !elem) {
+            elem = this.renderer
+              .text(options.text, 0, 0, options.useHTML)
+              .attr({
+                align: options.align,
+                class: "highcharts-" + name,
+                zIndex: options.zIndex || 4,
+              })
+              .add();
+            // Update methods, shortcut to Chart.setTitle, Chart.setSubtitle and
+            // Chart.setCaption
+            elem.update = function (updateOptions) {
+              var fn = {
+                title: "setTitle",
+                subtitle: "setSubtitle",
+                caption: "setCaption",
+              }[name];
+              chart[fn](updateOptions);
+            };
+            // Presentational
+            if (!this.styledMode) {
+              elem.css(options.style);
+            }
             /**
-             * Use a solid rectangle like the area series types
-             *
-             * @private
-             * @function Highcharts.seriesTypes.column#drawLegendSymbol
+             * The chart title. The title has an `update` method that allows
+             * modifying the options directly or indirectly via
+             * `chart.update`.
              *
-             * @param {Highcharts.Legend} legend
-             *        The legend object
+             * @sample highcharts/members/title-update/
+             *         Updating titles
              *
-             * @param {Highcharts.Series|Highcharts.Point} item
-             *        The series (this) or point
+             * @name Highcharts.Chart#title
+             * @type {Highcharts.TitleObject}
              */
-            drawLegendSymbol: LegendSymbolMixin.drawRectangle,
             /**
-             * Columns have no graph
+             * The chart subtitle. The subtitle has an `update` method that
+             * allows modifying the options directly or indirectly via
+             * `chart.update`.
              *
-             * @private
-             * @function Highcharts.seriesTypes.column#drawGraph
-             */
-            drawGraph: function () {
-                this.group[this.dense ? 'addClass' : 'removeClass']('highcharts-dense-data');
-            },
-            /**
-             * Get presentational attributes
-             *
-             * @private
-             * @function Highcharts.seriesTypes.column#pointAttribs
-             *
-             * @param {Highcharts.ColumnPoint} point
-             *
-             * @param {string} state
-             *
-             * @return {Highcharts.SVGAttributes}
+             * @name Highcharts.Chart#subtitle
+             * @type {Highcharts.SubtitleObject}
              */
-            pointAttribs: function (point, state) {
-                var options = this.options, stateOptions, ret, p2o = this.pointAttrToOptions || {}, strokeOption = p2o.stroke || 'borderColor', strokeWidthOption = p2o['stroke-width'] || 'borderWidth', fill = (point && point.color) || this.color, 
-                    // set to fill when borderColor null:
-                    stroke = ((point && point[strokeOption]) ||
-                        options[strokeOption] ||
-                        this.color ||
-                        fill), strokeWidth = (point && point[strokeWidthOption]) ||
-                        options[strokeWidthOption] ||
-                        this[strokeWidthOption] || 0, dashstyle = (point && point.options.dashStyle) || options.dashStyle, opacity = pick(point && point.opacity, options.opacity, 1), zone, brightness;
-                // Handle zone colors
-                if (point && this.zones.length) {
-                    zone = point.getZone();
-                    // When zones are present, don't use point.color (#4267).
-                    // Changed order (#6527), added support for colorAxis (#10670)
-                    fill = (point.options.color ||
-                        (zone && (zone.color || point.nonZonedColor)) ||
-                        this.color);
-                    if (zone) {
-                        stroke = zone.borderColor || stroke;
-                        dashstyle = zone.dashStyle || dashstyle;
-                        strokeWidth = zone.borderWidth || strokeWidth;
-                    }
-                }
-                // Select or hover states
-                if (state && point) {
-                    stateOptions = merge(options.states[state], 
-                    // #6401
-                    point.options.states &&
-                        point.options.states[state] ||
-                        {});
-                    brightness = stateOptions.brightness;
-                    fill =
-                        stateOptions.color || (typeof brightness !== 'undefined' &&
-                            color(fill)
-                                .brighten(stateOptions.brightness)
-                                .get()) || fill;
-                    stroke = stateOptions[strokeOption] || stroke;
-                    strokeWidth =
-                        stateOptions[strokeWidthOption] || strokeWidth;
-                    dashstyle = stateOptions.dashStyle || dashstyle;
-                    opacity = pick(stateOptions.opacity, opacity);
-                }
-                ret = {
-                    fill: fill,
-                    stroke: stroke,
-                    'stroke-width': strokeWidth,
-                    opacity: opacity
+            this[name] = elem;
+          }
+        };
+        /**
+         * Internal function to lay out the chart title, subtitle and caption, and
+         * cache the full offset height for use in `getMargins`. The result is
+         * stored in `this.titleOffset`.
+         *
+         * @private
+         * @function Highcharts.Chart#layOutTitles
+         *
+         * @param {boolean} [redraw=true]
+         * @fires Highcharts.Chart#event:afterLayOutTitles
+         */
+        Chart.prototype.layOutTitles = function (redraw) {
+          var titleOffset = [0, 0, 0],
+            requiresDirtyBox,
+            renderer = this.renderer,
+            spacingBox = this.spacingBox;
+          // Lay out the title and the subtitle respectively
+          ["title", "subtitle", "caption"].forEach(function (key) {
+            var title = this[key],
+              titleOptions = this.options[key],
+              verticalAlign = titleOptions.verticalAlign || "top",
+              offset =
+                key === "title"
+                  ? -3
+                  : // Floating subtitle (#6574)
+                  verticalAlign === "top"
+                  ? titleOffset[0] + 2
+                  : 0,
+              titleSize,
+              height;
+            if (title) {
+              if (!this.styledMode) {
+                titleSize = titleOptions.style.fontSize;
+              }
+              titleSize = renderer.fontMetrics(titleSize, title).b;
+              title.css({
+                width:
+                  (titleOptions.width ||
+                    spacingBox.width + (titleOptions.widthAdjust || 0)) + "px",
+              });
+              // Skip the cache for HTML (#3481, #11666)
+              height = Math.round(title.getBBox(titleOptions.useHTML).height);
+              title.align(
+                extend(
+                  {
+                    y:
+                      verticalAlign === "bottom"
+                        ? titleSize
+                        : offset + titleSize,
+                    height: height,
+                  },
+                  titleOptions
+                ),
+                false,
+                "spacingBox"
+              );
+              if (!titleOptions.floating) {
+                if (verticalAlign === "top") {
+                  titleOffset[0] = Math.ceil(titleOffset[0] + height);
+                } else if (verticalAlign === "bottom") {
+                  titleOffset[2] = Math.ceil(titleOffset[2] + height);
+                }
+              }
+            }
+          }, this);
+          // Handle title.margin and caption.margin
+          if (
+            titleOffset[0] &&
+            (this.options.title.verticalAlign || "top") === "top"
+          ) {
+            titleOffset[0] += this.options.title.margin;
+          }
+          if (
+            titleOffset[2] &&
+            this.options.caption.verticalAlign === "bottom"
+          ) {
+            titleOffset[2] += this.options.caption.margin;
+          }
+          requiresDirtyBox =
+            !this.titleOffset ||
+            this.titleOffset.join(",") !== titleOffset.join(",");
+          // Used in getMargins
+          this.titleOffset = titleOffset;
+          fireEvent(this, "afterLayOutTitles");
+          if (!this.isDirtyBox && requiresDirtyBox) {
+            this.isDirtyBox = this.isDirtyLegend = requiresDirtyBox;
+            // Redraw if necessary (#2719, #2744)
+            if (this.hasRendered && pick(redraw, true) && this.isDirtyBox) {
+              this.redraw();
+            }
+          }
+        };
+        /**
+         * Internal function to get the chart width and height according to options
+         * and container size. Sets {@link Chart.chartWidth} and
+         * {@link Chart.chartHeight}.
+         *
+         * @private
+         * @function Highcharts.Chart#getChartSize
+         */
+        Chart.prototype.getChartSize = function () {
+          var chart = this,
+            optionsChart = chart.options.chart,
+            widthOption = optionsChart.width,
+            heightOption = optionsChart.height,
+            renderTo = chart.renderTo;
+          // Get inner width and height
+          if (!defined(widthOption)) {
+            chart.containerWidth = getStyle(renderTo, "width");
+          }
+          if (!defined(heightOption)) {
+            chart.containerHeight = getStyle(renderTo, "height");
+          }
+          /**
+           * The current pixel width of the chart.
+           *
+           * @name Highcharts.Chart#chartWidth
+           * @type {number}
+           */
+          chart.chartWidth = Math.max(
+            // #1393
+            0,
+            widthOption || chart.containerWidth || 600 // #1460
+          );
+          /**
+           * The current pixel height of the chart.
+           *
+           * @name Highcharts.Chart#chartHeight
+           * @type {number}
+           */
+          chart.chartHeight = Math.max(
+            0,
+            relativeLength(heightOption, chart.chartWidth) ||
+              (chart.containerHeight > 1 ? chart.containerHeight : 400)
+          );
+        };
+        /**
+         * If the renderTo element has no offsetWidth, most likely one or more of
+         * its parents are hidden. Loop up the DOM tree to temporarily display the
+         * parents, then save the original display properties, and when the true
+         * size is retrieved, reset them. Used on first render and on redraws.
+         *
+         * @private
+         * @function Highcharts.Chart#temporaryDisplay
+         *
+         * @param {boolean} [revert]
+         * Revert to the saved original styles.
+         */
+        Chart.prototype.temporaryDisplay = function (revert) {
+          var node = this.renderTo,
+            tempStyle;
+          if (!revert) {
+            while (node && node.style) {
+              // When rendering to a detached node, it needs to be temporarily
+              // attached in order to read styling and bounding boxes (#5783,
+              // #7024).
+              if (!doc.body.contains(node) && !node.parentNode) {
+                node.hcOrigDetached = true;
+                doc.body.appendChild(node);
+              }
+              if (
+                getStyle(node, "display", false) === "none" ||
+                node.hcOricDetached
+              ) {
+                node.hcOrigStyle = {
+                  display: node.style.display,
+                  height: node.style.height,
+                  overflow: node.style.overflow,
                 };
-                if (dashstyle) {
-                    ret.dashstyle = dashstyle;
-                }
-                return ret;
-            },
-            /**
-             * Draw the columns. For bars, the series.group is rotated, so the same
-             * coordinates apply for columns and bars. This method is inherited by
-             * scatter series.
-             *
-             * @private
-             * @function Highcharts.seriesTypes.column#drawPoints
-             */
-            drawPoints: function () {
-                var series = this,
-                    chart = this.chart,
-                    options = series.options,
-                    renderer = chart.renderer,
-                    animationLimit = options.animationLimit || 250,
-                    shapeArgs;
-                // draw the columns
-                series.points.forEach(function (point) {
-                    var plotY = point.plotY,
-                        graphic = point.graphic,
-                        hasGraphic = !!graphic,
-                        verb = graphic && chart.pointCount < animationLimit ?
-                            'animate' : 'attr';
-                    if (isNumber(plotY) && point.y !== null) {
-                        shapeArgs = point.shapeArgs;
-                        // When updating a series between 2d and 3d or cartesian and
-                        // polar, the shape type changes.
-                        if (graphic && point.hasNewShapeType()) {
-                            graphic = graphic.destroy();
-                        }
-                        // Set starting position for point sliding animation.
-                        if (series.enabledDataSorting) {
-                            point.startXPos = series.xAxis.reversed ?
-                                -(shapeArgs ? shapeArgs.width : 0) :
-                                series.xAxis.width;
-                        }
-                        if (!graphic) {
-                            point.graphic = graphic =
-                                renderer[point.shapeType](shapeArgs)
-                                    .add(point.group || series.group);
-                            if (graphic &&
-                                series.enabledDataSorting &&
-                                chart.hasRendered &&
-                                chart.pointCount < animationLimit) {
-                                graphic.attr({
-                                    x: point.startXPos
-                                });
-                                hasGraphic = true;
-                                verb = 'animate';
-                            }
-                        }
-                        if (graphic && hasGraphic) { // update
-                            graphic[verb](merge(shapeArgs));
-                        }
-                        // Border radius is not stylable (#6900)
-                        if (options.borderRadius) {
-                            graphic[verb]({
-                                r: options.borderRadius
-                            });
-                        }
-                        // Presentational
-                        if (!chart.styledMode) {
-                            graphic[verb](series.pointAttribs(point, (point.selected && 'select')))
-                                .shadow(point.allowShadow !== false && options.shadow, null, options.stacking && !options.borderRadius);
-                        }
-                        graphic.addClass(point.getClassName(), true);
-                    }
-                    else if (graphic) {
-                        point.graphic = graphic.destroy(); // #1269
-                    }
-                });
+                tempStyle = {
+                  display: "block",
+                  overflow: "hidden",
+                };
+                if (node !== this.renderTo) {
+                  tempStyle.height = 0;
+                }
+                css(node, tempStyle);
+                // If it still doesn't have an offset width after setting
+                // display to block, it probably has an !important priority
+                // #2631, 6803
+                if (!node.offsetWidth) {
+                  node.style.setProperty("display", "block", "important");
+                }
+              }
+              node = node.parentNode;
+              if (node === doc.body) {
+                break;
+              }
+            }
+          } else {
+            while (node && node.style) {
+              if (node.hcOrigStyle) {
+                css(node, node.hcOrigStyle);
+                delete node.hcOrigStyle;
+              }
+              if (node.hcOrigDetached) {
+                doc.body.removeChild(node);
+                node.hcOrigDetached = false;
+              }
+              node = node.parentNode;
+            }
+          }
+        };
+        /**
+         * Set the {@link Chart.container|chart container's} class name, in
+         * addition to `highcharts-container`.
+         *
+         * @function Highcharts.Chart#setClassName
+         *
+         * @param {string} [className]
+         * The additional class name.
+         */
+        Chart.prototype.setClassName = function (className) {
+          this.container.className =
+            "highcharts-container " + (className || "");
+        };
+        /**
+         * Get the containing element, determine the size and create the inner
+         * container div to hold the chart.
+         *
+         * @private
+         * @function Highcharts.Chart#afterGetContainer
+         * @fires Highcharts.Chart#event:afterGetContainer
+         */
+        Chart.prototype.getContainer = function () {
+          var chart = this,
+            container,
+            options = chart.options,
+            optionsChart = options.chart,
+            chartWidth,
+            chartHeight,
+            renderTo = chart.renderTo,
+            indexAttrName = "data-highcharts-chart",
+            oldChartIndex,
+            Ren,
+            containerId = uniqueKey(),
+            containerStyle,
+            key;
+          if (!renderTo) {
+            chart.renderTo = renderTo = optionsChart.renderTo;
+          }
+          if (isString(renderTo)) {
+            chart.renderTo = renderTo = doc.getElementById(renderTo);
+          }
+          // Display an error if the renderTo is wrong
+          if (!renderTo) {
+            error(13, true, chart);
+          }
+          // If the container already holds a chart, destroy it. The check for
+          // hasRendered is there because web pages that are saved to disk from
+          // the browser, will preserve the data-highcharts-chart attribute and
+          // the SVG contents, but not an interactive chart. So in this case,
+          // charts[oldChartIndex] will point to the wrong chart if any (#2609).
+          oldChartIndex = pInt(attr(renderTo, indexAttrName));
+          if (
+            isNumber(oldChartIndex) &&
+            charts[oldChartIndex] &&
+            charts[oldChartIndex].hasRendered
+          ) {
+            charts[oldChartIndex].destroy();
+          }
+          // Make a reference to the chart from the div
+          attr(renderTo, indexAttrName, chart.index);
+          // remove previous chart
+          renderTo.innerHTML = "";
+          // If the container doesn't have an offsetWidth, it has or is a child of
+          // a node that has display:none. We need to temporarily move it out to a
+          // visible state to determine the size, else the legend and tooltips
+          // won't render properly. The skipClone option is used in sparklines as
+          // a micro optimization, saving about 1-2 ms each chart.
+          if (!optionsChart.skipClone && !renderTo.offsetWidth) {
+            chart.temporaryDisplay();
+          }
+          // get the width and height
+          chart.getChartSize();
+          chartWidth = chart.chartWidth;
+          chartHeight = chart.chartHeight;
+          // Allow table cells and flex-boxes to shrink without the chart blocking
+          // them out (#6427)
+          css(renderTo, { overflow: "hidden" });
+          // Create the inner container
+          if (!chart.styledMode) {
+            containerStyle = extend(
+              {
+                position: "relative",
+                // needed for context menu (avoidscrollbars) and content
+                // overflow in IE
+                overflow: "hidden",
+                width: chartWidth + "px",
+                height: chartHeight + "px",
+                textAlign: "left",
+                lineHeight: "normal",
+                zIndex: 0,
+                "-webkit-tap-highlight-color": "rgba(0,0,0,0)",
+                userSelect: "none", // #13503
+              },
+              optionsChart.style
+            );
+          }
+          /**
+           * The containing HTML element of the chart. The container is
+           * dynamically inserted into the element given as the `renderTo`
+           * parameter in the {@link Highcharts#chart} constructor.
+           *
+           * @name Highcharts.Chart#container
+           * @type {Highcharts.HTMLDOMElement}
+           */
+          container = createElement(
+            "div",
+            {
+              id: containerId,
             },
-            /**
-             * Animate the column heights one by one from zero.
-             *
-             * @private
-             * @function Highcharts.seriesTypes.column#animate
-             *
-             * @param {boolean} init
-             *        Whether to initialize the animation or run it
-             */
-            animate: function (init) {
-                var series = this,
-                    yAxis = this.yAxis,
-                    options = series.options,
-                    inverted = this.chart.inverted,
-                    attr = {},
-                    translateProp = inverted ? 'translateX' : 'translateY',
-                    translateStart,
-                    translatedThreshold;
-                if (init) {
-                    attr.scaleY = 0.001;
-                    translatedThreshold = clamp(yAxis.toPixels(options.threshold), yAxis.pos, yAxis.pos + yAxis.len);
-                    if (inverted) {
-                        attr.translateX = translatedThreshold - yAxis.len;
-                    }
-                    else {
-                        attr.translateY = translatedThreshold;
-                    }
-                    // apply finnal clipping (used in Highstock) (#7083)
-                    // animation is done by scaleY, so cliping is for panes
-                    if (series.clipBox) {
-                        series.setClip();
-                    }
-                    series.group.attr(attr);
-                }
-                else { // run the animation
-                    translateStart = series.group.attr(translateProp);
-                    series.group.animate({ scaleY: 1 }, extend(animObject(series.options.animation), {
-                        // Do the scale synchronously to ensure smooth
-                        // updating (#5030, #7228)
-                        step: function (val, fx) {
-                            if (series.group) {
-                                attr[translateProp] = translateStart +
-                                    fx.pos * (yAxis.pos - translateStart);
-                                series.group.attr(attr);
-                            }
-                        }
-                    }));
+            containerStyle,
+            renderTo
+          );
+          chart.container = container;
+          // cache the cursor (#1650)
+          chart._cursor = container.style.cursor;
+          // Initialize the renderer
+          Ren = H[optionsChart.renderer] || H.Renderer;
+          /**
+           * The renderer instance of the chart. Each chart instance has only one
+           * associated renderer.
+           *
+           * @name Highcharts.Chart#renderer
+           * @type {Highcharts.SVGRenderer}
+           */
+          chart.renderer = new Ren(
+            container,
+            chartWidth,
+            chartHeight,
+            null,
+            optionsChart.forExport,
+            options.exporting && options.exporting.allowHTML,
+            chart.styledMode
+          );
+          // Set the initial animation from the options
+          setAnimation(void 0, chart);
+          chart.setClassName(optionsChart.className);
+          if (!chart.styledMode) {
+            chart.renderer.setStyle(optionsChart.style);
+          } else {
+            // Initialize definitions
+            for (key in options.defs) {
+              // eslint-disable-line guard-for-in
+              this.renderer.definition(options.defs[key]);
+            }
+          }
+          // Add a reference to the charts index
+          chart.renderer.chartIndex = chart.index;
+          fireEvent(this, "afterGetContainer");
+        };
+        /**
+         * Calculate margins by rendering axis labels in a preliminary position.
+         * Title, subtitle and legend have already been rendered at this stage, but
+         * will be moved into their final positions.
+         *
+         * @private
+         * @function Highcharts.Chart#getMargins
+         * @fires Highcharts.Chart#event:getMargins
+         */
+        Chart.prototype.getMargins = function (skipAxes) {
+          var _a = this,
+            spacing = _a.spacing,
+            margin = _a.margin,
+            titleOffset = _a.titleOffset;
+          this.resetMargins();
+          // Adjust for title and subtitle
+          if (titleOffset[0] && !defined(margin[0])) {
+            this.plotTop = Math.max(this.plotTop, titleOffset[0] + spacing[0]);
+          }
+          if (titleOffset[2] && !defined(margin[2])) {
+            this.marginBottom = Math.max(
+              this.marginBottom,
+              titleOffset[2] + spacing[2]
+            );
+          }
+          // Adjust for legend
+          if (this.legend && this.legend.display) {
+            this.legend.adjustMargins(margin, spacing);
+          }
+          fireEvent(this, "getMargins");
+          if (!skipAxes) {
+            this.getAxisMargins();
+          }
+        };
+        /**
+         * @private
+         * @function Highcharts.Chart#getAxisMargins
+         */
+        Chart.prototype.getAxisMargins = function () {
+          var chart = this,
+            // [top, right, bottom, left]
+            axisOffset = (chart.axisOffset = [0, 0, 0, 0]),
+            colorAxis = chart.colorAxis,
+            margin = chart.margin,
+            getOffset = function (axes) {
+              axes.forEach(function (axis) {
+                if (axis.visible) {
+                  axis.getOffset();
+                }
+              });
+            };
+          // pre-render axes to get labels offset width
+          if (chart.hasCartesianSeries) {
+            getOffset(chart.axes);
+          } else if (colorAxis && colorAxis.length) {
+            getOffset(colorAxis);
+          }
+          // Add the axis offsets
+          marginNames.forEach(function (m, side) {
+            if (!defined(margin[side])) {
+              chart[m] += axisOffset[side];
+            }
+          });
+          chart.setChartSize();
+        };
+        /**
+         * Reflows the chart to its container. By default, the chart reflows
+         * automatically to its container following a `window.resize` event, as per
+         * the [chart.reflow](https://api.highcharts.com/highcharts/chart.reflow)
+         * option. However, there are no reliable events for div resize, so if the
+         * container is resized without a window resize event, this must be called
+         * explicitly.
+         *
+         * @sample highcharts/members/chart-reflow/
+         *         Resize div and reflow
+         * @sample highcharts/chart/events-container/
+         *         Pop up and reflow
+         *
+         * @function Highcharts.Chart#reflow
+         *
+         * @param {global.Event} [e]
+         *        Event arguments. Used primarily when the function is called
+         *        internally as a response to window resize.
+         */
+        Chart.prototype.reflow = function (e) {
+          var chart = this,
+            optionsChart = chart.options.chart,
+            renderTo = chart.renderTo,
+            hasUserSize =
+              defined(optionsChart.width) && defined(optionsChart.height),
+            width = optionsChart.width || getStyle(renderTo, "width"),
+            height = optionsChart.height || getStyle(renderTo, "height"),
+            target = e ? e.target : win;
+          // Width and height checks for display:none. Target is doc in IE8 and
+          // Opera, win in Firefox, Chrome and IE9.
+          if (
+            !hasUserSize &&
+            !chart.isPrinting &&
+            width &&
+            height &&
+            (target === win || target === doc)
+          ) {
+            if (
+              width !== chart.containerWidth ||
+              height !== chart.containerHeight
+            ) {
+              U.clearTimeout(chart.reflowTimeout);
+              // When called from window.resize, e is set, else it's called
+              // directly (#2224)
+              chart.reflowTimeout = syncTimeout(
+                function () {
+                  // Set size, it may have been destroyed in the meantime
+                  // (#1257)
+                  if (chart.container) {
+                    chart.setSize(void 0, void 0, false);
+                  }
+                },
+                e ? 100 : 0
+              );
+            }
+            chart.containerWidth = width;
+            chart.containerHeight = height;
+          }
+        };
+        /**
+         * Toggle the event handlers necessary for auto resizing, depending on the
+         * `chart.reflow` option.
+         *
+         * @private
+         * @function Highcharts.Chart#setReflow
+         */
+        Chart.prototype.setReflow = function (reflow) {
+          var chart = this;
+          if (reflow !== false && !this.unbindReflow) {
+            this.unbindReflow = addEvent(win, "resize", function (e) {
+              // a removed event listener still runs in Edge and IE if the
+              // listener was removed while the event runs, so check if the
+              // chart is not destroyed (#11609)
+              if (chart.options) {
+                chart.reflow(e);
+              }
+            });
+            addEvent(this, "destroy", this.unbindReflow);
+          } else if (reflow === false && this.unbindReflow) {
+            // Unbind and unset
+            this.unbindReflow = this.unbindReflow();
+          }
+          // The following will add listeners to re-fit the chart before and after
+          // printing (#2284). However it only works in WebKit. Should have worked
+          // in Firefox, but not supported in IE.
+          /*
+                if (win.matchMedia) {
+                    win.matchMedia('print').addListener(function reflow() {
+                        chart.reflow();
+                    });
                 }
-            },
+                //*/
+        };
+        /**
+         * Resize the chart to a given width and height. In order to set the width
+         * only, the height argument may be skipped. To set the height only, pass
+         * `undefined` for the width.
+         *
+         * @sample highcharts/members/chart-setsize-button/
+         *         Test resizing from buttons
+         * @sample highcharts/members/chart-setsize-jquery-resizable/
+         *         Add a jQuery UI resizable
+         * @sample stock/members/chart-setsize/
+         *         Highstock with UI resizable
+         *
+         * @function Highcharts.Chart#setSize
+         *
+         * @param {number|null} [width]
+         *        The new pixel width of the chart. Since v4.2.6, the argument can
+         *        be `undefined` in order to preserve the current value (when
+         *        setting height only), or `null` to adapt to the width of the
+         *        containing element.
+         *
+         * @param {number|null} [height]
+         *        The new pixel height of the chart. Since v4.2.6, the argument can
+         *        be `undefined` in order to preserve the current value, or `null`
+         *        in order to adapt to the height of the containing element.
+         *
+         * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation=true]
+         *        Whether and how to apply animation.
+         *
+         * @return {void}
+         *
+         * @fires Highcharts.Chart#event:endResize
+         * @fires Highcharts.Chart#event:resize
+         */
+        Chart.prototype.setSize = function (width, height, animation) {
+          var chart = this,
+            renderer = chart.renderer,
+            globalAnimation;
+          // Handle the isResizing counter
+          chart.isResizing += 1;
+          // set the animation for the current process
+          setAnimation(animation, chart);
+          globalAnimation = renderer.globalAnimation;
+          chart.oldChartHeight = chart.chartHeight;
+          chart.oldChartWidth = chart.chartWidth;
+          if (typeof width !== "undefined") {
+            chart.options.chart.width = width;
+          }
+          if (typeof height !== "undefined") {
+            chart.options.chart.height = height;
+          }
+          chart.getChartSize();
+          // Resize the container with the global animation applied if enabled
+          // (#2503)
+          if (!chart.styledMode) {
+            (globalAnimation ? animate : css)(
+              chart.container,
+              {
+                width: chart.chartWidth + "px",
+                height: chart.chartHeight + "px",
+              },
+              globalAnimation
+            );
+          }
+          chart.setChartSize(true);
+          renderer.setSize(
+            chart.chartWidth,
+            chart.chartHeight,
+            globalAnimation
+          );
+          // handle axes
+          chart.axes.forEach(function (axis) {
+            axis.isDirty = true;
+            axis.setScale();
+          });
+          chart.isDirtyLegend = true; // force legend redraw
+          chart.isDirtyBox = true; // force redraw of plot and chart border
+          chart.layOutTitles(); // #2857
+          chart.getMargins();
+          chart.redraw(globalAnimation);
+          chart.oldChartHeight = null;
+          fireEvent(chart, "resize");
+          // Fire endResize and set isResizing back. If animation is disabled,
+          // fire without delay
+          syncTimeout(function () {
+            if (chart) {
+              fireEvent(chart, "endResize", null, function () {
+                chart.isResizing -= 1;
+              });
+            }
+          }, animObject(globalAnimation).duration);
+        };
+        /**
+         * Set the public chart properties. This is done before and after the
+         * pre-render to determine margin sizes.
+         *
+         * @private
+         * @function Highcharts.Chart#setChartSize
+         * @fires Highcharts.Chart#event:afterSetChartSize
+         */
+        Chart.prototype.setChartSize = function (skipAxes) {
+          var chart = this,
+            inverted = chart.inverted,
+            renderer = chart.renderer,
+            chartWidth = chart.chartWidth,
+            chartHeight = chart.chartHeight,
+            optionsChart = chart.options.chart,
+            spacing = chart.spacing,
+            clipOffset = chart.clipOffset,
+            clipX,
+            clipY,
+            plotLeft,
+            plotTop,
+            plotWidth,
+            plotHeight,
+            plotBorderWidth;
+          /**
+           * The current left position of the plot area in pixels.
+           *
+           * @name Highcharts.Chart#plotLeft
+           * @type {number}
+           */
+          chart.plotLeft = plotLeft = Math.round(chart.plotLeft);
+          /**
+           * The current top position of the plot area in pixels.
+           *
+           * @name Highcharts.Chart#plotTop
+           * @type {number}
+           */
+          chart.plotTop = plotTop = Math.round(chart.plotTop);
+          /**
+           * The current width of the plot area in pixels.
+           *
+           * @name Highcharts.Chart#plotWidth
+           * @type {number}
+           */
+          chart.plotWidth = plotWidth = Math.max(
+            0,
+            Math.round(chartWidth - plotLeft - chart.marginRight)
+          );
+          /**
+           * The current height of the plot area in pixels.
+           *
+           * @name Highcharts.Chart#plotHeight
+           * @type {number}
+           */
+          chart.plotHeight = plotHeight = Math.max(
+            0,
+            Math.round(chartHeight - plotTop - chart.marginBottom)
+          );
+          chart.plotSizeX = inverted ? plotHeight : plotWidth;
+          chart.plotSizeY = inverted ? plotWidth : plotHeight;
+          chart.plotBorderWidth = optionsChart.plotBorderWidth || 0;
+          // Set boxes used for alignment
+          chart.spacingBox = renderer.spacingBox = {
+            x: spacing[3],
+            y: spacing[0],
+            width: chartWidth - spacing[3] - spacing[1],
+            height: chartHeight - spacing[0] - spacing[2],
+          };
+          chart.plotBox = renderer.plotBox = {
+            x: plotLeft,
+            y: plotTop,
+            width: plotWidth,
+            height: plotHeight,
+          };
+          plotBorderWidth = 2 * Math.floor(chart.plotBorderWidth / 2);
+          clipX = Math.ceil(Math.max(plotBorderWidth, clipOffset[3]) / 2);
+          clipY = Math.ceil(Math.max(plotBorderWidth, clipOffset[0]) / 2);
+          chart.clipBox = {
+            x: clipX,
+            y: clipY,
+            width: Math.floor(
+              chart.plotSizeX -
+                Math.max(plotBorderWidth, clipOffset[1]) / 2 -
+                clipX
+            ),
+            height: Math.max(
+              0,
+              Math.floor(
+                chart.plotSizeY -
+                  Math.max(plotBorderWidth, clipOffset[2]) / 2 -
+                  clipY
+              )
+            ),
+          };
+          if (!skipAxes) {
+            chart.axes.forEach(function (axis) {
+              axis.setAxisSize();
+              axis.setAxisTranslation();
+            });
+          }
+          fireEvent(chart, "afterSetChartSize", { skipAxes: skipAxes });
+        };
+        /**
+         * Initial margins before auto size margins are applied.
+         *
+         * @private
+         * @function Highcharts.Chart#resetMargins
+         */
+        Chart.prototype.resetMargins = function () {
+          fireEvent(this, "resetMargins");
+          var chart = this,
+            chartOptions = chart.options.chart;
+          // Create margin and spacing array
+          ["margin", "spacing"].forEach(function splashArrays(target) {
+            var value = chartOptions[target],
+              values = isObject(value) ? value : [value, value, value, value];
+            ["Top", "Right", "Bottom", "Left"].forEach(function (
+              sideName,
+              side
+            ) {
+              chart[target][side] = pick(
+                chartOptions[target + sideName],
+                values[side]
+              );
+            });
+          });
+          // Set margin names like chart.plotTop, chart.plotLeft,
+          // chart.marginRight, chart.marginBottom.
+          marginNames.forEach(function (m, side) {
+            chart[m] = pick(chart.margin[side], chart.spacing[side]);
+          });
+          chart.axisOffset = [0, 0, 0, 0]; // top, right, bottom, left
+          chart.clipOffset = [0, 0, 0, 0];
+        };
+        /**
+         * Internal function to draw or redraw the borders and backgrounds for chart
+         * and plot area.
+         *
+         * @private
+         * @function Highcharts.Chart#drawChartBox
+         * @fires Highcharts.Chart#event:afterDrawChartBox
+         */
+        Chart.prototype.drawChartBox = function () {
+          var chart = this,
+            optionsChart = chart.options.chart,
+            renderer = chart.renderer,
+            chartWidth = chart.chartWidth,
+            chartHeight = chart.chartHeight,
+            chartBackground = chart.chartBackground,
+            plotBackground = chart.plotBackground,
+            plotBorder = chart.plotBorder,
+            chartBorderWidth,
+            styledMode = chart.styledMode,
+            plotBGImage = chart.plotBGImage,
+            chartBackgroundColor = optionsChart.backgroundColor,
+            plotBackgroundColor = optionsChart.plotBackgroundColor,
+            plotBackgroundImage = optionsChart.plotBackgroundImage,
+            mgn,
+            bgAttr,
+            plotLeft = chart.plotLeft,
+            plotTop = chart.plotTop,
+            plotWidth = chart.plotWidth,
+            plotHeight = chart.plotHeight,
+            plotBox = chart.plotBox,
+            clipRect = chart.clipRect,
+            clipBox = chart.clipBox,
+            verb = "animate";
+          // Chart area
+          if (!chartBackground) {
+            chart.chartBackground = chartBackground = renderer
+              .rect()
+              .addClass("highcharts-background")
+              .add();
+            verb = "attr";
+          }
+          if (!styledMode) {
+            // Presentational
+            chartBorderWidth = optionsChart.borderWidth || 0;
+            mgn = chartBorderWidth + (optionsChart.shadow ? 8 : 0);
+            bgAttr = {
+              fill: chartBackgroundColor || "none",
+            };
+            if (chartBorderWidth || chartBackground["stroke-width"]) {
+              // #980
+              bgAttr.stroke = optionsChart.borderColor;
+              bgAttr["stroke-width"] = chartBorderWidth;
+            }
+            chartBackground.attr(bgAttr).shadow(optionsChart.shadow);
+          } else {
+            chartBorderWidth = mgn = chartBackground.strokeWidth();
+          }
+          chartBackground[verb]({
+            x: mgn / 2,
+            y: mgn / 2,
+            width: chartWidth - mgn - (chartBorderWidth % 2),
+            height: chartHeight - mgn - (chartBorderWidth % 2),
+            r: optionsChart.borderRadius,
+          });
+          // Plot background
+          verb = "animate";
+          if (!plotBackground) {
+            verb = "attr";
+            chart.plotBackground = plotBackground = renderer
+              .rect()
+              .addClass("highcharts-plot-background")
+              .add();
+          }
+          plotBackground[verb](plotBox);
+          if (!styledMode) {
+            // Presentational attributes for the background
+            plotBackground
+              .attr({
+                fill: plotBackgroundColor || "none",
+              })
+              .shadow(optionsChart.plotShadow);
+            // Create the background image
+            if (plotBackgroundImage) {
+              if (!plotBGImage) {
+                chart.plotBGImage = renderer
+                  .image(
+                    plotBackgroundImage,
+                    plotLeft,
+                    plotTop,
+                    plotWidth,
+                    plotHeight
+                  )
+                  .add();
+              } else {
+                if (plotBackgroundImage !== plotBGImage.attr("href")) {
+                  plotBGImage.attr("href", plotBackgroundImage);
+                }
+                plotBGImage.animate(plotBox);
+              }
+            }
+          }
+          // Plot clip
+          if (!clipRect) {
+            chart.clipRect = renderer.clipRect(clipBox);
+          } else {
+            clipRect.animate({
+              width: clipBox.width,
+              height: clipBox.height,
+            });
+          }
+          // Plot area border
+          verb = "animate";
+          if (!plotBorder) {
+            verb = "attr";
+            chart.plotBorder = plotBorder = renderer
+              .rect()
+              .addClass("highcharts-plot-border")
+              .attr({
+                zIndex: 1, // Above the grid
+              })
+              .add();
+          }
+          if (!styledMode) {
+            // Presentational
+            plotBorder.attr({
+              stroke: optionsChart.plotBorderColor,
+              "stroke-width": optionsChart.plotBorderWidth || 0,
+              fill: "none",
+            });
+          }
+          plotBorder[verb](
+            plotBorder.crisp(
+              {
+                x: plotLeft,
+                y: plotTop,
+                width: plotWidth,
+                height: plotHeight,
+              },
+              -plotBorder.strokeWidth()
+            )
+          ); // #3282 plotBorder should be negative;
+          // reset
+          chart.isDirtyBox = false;
+          fireEvent(this, "afterDrawChartBox");
+        };
+        /**
+         * Detect whether a certain chart property is needed based on inspecting its
+         * options and series. This mainly applies to the chart.inverted property,
+         * and in extensions to the chart.angular and chart.polar properties.
+         *
+         * @private
+         * @function Highcharts.Chart#propFromSeries
+         * @return {void}
+         */
+        Chart.prototype.propFromSeries = function () {
+          var chart = this,
+            optionsChart = chart.options.chart,
+            klass,
+            seriesOptions = chart.options.series,
+            i,
+            value;
+          /**
+           * The flag is set to `true` if a series of the chart is inverted.
+           *
+           * @name Highcharts.Chart#inverted
+           * @type {boolean|undefined}
+           */
+          ["inverted", "angular", "polar"].forEach(function (key) {
+            // The default series type's class
+            klass =
+              BaseSeries.seriesTypes[
+                optionsChart.type || optionsChart.defaultSeriesType
+              ];
+            // Get the value from available chart-wide properties
+            value =
+              // It is set in the options:
+              optionsChart[key] ||
+              // The default series class:
+              (klass && klass.prototype[key]);
+            // requires it
+            // 4. Check if any the chart's series require it
+            i = seriesOptions && seriesOptions.length;
+            while (!value && i--) {
+              klass = BaseSeries.seriesTypes[seriesOptions[i].type];
+              if (klass && klass.prototype[key]) {
+                value = true;
+              }
+            }
+            // Set the chart property
+            chart[key] = value;
+          });
+        };
+        /**
+         * Internal function to link two or more series together, based on the
+         * `linkedTo` option. This is done from `Chart.render`, and after
+         * `Chart.addSeries` and `Series.remove`.
+         *
+         * @private
+         * @function Highcharts.Chart#linkSeries
+         * @fires Highcharts.Chart#event:afterLinkSeries
+         */
+        Chart.prototype.linkSeries = function () {
+          var chart = this,
+            chartSeries = chart.series;
+          // Reset links
+          chartSeries.forEach(function (series) {
+            series.linkedSeries.length = 0;
+          });
+          // Apply new links
+          chartSeries.forEach(function (series) {
+            var linkedTo = series.options.linkedTo;
+            if (isString(linkedTo)) {
+              if (linkedTo === ":previous") {
+                linkedTo = chart.series[series.index - 1];
+              } else {
+                linkedTo = chart.get(linkedTo);
+              }
+              // #3341 avoid mutual linking
+              if (linkedTo && linkedTo.linkedParent !== series) {
+                linkedTo.linkedSeries.push(series);
+                series.linkedParent = linkedTo;
+                if (linkedTo.enabledDataSorting) {
+                  series.setDataSortingOptions();
+                }
+                series.visible = pick(
+                  series.options.visible,
+                  linkedTo.options.visible,
+                  series.visible
+                ); // #3879
+              }
+            }
+          });
+          fireEvent(this, "afterLinkSeries");
+        };
+        /**
+         * Render series for the chart.
+         *
+         * @private
+         * @function Highcharts.Chart#renderSeries
+         */
+        Chart.prototype.renderSeries = function () {
+          this.series.forEach(function (serie) {
+            serie.translate();
+            serie.render();
+          });
+        };
+        /**
+         * Render labels for the chart.
+         *
+         * @private
+         * @function Highcharts.Chart#renderLabels
+         */
+        Chart.prototype.renderLabels = function () {
+          var chart = this,
+            labels = chart.options.labels;
+          if (labels.items) {
+            labels.items.forEach(function (label) {
+              var style = extend(labels.style, label.style),
+                x = pInt(style.left) + chart.plotLeft,
+                y = pInt(style.top) + chart.plotTop + 12;
+              // delete to prevent rewriting in IE
+              delete style.left;
+              delete style.top;
+              chart.renderer
+                .text(label.html, x, y)
+                .attr({ zIndex: 2 })
+                .css(style)
+                .add();
+            });
+          }
+        };
+        /**
+         * Render all graphics for the chart. Runs internally on initialization.
+         *
+         * @private
+         * @function Highcharts.Chart#render
+         */
+        Chart.prototype.render = function () {
+          var chart = this,
+            axes = chart.axes,
+            colorAxis = chart.colorAxis,
+            renderer = chart.renderer,
+            options = chart.options,
+            correction = 0, // correction for X axis labels
+            tempWidth,
+            tempHeight,
+            redoHorizontal,
+            redoVertical,
+            renderAxes = function (axes) {
+              axes.forEach(function (axis) {
+                if (axis.visible) {
+                  axis.render();
+                }
+              });
+            };
+          // Title
+          chart.setTitle();
+          /**
+           * The overview of the chart's series.
+           *
+           * @name Highcharts.Chart#legend
+           * @type {Highcharts.Legend}
+           */
+          chart.legend = new Legend(chart, options.legend);
+          // Get stacks
+          if (chart.getStacks) {
+            chart.getStacks();
+          }
+          // Get chart margins
+          chart.getMargins(true);
+          chart.setChartSize();
+          // Record preliminary dimensions for later comparison
+          tempWidth = chart.plotWidth;
+          axes.some(function (axis) {
+            if (
+              axis.horiz &&
+              axis.visible &&
+              axis.options.labels.enabled &&
+              axis.series.length
+            ) {
+              // 21 is the most common correction for X axis labels
+              correction = 21;
+              return true;
+            }
+          });
+          // use Math.max to prevent negative plotHeight
+          chart.plotHeight = Math.max(chart.plotHeight - correction, 0);
+          tempHeight = chart.plotHeight;
+          // Get margins by pre-rendering axes
+          axes.forEach(function (axis) {
+            axis.setScale();
+          });
+          chart.getAxisMargins();
+          // If the plot area size has changed significantly, calculate tick
+          // positions again
+          redoHorizontal = tempWidth / chart.plotWidth > 1.1;
+          // Height is more sensitive, use lower threshold
+          redoVertical = tempHeight / chart.plotHeight > 1.05;
+          if (redoHorizontal || redoVertical) {
+            axes.forEach(function (axis) {
+              if (
+                (axis.horiz && redoHorizontal) ||
+                (!axis.horiz && redoVertical)
+              ) {
+                // update to reflect the new margins
+                axis.setTickInterval(true);
+              }
+            });
+            chart.getMargins(); // second pass to check for new labels
+          }
+          // Draw the borders and backgrounds
+          chart.drawChartBox();
+          // Axes
+          if (chart.hasCartesianSeries) {
+            renderAxes(axes);
+          } else if (colorAxis && colorAxis.length) {
+            renderAxes(colorAxis);
+          }
+          // The series
+          if (!chart.seriesGroup) {
+            chart.seriesGroup = renderer
+              .g("series-group")
+              .attr({ zIndex: 3 })
+              .add();
+          }
+          chart.renderSeries();
+          // Labels
+          chart.renderLabels();
+          // Credits
+          chart.addCredits();
+          // Handle responsiveness
+          if (chart.setResponsive) {
+            chart.setResponsive();
+          }
+          // Handle scaling
+          chart.updateContainerScaling();
+          // Set flag
+          chart.hasRendered = true;
+        };
+        /**
+         * Set a new credits label for the chart.
+         *
+         * @sample highcharts/credits/credits-update/
+         *         Add and update credits
+         *
+         * @function Highcharts.Chart#addCredits
+         *
+         * @param {Highcharts.CreditsOptions} [credits]
+         * A configuration object for the new credits.
+         */
+        Chart.prototype.addCredits = function (credits) {
+          var chart = this,
+            creds = merge(true, this.options.credits, credits);
+          if (creds.enabled && !this.credits) {
             /**
-             * Remove this series from the chart
+             * The chart's credits label. The label has an `update` method that
+             * allows setting new options as per the
+             * [credits options set](https://api.highcharts.com/highcharts/credits).
              *
-             * @private
-             * @function Highcharts.seriesTypes.column#remove
+             * @name Highcharts.Chart#credits
+             * @type {Highcharts.SVGElement}
              */
-            remove: function () {
-                var series = this,
-                    chart = series.chart;
-                // column and bar series affects other series of the same type
-                // as they are either stacked or grouped
-                if (chart.hasRendered) {
-                    chart.series.forEach(function (otherSeries) {
-                        if (otherSeries.type === series.type) {
-                            otherSeries.isDirty = true;
-                        }
-                    });
+            this.credits = this.renderer
+              .text(creds.text + (this.mapCredits || ""), 0, 0)
+              .addClass("highcharts-credits")
+              .on("click", function () {
+                if (creds.href) {
+                  win.location.href = creds.href;
                 }
-                LineSeries.prototype.remove.apply(series, arguments);
+              })
+              .attr({
+                align: creds.position.align,
+                zIndex: 8,
+              });
+            if (!chart.styledMode) {
+              this.credits.css(creds.style);
+            }
+            this.credits.add().align(creds.position);
+            // Dynamically update
+            this.credits.update = function (options) {
+              chart.credits = chart.credits.destroy();
+              chart.addCredits(options);
+            };
+          }
+        };
+        /**
+         * Handle scaling, #11329 - when there is scaling/transform on the container
+         * or on a parent element, we need to take this into account. We calculate
+         * the scaling once here and it is picked up where we need to use it
+         * (Pointer, Tooltip).
+         *
+         * @private
+         * @function Highcharts.Chart#updateContainerScaling
+         */
+        Chart.prototype.updateContainerScaling = function () {
+          var container = this.container;
+          // #13342 - tooltip was not visible in Chrome, when chart
+          // updates height.
+          if (
+            container.offsetWidth > 2 && // #13342
+            container.offsetHeight > 2 && // #13342
+            container.getBoundingClientRect
+          ) {
+            var bb = container.getBoundingClientRect(),
+              scaleX = bb.width / container.offsetWidth,
+              scaleY = bb.height / container.offsetHeight;
+            if (scaleX !== 1 || scaleY !== 1) {
+              this.containerScaling = { scaleX: scaleX, scaleY: scaleY };
+            } else {
+              delete this.containerScaling;
+            }
+          }
+        };
+        /**
+         * Remove the chart and purge memory. This method is called internally
+         * before adding a second chart into the same container, as well as on
+         * window unload to prevent leaks.
+         *
+         * @sample highcharts/members/chart-destroy/
+         *         Destroy the chart from a button
+         * @sample stock/members/chart-destroy/
+         *         Destroy with Highstock
+         *
+         * @function Highcharts.Chart#destroy
+         *
+         * @fires Highcharts.Chart#event:destroy
+         */
+        Chart.prototype.destroy = function () {
+          var chart = this,
+            axes = chart.axes,
+            series = chart.series,
+            container = chart.container,
+            i,
+            parentNode = container && container.parentNode;
+          // fire the chart.destoy event
+          fireEvent(chart, "destroy");
+          // Delete the chart from charts lookup array
+          if (chart.renderer.forExport) {
+            erase(charts, chart); // #6569
+          } else {
+            charts[chart.index] = void 0;
+          }
+          H.chartCount--;
+          chart.renderTo.removeAttribute("data-highcharts-chart");
+          // remove events
+          removeEvent(chart);
+          // ==== Destroy collections:
+          // Destroy axes
+          i = axes.length;
+          while (i--) {
+            axes[i] = axes[i].destroy();
+          }
+          // Destroy scroller & scroller series before destroying base series
+          if (this.scroller && this.scroller.destroy) {
+            this.scroller.destroy();
+          }
+          // Destroy each series
+          i = series.length;
+          while (i--) {
+            series[i] = series[i].destroy();
+          }
+          // ==== Destroy chart properties:
+          [
+            "title",
+            "subtitle",
+            "chartBackground",
+            "plotBackground",
+            "plotBGImage",
+            "plotBorder",
+            "seriesGroup",
+            "clipRect",
+            "credits",
+            "pointer",
+            "rangeSelector",
+            "legend",
+            "resetZoomButton",
+            "tooltip",
+            "renderer",
+          ].forEach(function (name) {
+            var prop = chart[name];
+            if (prop && prop.destroy) {
+              chart[name] = prop.destroy();
+            }
+          });
+          // Remove container and all SVG, check container as it can break in IE
+          // when destroyed before finished loading
+          if (container) {
+            container.innerHTML = "";
+            removeEvent(container);
+            if (parentNode) {
+              discardElement(container);
+            }
+          }
+          // clean it all up
+          objectEach(chart, function (val, key) {
+            delete chart[key];
+          });
+        };
+        /**
+         * Prepare for first rendering after all data are loaded.
+         *
+         * @private
+         * @function Highcharts.Chart#firstRender
+         * @fires Highcharts.Chart#event:beforeRender
+         */
+        Chart.prototype.firstRender = function () {
+          var chart = this,
+            options = chart.options;
+          // Hook for oldIE to check whether the chart is ready to render
+          if (chart.isReadyToRender && !chart.isReadyToRender()) {
+            return;
+          }
+          // Create the container
+          chart.getContainer();
+          chart.resetMargins();
+          chart.setChartSize();
+          // Set the common chart properties (mainly invert) from the given series
+          chart.propFromSeries();
+          // get axes
+          chart.getAxes();
+          // Initialize the series
+          (isArray(options.series) ? options.series : []).forEach(
+            // #9680
+            function (serieOptions) {
+              chart.initSeries(serieOptions);
+            }
+          );
+          chart.linkSeries();
+          chart.setSeriesData();
+          // Run an event after axes and series are initialized, but before
+          // render. At this stage, the series data is indexed and cached in the
+          // xData and yData arrays, so we can access those before rendering. Used
+          // in Highstock.
+          fireEvent(chart, "beforeRender");
+          // depends on inverted and on margins being set
+          if (Pointer) {
+            if (!H.hasTouch && (win.PointerEvent || win.MSPointerEvent)) {
+              chart.pointer = new MSPointer(chart, options);
+            } else {
+              /**
+               * The Pointer that keeps track of mouse and touch interaction.
+               *
+               * @memberof Highcharts.Chart
+               * @name pointer
+               * @type {Highcharts.Pointer}
+               * @instance
+               */
+              chart.pointer = new Pointer(chart, options);
+            }
+          }
+          chart.render();
+          // Fire the load event if there are no external images
+          if (!chart.renderer.imgCount && !chart.hasLoaded) {
+            chart.onload();
+          }
+          // If the chart was rendered outside the top container, put it back in
+          // (#3679)
+          chart.temporaryDisplay(true);
+        };
+        /**
+         * Internal function that runs on chart load, async if any images are loaded
+         * in the chart. Runs the callbacks and triggers the `load` and `render`
+         * events.
+         *
+         * @private
+         * @function Highcharts.Chart#onload
+         * @fires Highcharts.Chart#event:load
+         * @fires Highcharts.Chart#event:render
+         */
+        Chart.prototype.onload = function () {
+          // Run callbacks, first the ones registered by modules, then user's one
+          this.callbacks.concat([this.callback]).forEach(function (fn) {
+            // Chart destroyed in its own callback (#3600)
+            if (fn && typeof this.index !== "undefined") {
+              fn.apply(this, [this]);
+            }
+          }, this);
+          fireEvent(this, "load");
+          fireEvent(this, "render");
+          // Set up auto resize, check for not destroyed (#6068)
+          if (defined(this.index)) {
+            this.setReflow(this.options.chart.reflow);
+          }
+          // Don't run again
+          this.hasLoaded = true;
+        };
+        return Chart;
+      })();
+      // Hook for adding callbacks in modules
+      Chart.prototype.callbacks = [];
+      /**
+       * Factory function for basic charts.
+       *
+       * @example
+       * // Render a chart in to div#container
+       * var chart = Highcharts.chart('container', {
+       *     title: {
+       *         text: 'My chart'
+       *     },
+       *     series: [{
+       *         data: [1, 3, 2, 4]
+       *     }]
+       * });
+       *
+       * @function Highcharts.chart
+       *
+       * @param {string|Highcharts.HTMLDOMElement} [renderTo]
+       *        The DOM element to render to, or its id.
+       *
+       * @param {Highcharts.Options} options
+       *        The chart options structure.
+       *
+       * @param {Highcharts.ChartCallbackFunction} [callback]
+       *        Function to run when the chart has loaded and and all external images
+       *        are loaded. Defining a
+       *        [chart.events.load](https://api.highcharts.com/highcharts/chart.events.load)
+       *        handler is equivalent.
+       *
+       * @return {Highcharts.Chart}
+       *         Returns the Chart object.
+       */
+      function chart(a, b, c) {
+        return new Chart(a, b, c);
+      }
+      H.chart = chart;
+      H.Chart = Chart;
+
+      return Chart;
+    }
+  );
+  _registerModule(
+    _modules,
+    "Extensions/ScrollablePlotArea.js",
+    [
+      _modules["Core/Animation/AnimationUtilities.js"],
+      _modules["Core/Chart/Chart.js"],
+      _modules["Core/Globals.js"],
+      _modules["Core/Utilities.js"],
+    ],
+    function (A, Chart, H, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       *  Highcharts feature to make the Y axis stay fixed when scrolling the chart
+       *  horizontally on mobile devices. Supports left and right side axes.
+       */
+      /*
+        WIP on vertical scrollable plot area (#9378). To do:
+        - Bottom axis positioning
+        - Test with Gantt
+        - Look for size optimizing the code
+        - API and demos
+         */
+      var stop = A.stop;
+      var addEvent = U.addEvent,
+        createElement = U.createElement,
+        pick = U.pick;
+      /**
+       * Options for a scrollable plot area. This feature provides a minimum size for
+       * the plot area of the chart. If the size gets smaller than this, typically
+       * on mobile devices, a native browser scrollbar is presented. This scrollbar
+       * provides smooth scrolling for the contents of the plot area, whereas the
+       * title, legend and unaffected axes are fixed.
+       *
+       * Since v7.1.2, a scrollable plot area can be defined for either horizontal or
+       * vertical scrolling, depending on whether the `minWidth` or `minHeight`
+       * option is set.
+       *
+       * @sample highcharts/chart/scrollable-plotarea
+       *         Scrollable plot area
+       * @sample highcharts/chart/scrollable-plotarea-vertical
+       *         Vertically scrollable plot area
+       * @sample {gantt} highcharts/chart/scrollable-plotarea-vertical
+       *         Gantt chart with vertically scrollable plot area
+       *
+       * @since     6.1.0
+       * @product   highcharts gantt
+       * @apioption chart.scrollablePlotArea
+       */
+      /**
+       * The minimum height for the plot area. If it gets smaller than this, the plot
+       * area will become scrollable.
+       *
+       * @type      {number}
+       * @apioption chart.scrollablePlotArea.minHeight
+       */
+      /**
+       * The minimum width for the plot area. If it gets smaller than this, the plot
+       * area will become scrollable.
+       *
+       * @type      {number}
+       * @apioption chart.scrollablePlotArea.minWidth
+       */
+      /**
+       * The initial scrolling position of the scrollable plot area. Ranges from 0 to
+       * 1, where 0 aligns the plot area to the left and 1 aligns it to the right.
+       * Typically we would use 1 if the chart has right aligned Y axes.
+       *
+       * @type      {number}
+       * @apioption chart.scrollablePlotArea.scrollPositionX
+       */
+      /**
+       * The initial scrolling position of the scrollable plot area. Ranges from 0 to
+       * 1, where 0 aligns the plot area to the top and 1 aligns it to the bottom.
+       *
+       * @type      {number}
+       * @apioption chart.scrollablePlotArea.scrollPositionY
+       */
+      /**
+       * The opacity of mask applied on one of the sides of the plot
+       * area.
+       *
+       * @sample {highcharts} highcharts/chart/scrollable-plotarea-opacity
+       *         Disabled opacity for the mask
+       *
+       * @type        {number}
+       * @default     0.85
+       * @since       7.1.1
+       * @apioption   chart.scrollablePlotArea.opacity
+       */
+      (""); // detach API doclets
+      /* eslint-disable no-invalid-this, valid-jsdoc */
+      addEvent(Chart, "afterSetChartSize", function (e) {
+        var scrollablePlotArea = this.options.chart.scrollablePlotArea,
+          scrollableMinWidth =
+            scrollablePlotArea && scrollablePlotArea.minWidth,
+          scrollableMinHeight =
+            scrollablePlotArea && scrollablePlotArea.minHeight,
+          scrollablePixelsX,
+          scrollablePixelsY,
+          corrections;
+        if (!this.renderer.forExport) {
+          // The amount of pixels to scroll, the difference between chart
+          // width and scrollable width
+          if (scrollableMinWidth) {
+            this.scrollablePixelsX = scrollablePixelsX = Math.max(
+              0,
+              scrollableMinWidth - this.chartWidth
+            );
+            if (scrollablePixelsX) {
+              this.plotWidth += scrollablePixelsX;
+              if (this.inverted) {
+                this.clipBox.height += scrollablePixelsX;
+                this.plotBox.height += scrollablePixelsX;
+              } else {
+                this.clipBox.width += scrollablePixelsX;
+                this.plotBox.width += scrollablePixelsX;
+              }
+              corrections = {
+                // Corrections for right side
+                1: { name: "right", value: scrollablePixelsX },
+              };
+            }
+            // Currently we can only do either X or Y
+          } else if (scrollableMinHeight) {
+            this.scrollablePixelsY = scrollablePixelsY = Math.max(
+              0,
+              scrollableMinHeight - this.chartHeight
+            );
+            if (scrollablePixelsY) {
+              this.plotHeight += scrollablePixelsY;
+              if (this.inverted) {
+                this.clipBox.width += scrollablePixelsY;
+                this.plotBox.width += scrollablePixelsY;
+              } else {
+                this.clipBox.height += scrollablePixelsY;
+                this.plotBox.height += scrollablePixelsY;
+              }
+              corrections = {
+                2: { name: "bottom", value: scrollablePixelsY },
+              };
+            }
+          }
+          if (corrections && !e.skipAxes) {
+            this.axes.forEach(function (axis) {
+              // For right and bottom axes, only fix the plot line length
+              if (corrections[axis.side]) {
+                // Get the plot lines right in getPlotLinePath,
+                // temporarily set it to the adjusted plot width.
+                axis.getPlotLinePath = function () {
+                  var marginName = corrections[axis.side].name,
+                    correctionValue = corrections[axis.side].value,
+                    // axis.right or axis.bottom
+                    margin = this[marginName],
+                    path;
+                  // Temporarily adjust
+                  this[marginName] = margin - correctionValue;
+                  path = H.Axis.prototype.getPlotLinePath.apply(
+                    this,
+                    arguments
+                  );
+                  // Reset
+                  this[marginName] = margin;
+                  return path;
+                };
+              } else {
+                // Apply the corrected plotWidth
+                axis.setAxisSize();
+                axis.setAxisTranslation();
+              }
+            });
+          }
+        }
+      });
+      addEvent(Chart, "render", function () {
+        if (this.scrollablePixelsX || this.scrollablePixelsY) {
+          if (this.setUpScrolling) {
+            this.setUpScrolling();
+          }
+          this.applyFixed();
+        } else if (this.fixedDiv) {
+          // Has been in scrollable mode
+          this.applyFixed();
+        }
+      });
+      /**
+       * @private
+       * @function Highcharts.Chart#setUpScrolling
+       * @return {void}
+       */
+      Chart.prototype.setUpScrolling = function () {
+        var _this = this;
+        var attribs = {
+          WebkitOverflowScrolling: "touch",
+          overflowX: "hidden",
+          overflowY: "hidden",
+        };
+        if (this.scrollablePixelsX) {
+          attribs.overflowX = "auto";
+        }
+        if (this.scrollablePixelsY) {
+          attribs.overflowY = "auto";
+        }
+        // Insert a container with position relative
+        // that scrolling and fixed container renders to (#10555)
+        this.scrollingParent = createElement(
+          "div",
+          {
+            className: "highcharts-scrolling-parent",
+          },
+          {
+            position: "relative",
+          },
+          this.renderTo
+        );
+        // Add the necessary divs to provide scrolling
+        this.scrollingContainer = createElement(
+          "div",
+          {
+            className: "highcharts-scrolling",
+          },
+          attribs,
+          this.scrollingParent
+        );
+        // On scroll, reset the chart position because it applies to the scrolled
+        // container
+        addEvent(this.scrollingContainer, "scroll", function () {
+          if (_this.pointer) {
+            delete _this.pointer.chartPosition;
+          }
+        });
+        this.innerContainer = createElement(
+          "div",
+          {
+            className: "highcharts-inner-container",
+          },
+          null,
+          this.scrollingContainer
+        );
+        // Now move the container inside
+        this.innerContainer.appendChild(this.container);
+        // Don't run again
+        this.setUpScrolling = null;
+      };
+      /**
+       * These elements are moved over to the fixed renderer and stay fixed when the
+       * user scrolls the chart
+       * @private
+       */
+      Chart.prototype.moveFixedElements = function () {
+        var container = this.container,
+          fixedRenderer = this.fixedRenderer,
+          fixedSelectors = [
+            ".highcharts-contextbutton",
+            ".highcharts-credits",
+            ".highcharts-legend",
+            ".highcharts-legend-checkbox",
+            ".highcharts-navigator-series",
+            ".highcharts-navigator-xaxis",
+            ".highcharts-navigator-yaxis",
+            ".highcharts-navigator",
+            ".highcharts-reset-zoom",
+            ".highcharts-scrollbar",
+            ".highcharts-subtitle",
+            ".highcharts-title",
+          ],
+          axisClass;
+        if (this.scrollablePixelsX && !this.inverted) {
+          axisClass = ".highcharts-yaxis";
+        } else if (this.scrollablePixelsX && this.inverted) {
+          axisClass = ".highcharts-xaxis";
+        } else if (this.scrollablePixelsY && !this.inverted) {
+          axisClass = ".highcharts-xaxis";
+        } else if (this.scrollablePixelsY && this.inverted) {
+          axisClass = ".highcharts-yaxis";
+        }
+        fixedSelectors.push(axisClass, axisClass + "-labels");
+        fixedSelectors.forEach(function (className) {
+          [].forEach.call(
+            container.querySelectorAll(className),
+            function (elem) {
+              (elem.namespaceURI === fixedRenderer.SVG_NS
+                ? fixedRenderer.box
+                : fixedRenderer.box.parentNode
+              ).appendChild(elem);
+              elem.style.pointerEvents = "auto";
             }
+          );
+        });
+      };
+      /**
+       * @private
+       * @function Highcharts.Chart#applyFixed
+       * @return {void}
+       */
+      Chart.prototype.applyFixed = function () {
+        var _a, _b;
+        var fixedRenderer,
+          scrollableWidth,
+          scrollableHeight,
+          firstTime = !this.fixedDiv,
+          scrollableOptions = this.options.chart.scrollablePlotArea;
+        // First render
+        if (firstTime) {
+          this.fixedDiv = createElement(
+            "div",
+            {
+              className: "highcharts-fixed",
+            },
+            {
+              position: "absolute",
+              overflow: "hidden",
+              pointerEvents: "none",
+              zIndex: 2,
+              top: 0,
+            },
+            null,
+            true
+          );
+          (_a = this.scrollingContainer) === null || _a === void 0
+            ? void 0
+            : _a.parentNode.insertBefore(
+                this.fixedDiv,
+                this.scrollingContainer
+              );
+          this.renderTo.style.overflow = "visible";
+          this.fixedRenderer = fixedRenderer = new H.Renderer(
+            this.fixedDiv,
+            this.chartWidth,
+            this.chartHeight,
+            (_b = this.options.chart) === null || _b === void 0
+              ? void 0
+              : _b.style
+          );
+          // Mask
+          this.scrollableMask = fixedRenderer
+            .path()
+            .attr({
+              fill: this.options.chart.backgroundColor || "#fff",
+              "fill-opacity": pick(scrollableOptions.opacity, 0.85),
+              zIndex: -1,
+            })
+            .addClass("highcharts-scrollable-mask")
+            .add();
+          this.moveFixedElements();
+          addEvent(this, "afterShowResetZoom", this.moveFixedElements);
+          addEvent(this, "afterLayOutTitles", this.moveFixedElements);
+        } else {
+          // Set the size of the fixed renderer to the visible width
+          this.fixedRenderer.setSize(this.chartWidth, this.chartHeight);
+        }
+        // Increase the size of the scrollable renderer and background
+        scrollableWidth = this.chartWidth + (this.scrollablePixelsX || 0);
+        scrollableHeight = this.chartHeight + (this.scrollablePixelsY || 0);
+        stop(this.container);
+        this.container.style.width = scrollableWidth + "px";
+        this.container.style.height = scrollableHeight + "px";
+        this.renderer.boxWrapper.attr({
+          width: scrollableWidth,
+          height: scrollableHeight,
+          viewBox: [0, 0, scrollableWidth, scrollableHeight].join(" "),
         });
-        /* eslint-enable valid-jsdoc */
-        /**
-         * A `column` series. If the [type](#series.column.type) option is
-         * not specified, it is inherited from [chart.type](#chart.type).
+        this.chartBackground.attr({
+          width: scrollableWidth,
+          height: scrollableHeight,
+        });
+        this.scrollingContainer.style.height = this.chartHeight + "px";
+        // Set scroll position
+        if (firstTime) {
+          if (scrollableOptions.scrollPositionX) {
+            this.scrollingContainer.scrollLeft =
+              this.scrollablePixelsX * scrollableOptions.scrollPositionX;
+          }
+          if (scrollableOptions.scrollPositionY) {
+            this.scrollingContainer.scrollTop =
+              this.scrollablePixelsY * scrollableOptions.scrollPositionY;
+          }
+        }
+        // Mask behind the left and right side
+        var axisOffset = this.axisOffset,
+          maskTop = this.plotTop - axisOffset[0] - 1,
+          maskLeft = this.plotLeft - axisOffset[3] - 1,
+          maskBottom = this.plotTop + this.plotHeight + axisOffset[2] + 1,
+          maskRight = this.plotLeft + this.plotWidth + axisOffset[1] + 1,
+          maskPlotRight =
+            this.plotLeft + this.plotWidth - (this.scrollablePixelsX || 0),
+          maskPlotBottom =
+            this.plotTop + this.plotHeight - (this.scrollablePixelsY || 0),
+          d;
+        if (this.scrollablePixelsX) {
+          d = [
+            // Left side
+            ["M", 0, maskTop],
+            ["L", this.plotLeft - 1, maskTop],
+            ["L", this.plotLeft - 1, maskBottom],
+            ["L", 0, maskBottom],
+            ["Z"],
+            // Right side
+            ["M", maskPlotRight, maskTop],
+            ["L", this.chartWidth, maskTop],
+            ["L", this.chartWidth, maskBottom],
+            ["L", maskPlotRight, maskBottom],
+            ["Z"],
+          ];
+        } else if (this.scrollablePixelsY) {
+          d = [
+            // Top side
+            ["M", maskLeft, 0],
+            ["L", maskLeft, this.plotTop - 1],
+            ["L", maskRight, this.plotTop - 1],
+            ["L", maskRight, 0],
+            ["Z"],
+            // Bottom side
+            ["M", maskLeft, maskPlotBottom],
+            ["L", maskLeft, this.chartHeight],
+            ["L", maskRight, this.chartHeight],
+            ["L", maskRight, maskPlotBottom],
+            ["Z"],
+          ];
+        } else {
+          d = [["M", 0, 0]];
+        }
+        if (this.redrawTrigger !== "adjustHeight") {
+          this.scrollableMask.attr({ d: d });
+        }
+      };
+    }
+  );
+  _registerModule(
+    _modules,
+    "Core/Axis/StackingAxis.js",
+    [
+      _modules["Core/Animation/AnimationUtilities.js"],
+      _modules["Core/Utilities.js"],
+    ],
+    function (A, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      var getDeferredAnimation = A.getDeferredAnimation;
+      var addEvent = U.addEvent,
+        destroyObjectProperties = U.destroyObjectProperties,
+        fireEvent = U.fireEvent,
+        objectEach = U.objectEach,
+        pick = U.pick;
+      /* eslint-disable valid-jsdoc */
+      /**
+       * Adds stacking support to axes.
+       * @private
+       * @class
+       */
+      var StackingAxisAdditions = /** @class */ (function () {
+        /* *
          *
-         * @extends   series,plotOptions.column
-         * @excluding connectNulls, dataParser, dataURL, gapSize, gapUnit, linecap,
-         *            lineWidth, marker, connectEnds, step
-         * @product   highcharts highstock
-         * @apioption series.column
-         */
-        /**
-         * An array of data points for the series. For the `column` series type,
-         * points can be given in the following ways:
-         *
-         * 1. An array of numerical values. In this case, the numerical values will be
-         *    interpreted as `y` options. The `x` values will be automatically
-         *    calculated, either starting at 0 and incremented by 1, or from
-         *    `pointStart` and `pointInterval` given in the series options. If the axis
-         *    has categories, these will be used. Example:
-         *    ```js
-         *    data: [0, 5, 3, 5]
-         *    ```
-         *
-         * 2. An array of arrays with 2 values. In this case, the values correspond to
-         *    `x,y`. If the first value is a string, it is applied as the name of the
-         *    point, and the `x` value is inferred.
-         *    ```js
-         *    data: [
-         *        [0, 6],
-         *        [1, 2],
-         *        [2, 6]
-         *    ]
-         *    ```
-         *
-         * 3. An array of objects with named values. The following snippet shows only a
-         *    few settings, see the complete options set below. If the total number of
-         *    data points exceeds the series'
-         *    [turboThreshold](#series.column.turboThreshold), this option is not
-         *    available.
-         *    ```js
-         *    data: [{
-         *        x: 1,
-         *        y: 9,
-         *        name: "Point2",
-         *        color: "#00FF00"
-         *    }, {
-         *        x: 1,
-         *        y: 6,
-         *        name: "Point1",
-         *        color: "#FF00FF"
-         *    }]
-         *    ```
-         *
-         * @sample {highcharts} highcharts/chart/reflow-true/
-         *         Numerical values
-         * @sample {highcharts} highcharts/series/data-array-of-arrays/
-         *         Arrays of numeric x and y
-         * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
-         *         Arrays of datetime x and y
-         * @sample {highcharts} highcharts/series/data-array-of-name-value/
-         *         Arrays of point.name and y
-         * @sample {highcharts} highcharts/series/data-array-of-objects/
-         *         Config objects
-         *
-         * @type      {Array<number|Array<(number|string),(number|null)>|null|*>}
-         * @extends   series.line.data
-         * @excluding marker
-         * @product   highcharts highstock
-         * @apioption series.column.data
-         */
-        /**
-         * The color of the border surrounding the column or bar.
+         *  Constructors
          *
-         * In styled mode, the border stroke can be set with the `.highcharts-point`
-         * rule.
+         * */
+        function StackingAxisAdditions(axis) {
+          this.oldStacks = {};
+          this.stacks = {};
+          this.stacksTouched = 0;
+          this.axis = axis;
+        }
+        /* *
          *
-         * @sample {highcharts} highcharts/plotoptions/column-bordercolor/
-         *         Dark gray border
+         *  Functions
          *
-         * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-         * @product   highcharts highstock
-         * @apioption series.column.data.borderColor
+         * */
+        /**
+         * Build the stacks from top down
+         * @private
          */
+        StackingAxisAdditions.prototype.buildStacks = function () {
+          var stacking = this;
+          var axis = stacking.axis;
+          var axisSeries = axis.series;
+          var reversedStacks = pick(axis.options.reversedStacks, true);
+          var len = axisSeries.length;
+          var actualSeries, i;
+          if (!axis.isXAxis) {
+            stacking.usePercentage = false;
+            i = len;
+            while (i--) {
+              actualSeries = axisSeries[reversedStacks ? i : len - i - 1];
+              actualSeries.setStackedPoints();
+              actualSeries.setGroupedPoints();
+            }
+            // Loop up again to compute percent and stream stack
+            for (i = 0; i < len; i++) {
+              axisSeries[i].modifyStacks();
+            }
+            fireEvent(axis, "afterBuildStacks");
+          }
+        };
         /**
-         * The width of the border surrounding the column or bar.
-         *
-         * In styled mode, the stroke width can be set with the `.highcharts-point`
-         * rule.
-         *
-         * @sample {highcharts} highcharts/plotoptions/column-borderwidth/
-         *         2px black border
-         *
-         * @type      {number}
-         * @product   highcharts highstock
-         * @apioption series.column.data.borderWidth
+         * @private
          */
+        StackingAxisAdditions.prototype.cleanStacks = function () {
+          var stacking = this;
+          var axis = stacking.axis;
+          var stacks;
+          if (!axis.isXAxis) {
+            if (stacking.oldStacks) {
+              stacks = stacking.stacks = stacking.oldStacks;
+            }
+            // reset stacks
+            objectEach(stacks, function (type) {
+              objectEach(type, function (stack) {
+                stack.cumulative = stack.total;
+              });
+            });
+          }
+        };
         /**
-         * A name for the dash style to use for the column or bar. Overrides
-         * dashStyle on the series.
-         *
-         * In styled mode, the stroke dash-array can be set with the same classes as
-         * listed under [data.color](#series.column.data.color).
-         *
-         * @see [series.pointWidth](#plotOptions.column.dashStyle)
-         *
-         * @type      {Highcharts.DashStyleValue}
-         * @apioption series.column.data.dashStyle
+         * Set all the stacks to initial states and destroy unused ones.
+         * @private
          */
+        StackingAxisAdditions.prototype.resetStacks = function () {
+          var stacking = this;
+          var axis = stacking.axis;
+          var stacks = stacking.stacks;
+          if (!axis.isXAxis) {
+            objectEach(stacks, function (type) {
+              objectEach(type, function (stack, key) {
+                // Clean up memory after point deletion (#1044, #4320)
+                if (stack.touched < stacking.stacksTouched) {
+                  stack.destroy();
+                  delete type[key];
+                  // Reset stacks
+                } else {
+                  stack.total = null;
+                  stack.cumulative = null;
+                }
+              });
+            });
+          }
+        };
         /**
-         * A pixel value specifying a fixed width for the column or bar. Overrides
-         * pointWidth on the series. The width effects the dimension that is not based
-         * on the point value.
+         * @private
+         */
+        StackingAxisAdditions.prototype.renderStackTotals = function () {
+          var stacking = this;
+          var axis = stacking.axis;
+          var chart = axis.chart;
+          var renderer = chart.renderer;
+          var stacks = stacking.stacks;
+          var stackLabelsAnim = axis.options.stackLabels.animation;
+          var animationConfig = getDeferredAnimation(chart, stackLabelsAnim);
+          var stackTotalGroup = (stacking.stackTotalGroup =
+            stacking.stackTotalGroup ||
+            renderer
+              .g("stack-labels")
+              .attr({
+                visibility: "visible",
+                zIndex: 6,
+                opacity: 0,
+              })
+              .add());
+          // plotLeft/Top will change when y axis gets wider so we need to
+          // translate the stackTotalGroup at every render call. See bug #506
+          // and #516
+          stackTotalGroup.translate(chart.plotLeft, chart.plotTop);
+          // Render each stack total
+          objectEach(stacks, function (type) {
+            objectEach(type, function (stack) {
+              stack.render(stackTotalGroup);
+            });
+          });
+          stackTotalGroup.animate(
+            {
+              opacity: 1,
+            },
+            animationConfig
+          );
+        };
+        return StackingAxisAdditions;
+      })();
+      /**
+       * Axis with stacking support.
+       * @private
+       * @class
+       */
+      var StackingAxis = /** @class */ (function () {
+        function StackingAxis() {}
+        /* *
          *
-         * @see [series.pointWidth](#plotOptions.column.pointWidth)
+         *  Static Functions
          *
-         * @type      {number}
-         * @apioption series.column.data.pointWidth
+         * */
+        /**
+         * Extends axis with stacking support.
+         * @private
          */
+        StackingAxis.compose = function (AxisClass) {
+          var axisProto = AxisClass.prototype;
+          addEvent(AxisClass, "init", StackingAxis.onInit);
+          addEvent(AxisClass, "destroy", StackingAxis.onDestroy);
+        };
         /**
-         * @excluding halo, lineWidth, lineWidthPlus, marker
-         * @product   highcharts highstock
-         * @apioption series.column.states.hover
+         * @private
          */
+        StackingAxis.onDestroy = function () {
+          var stacking = this.stacking;
+          if (!stacking) {
+            return;
+          }
+          var stacks = stacking.stacks;
+          // Destroy each stack total
+          objectEach(stacks, function (stack, stackKey) {
+            destroyObjectProperties(stack);
+            stacks[stackKey] = null;
+          });
+          if (stacking && stacking.stackTotalGroup) {
+            stacking.stackTotalGroup.destroy();
+          }
+        };
         /**
-         * @excluding halo, lineWidth, lineWidthPlus, marker
-         * @product   highcharts highstock
-         * @apioption series.column.states.select
+         * @private
          */
-        ''; // includes above doclets in transpilat
+        StackingAxis.onInit = function () {
+          var axis = this;
+          if (!axis.stacking) {
+            axis.stacking = new StackingAxisAdditions(axis);
+          }
+        };
+        return StackingAxis;
+      })();
 
-        return ColumnSeries;
-    });
-    _registerModule(_modules, 'Series/BarSeries.js', [_modules['Core/Series/Series.js']], function (Series) {
-        /* *
-         *
-         *  (c) 2010-2020 Torstein Honsi
+      return StackingAxis;
+    }
+  );
+  _registerModule(
+    _modules,
+    "Mixins/LegendSymbol.js",
+    [_modules["Core/Globals.js"], _modules["Core/Utilities.js"]],
+    function (H, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      var merge = U.merge,
+        pick = U.pick;
+      /* eslint-disable valid-jsdoc */
+      /**
+       * Legend symbol mixin.
+       *
+       * @private
+       * @mixin Highcharts.LegendSymbolMixin
+       */
+      var LegendSymbolMixin = (H.LegendSymbolMixin = {
+        /**
+         * Get the series' symbol in the legend
          *
-         *  License: www.highcharts.com/license
+         * @private
+         * @function Highcharts.LegendSymbolMixin.drawRectangle
          *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+         * @param {Highcharts.Legend} legend
+         * The legend object
          *
-         * */
-        /**
-         * Bar series type.
+         * @param {Highcharts.Point|Highcharts.Series} item
+         * The series (this) or point
+         */
+        drawRectangle: function (legend, item) {
+          var options = legend.options,
+            symbolHeight = legend.symbolHeight,
+            square = options.squareSymbol,
+            symbolWidth = square ? symbolHeight : legend.symbolWidth;
+          item.legendSymbol = this.chart.renderer
+            .rect(
+              square ? (legend.symbolWidth - symbolHeight) / 2 : 0,
+              legend.baseline - symbolHeight + 1, // #3988
+              symbolWidth,
+              symbolHeight,
+              pick(legend.options.symbolRadius, symbolHeight / 2)
+            )
+            .addClass("highcharts-point")
+            .attr({
+              zIndex: 3,
+            })
+            .add(item.legendGroup);
+        },
+        /**
+         * Get the series' symbol in the legend. This method should be overridable
+         * to create custom symbols through
+         * Highcharts.seriesTypes[type].prototype.drawLegendSymbols.
          *
          * @private
-         * @class
-         * @name Highcharts.seriesTypes.bar
+         * @function Highcharts.LegendSymbolMixin.drawLineMarker
          *
-         * @augments Highcharts.Series
+         * @param {Highcharts.Legend} legend
+         * The legend object.
          */
-        Series.seriesType('bar', 'column', 
+        drawLineMarker: function (legend) {
+          var options = this.options,
+            markerOptions = options.marker,
+            radius,
+            legendSymbol,
+            symbolWidth = legend.symbolWidth,
+            symbolHeight = legend.symbolHeight,
+            generalRadius = symbolHeight / 2,
+            renderer = this.chart.renderer,
+            legendItemGroup = this.legendGroup,
+            verticalCenter =
+              legend.baseline - Math.round(legend.fontMetrics.b * 0.3),
+            attr = {};
+          // Draw the line
+          if (!this.chart.styledMode) {
+            attr = {
+              "stroke-width": options.lineWidth || 0,
+            };
+            if (options.dashStyle) {
+              attr.dashstyle = options.dashStyle;
+            }
+          }
+          this.legendLine = renderer
+            .path([
+              ["M", 0, verticalCenter],
+              ["L", symbolWidth, verticalCenter],
+            ])
+            .addClass("highcharts-graph")
+            .attr(attr)
+            .add(legendItemGroup);
+          // Draw the marker
+          if (markerOptions && markerOptions.enabled !== false && symbolWidth) {
+            // Do not allow the marker to be larger than the symbolHeight
+            radius = Math.min(
+              pick(markerOptions.radius, generalRadius),
+              generalRadius
+            );
+            // Restrict symbol markers size
+            if (this.symbol.indexOf("url") === 0) {
+              markerOptions = merge(markerOptions, {
+                width: symbolHeight,
+                height: symbolHeight,
+              });
+              radius = 0;
+            }
+            this.legendSymbol = legendSymbol = renderer
+              .symbol(
+                this.symbol,
+                symbolWidth / 2 - radius,
+                verticalCenter - radius,
+                2 * radius,
+                2 * radius,
+                markerOptions
+              )
+              .addClass("highcharts-point")
+              .add(legendItemGroup);
+            legendSymbol.isMarker = true;
+          }
+        },
+      });
+
+      return LegendSymbolMixin;
+    }
+  );
+  _registerModule(
+    _modules,
+    "Core/Series/CartesianSeries.js",
+    [
+      _modules["Core/Animation/AnimationUtilities.js"],
+      _modules["Core/Series/Series.js"],
+      _modules["Core/Globals.js"],
+      _modules["Mixins/LegendSymbol.js"],
+      _modules["Core/Options.js"],
+      _modules["Core/Series/Point.js"],
+      _modules["Core/Renderer/SVG/SVGElement.js"],
+      _modules["Core/Utilities.js"],
+    ],
+    function (A, BaseSeries, H, LegendSymbolMixin, O, Point, SVGElement, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      var animObject = A.animObject;
+      var defaultOptions = O.defaultOptions;
+      var addEvent = U.addEvent,
+        arrayMax = U.arrayMax,
+        arrayMin = U.arrayMin,
+        clamp = U.clamp,
+        correctFloat = U.correctFloat,
+        defined = U.defined,
+        erase = U.erase,
+        error = U.error,
+        extend = U.extend,
+        find = U.find,
+        fireEvent = U.fireEvent,
+        getNestedProperty = U.getNestedProperty,
+        isArray = U.isArray,
+        isFunction = U.isFunction,
+        isNumber = U.isNumber,
+        isString = U.isString,
+        merge = U.merge,
+        objectEach = U.objectEach,
+        pick = U.pick,
+        removeEvent = U.removeEvent,
+        splat = U.splat,
+        syncTimeout = U.syncTimeout;
+      /**
+       * This is a placeholder type of the possible series options for
+       * [Highcharts](../highcharts/series), [Highstock](../highstock/series),
+       * [Highmaps](../highmaps/series), and [Gantt](../gantt/series).
+       *
+       * In TypeScript is this dynamically generated to reference all possible types
+       * of series options.
+       *
+       * @ignore-declaration
+       * @typedef {Highcharts.SeriesOptions|Highcharts.Dictionary<*>} Highcharts.SeriesOptionsType
+       */
+      /**
+       * Options for `dataSorting`.
+       *
+       * @interface Highcharts.DataSortingOptionsObject
+       * @since 8.0.0
+       */ /**
+       * Enable or disable data sorting for the series.
+       * @name Highcharts.DataSortingOptionsObject#enabled
+       * @type {boolean|undefined}
+       */ /**
+       * Whether to allow matching points by name in an update.
+       * @name Highcharts.DataSortingOptionsObject#matchByName
+       * @type {boolean|undefined}
+       */ /**
+       * Determines what data value should be used to sort by.
+       * @name Highcharts.DataSortingOptionsObject#sortKey
+       * @type {string|undefined}
+       */
+      /**
+       * Function callback when a series has been animated.
+       *
+       * @callback Highcharts.SeriesAfterAnimateCallbackFunction
+       *
+       * @param {Highcharts.Series} this
+       *        The series where the event occured.
+       *
+       * @param {Highcharts.SeriesAfterAnimateEventObject} event
+       *        Event arguments.
+       */
+      /**
+       * Event information regarding completed animation of a series.
+       *
+       * @interface Highcharts.SeriesAfterAnimateEventObject
+       */ /**
+       * Animated series.
+       * @name Highcharts.SeriesAfterAnimateEventObject#target
+       * @type {Highcharts.Series}
+       */ /**
+       * Event type.
+       * @name Highcharts.SeriesAfterAnimateEventObject#type
+       * @type {"afterAnimate"}
+       */
+      /**
+       * Function callback when the checkbox next to the series' name in the legend is
+       * clicked.
+       *
+       * @callback Highcharts.SeriesCheckboxClickCallbackFunction
+       *
+       * @param {Highcharts.Series} this
+       *        The series where the event occured.
+       *
+       * @param {Highcharts.SeriesCheckboxClickEventObject} event
+       *        Event arguments.
+       */
+      /**
+       * Event information regarding check of a series box.
+       *
+       * @interface Highcharts.SeriesCheckboxClickEventObject
+       */ /**
+       * Whether the box has been checked.
+       * @name Highcharts.SeriesCheckboxClickEventObject#checked
+       * @type {boolean}
+       */ /**
+       * Related series.
+       * @name Highcharts.SeriesCheckboxClickEventObject#item
+       * @type {Highcharts.Series}
+       */ /**
+       * Related series.
+       * @name Highcharts.SeriesCheckboxClickEventObject#target
+       * @type {Highcharts.Series}
+       */ /**
+       * Event type.
+       * @name Highcharts.SeriesCheckboxClickEventObject#type
+       * @type {"checkboxClick"}
+       */
+      /**
+       * Function callback when a series is clicked. Return false to cancel toogle
+       * actions.
+       *
+       * @callback Highcharts.SeriesClickCallbackFunction
+       *
+       * @param {Highcharts.Series} this
+       *        The series where the event occured.
+       *
+       * @param {Highcharts.SeriesClickEventObject} event
+       *        Event arguments.
+       */
+      /**
+       * Common information for a click event on a series.
+       *
+       * @interface Highcharts.SeriesClickEventObject
+       * @extends global.Event
+       */ /**
+       * Nearest point on the graph.
+       * @name Highcharts.SeriesClickEventObject#point
+       * @type {Highcharts.Point}
+       */
+      /**
+       * Gets fired when the series is hidden after chart generation time, either by
+       * clicking the legend item or by calling `.hide()`.
+       *
+       * @callback Highcharts.SeriesHideCallbackFunction
+       *
+       * @param {Highcharts.Series} this
+       *        The series where the event occured.
+       *
+       * @param {global.Event} event
+       *        The event that occured.
+       */
+      /**
+       * The SVG value used for the `stroke-linecap` and `stroke-linejoin` of a line
+       * graph.
+       *
+       * @typedef {"butt"|"round"|"square"|string} Highcharts.SeriesLinecapValue
+       */
+      /**
+       * Gets fired when the legend item belonging to the series is clicked. The
+       * default action is to toggle the visibility of the series. This can be
+       * prevented by returning `false` or calling `event.preventDefault()`.
+       *
+       * @callback Highcharts.SeriesLegendItemClickCallbackFunction
+       *
+       * @param {Highcharts.Series} this
+       *        The series where the event occured.
+       *
+       * @param {Highcharts.SeriesLegendItemClickEventObject} event
+       *        The event that occured.
+       */
+      /**
+       * Information about the event.
+       *
+       * @interface Highcharts.SeriesLegendItemClickEventObject
+       */ /**
+       * Related browser event.
+       * @name Highcharts.SeriesLegendItemClickEventObject#browserEvent
+       * @type {global.PointerEvent}
+       */ /**
+       * Prevent the default action of toggle the visibility of the series.
+       * @name Highcharts.SeriesLegendItemClickEventObject#preventDefault
+       * @type {Function}
+       */ /**
+       * Related series.
+       * @name Highcharts.SeriesCheckboxClickEventObject#target
+       * @type {Highcharts.Series}
+       */ /**
+       * Event type.
+       * @name Highcharts.SeriesCheckboxClickEventObject#type
+       * @type {"checkboxClick"}
+       */
+      /**
+       * Gets fired when the mouse leaves the graph.
+       *
+       * @callback Highcharts.SeriesMouseOutCallbackFunction
+       *
+       * @param {Highcharts.Series} this
+       *        Series where the event occured.
+       *
+       * @param {global.PointerEvent} event
+       *        Event that occured.
+       */
+      /**
+       * Gets fired when the mouse enters the graph.
+       *
+       * @callback Highcharts.SeriesMouseOverCallbackFunction
+       *
+       * @param {Highcharts.Series} this
+       *        Series where the event occured.
+       *
+       * @param {global.PointerEvent} event
+       *        Event that occured.
+       */
+      /**
+       * Translation and scale for the plot area of a series.
+       *
+       * @interface Highcharts.SeriesPlotBoxObject
+       */ /**
+       * @name Highcharts.SeriesPlotBoxObject#scaleX
+       * @type {number}
+       */ /**
+       * @name Highcharts.SeriesPlotBoxObject#scaleY
+       * @type {number}
+       */ /**
+       * @name Highcharts.SeriesPlotBoxObject#translateX
+       * @type {number}
+       */ /**
+       * @name Highcharts.SeriesPlotBoxObject#translateY
+       * @type {number}
+       */
+      /**
+       * Gets fired when the series is shown after chart generation time, either by
+       * clicking the legend item or by calling `.show()`.
+       *
+       * @callback Highcharts.SeriesShowCallbackFunction
+       *
+       * @param {Highcharts.Series} this
+       *        Series where the event occured.
+       *
+       * @param {global.Event} event
+       *        Event that occured.
+       */
+      /**
+       * Possible key values for the series state options.
+       *
+       * @typedef {"hover"|"inactive"|"normal"|"select"} Highcharts.SeriesStateValue
+       */
+      (""); // detach doclets above
+      var seriesTypes = BaseSeries.seriesTypes,
+        win = H.win;
+      /**
+       * This is the base series prototype that all other series types inherit from.
+       * A new series is initialized either through the
+       * [series](https://api.highcharts.com/highcharts/series)
+       * option structure, or after the chart is initialized, through
+       * {@link Highcharts.Chart#addSeries}.
+       *
+       * The object can be accessed in a number of ways. All series and point event
+       * handlers give a reference to the `series` object. The chart object has a
+       * {@link Highcharts.Chart#series|series} property that is a collection of all
+       * the chart's series. The point objects and axis objects also have the same
+       * reference.
+       *
+       * Another way to reference the series programmatically is by `id`. Add an id
+       * in the series configuration options, and get the series object by
+       * {@link Highcharts.Chart#get}.
+       *
+       * Configuration options for the series are given in three levels. Options for
+       * all series in a chart are given in the
+       * [plotOptions.series](https://api.highcharts.com/highcharts/plotOptions.series)
+       * object. Then options for all series of a specific type
+       * are given in the plotOptions of that type, for example `plotOptions.line`.
+       * Next, options for one single series are given in the series array, or as
+       * arguments to `chart.addSeries`.
+       *
+       * The data in the series is stored in various arrays.
+       *
+       * - First, `series.options.data` contains all the original config options for
+       *   each point whether added by options or methods like `series.addPoint`.
+       *
+       * - Next, `series.data` contains those values converted to points, but in case
+       *   the series data length exceeds the `cropThreshold`, or if the data is
+       *   grouped, `series.data` doesn't contain all the points. It only contains the
+       *   points that have been created on demand.
+       *
+       * - Then there's `series.points` that contains all currently visible point
+       *   objects. In case of cropping, the cropped-away points are not part of this
+       *   array. The `series.points` array starts at `series.cropStart` compared to
+       *   `series.data` and `series.options.data`. If however the series data is
+       *   grouped, these can't be correlated one to one.
+       *
+       * - `series.xData` and `series.processedXData` contain clean x values,
+       *   equivalent to `series.data` and `series.points`.
+       *
+       * - `series.yData` and `series.processedYData` contain clean y values,
+       *   equivalent to `series.data` and `series.points`.
+       *
+       * @class
+       * @name Highcharts.Series
+       *
+       * @param {Highcharts.Chart} chart
+       *        The chart instance.
+       *
+       * @param {Highcharts.SeriesOptionsType|object} options
+       *        The series options.
+       */ /**
+       * The line series is the base type and is therefor the series base prototype.
+       *
+       * @private
+       * @class
+       * @name Highcharts.seriesTypes.line
+       *
+       * @augments Highcharts.Series
+       */
+      var CartesianSeries = BaseSeries.seriesType(
+        "line",
         /**
-         * A bar series is a special type of column series where the columns are
-         * horizontal.
-         *
-         * @sample highcharts/demo/bar-basic/
-         *         Bar chart
+             * Series options for specific data and the data itself. In TypeScript you
+             * have to cast the series options to specific series types,
+            to get all
+             * possible options for a series.
+             *
+             * @example
+             * // TypeScript example
+             * Highcharts.chart('container', {
+             *     series: [{
+             *         color: '#06C',
+             *         data: [[0, 1],
+            [2, 3]]
+             *     } as Highcharts.SeriesLineOptions ]
+             * });
          *
-         * @extends   plotOptions.column
-         * @product   highcharts
-         * @apioption plotOptions.bar
-         */
-        /**
-         * @ignore
+         * @type      {Array<*>}
+         * @apioption series
          */
-        null, {
-            inverted: true
-        });
         /**
-         * A `bar` series. If the [type](#series.bar.type) option is not specified,
-         * it is inherited from [chart.type](#chart.type).
+         * An id for the series. This can be used after render time to get a pointer
+         * to the series object through `chart.get()`.
          *
-         * @extends   series,plotOptions.bar
-         * @excluding connectNulls, dashStyle, dataParser, dataURL, gapSize, gapUnit,
-         *            linecap, lineWidth, marker, connectEnds, step
-         * @product   highcharts
-         * @apioption series.bar
-         */
-        /**
-         * An array of data points for the series. For the `bar` series type,
-         * points can be given in the following ways:
-         *
-         * 1. An array of numerical values. In this case, the numerical values will be
-         *    interpreted as `y` options. The `x` values will be automatically
-         *    calculated, either starting at 0 and incremented by 1, or from
-         *    `pointStart` and `pointInterval` given in the series options. If the axis
-         *    has categories, these will be used. Example:
-         *    ```js
-         *    data: [0, 5, 3, 5]
-         *    ```
-         *
-         * 2. An array of arrays with 2 values. In this case, the values correspond to
-         *    `x,y`. If the first value is a string, it is applied as the name of the
-         *    point, and the `x` value is inferred.
-         *    ```js
-         *    data: [
-         *        [0, 5],
-         *        [1, 10],
-         *        [2, 3]
-         *    ]
-         *    ```
-         *
-         * 3. An array of objects with named values. The following snippet shows only a
-         *    few settings, see the complete options set below. If the total number of
-         *    data points exceeds the series'
-         *    [turboThreshold](#series.bar.turboThreshold), this option is not
-         *    available.
-         *    ```js
-         *    data: [{
-         *        x: 1,
-         *        y: 1,
-         *        name: "Point2",
-         *        color: "#00FF00"
-         *    }, {
-         *        x: 1,
-         *        y: 10,
-         *        name: "Point1",
-         *        color: "#FF00FF"
-         *    }]
-         *    ```
-         *
-         * @sample {highcharts} highcharts/chart/reflow-true/
-         *         Numerical values
-         * @sample {highcharts} highcharts/series/data-array-of-arrays/
-         *         Arrays of numeric x and y
-         * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
-         *         Arrays of datetime x and y
-         * @sample {highcharts} highcharts/series/data-array-of-name-value/
-         *         Arrays of point.name and y
-         * @sample {highcharts} highcharts/series/data-array-of-objects/
-         *         Config objects
-         *
-         * @type      {Array<number|Array<(number|string),(number|null)>|null|*>}
-         * @extends   series.column.data
-         * @product   highcharts
-         * @apioption series.bar.data
+         * @sample {highcharts} highcharts/plotoptions/series-id/
+         *         Get series by id
+         *
+         * @type      {string}
+         * @since     1.2.0
+         * @apioption series.id
          */
         /**
-         * @excluding halo,lineWidth,lineWidthPlus,marker
-         * @product   highcharts highstock
-         * @apioption series.bar.states.hover
+         * The index of the series in the chart, affecting the internal index in the
+         * `chart.series` array, the visible Z index as well as the order in the
+         * legend.
+         *
+         * @type      {number}
+         * @since     2.3.0
+         * @apioption series.index
          */
         /**
-         * @excluding halo,lineWidth,lineWidthPlus,marker
-         * @product   highcharts highstock
-         * @apioption series.bar.states.select
-         */
-        ''; // gets doclets above into transpilat
-
-    });
-    _registerModule(_modules, 'Series/ScatterSeries.js', [_modules['Core/Series/Series.js'], _modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (BaseSeries, H, U) {
-        /* *
-         *
-         *  (c) 2010-2020 Torstein Honsi
-         *
-         *  License: www.highcharts.com/license
-         *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+         * The sequential index of the series in the legend.
          *
-         * */
-        var addEvent = U.addEvent;
-        var Series = H.Series;
-        /**
-         * Scatter series type.
+         * @see [legend.reversed](#legend.reversed),
+         *      [yAxis.reversedStacks](#yAxis.reversedStacks)
          *
-         * @private
-         * @class
-         * @name Highcharts.seriesTypes.scatter
+         * @sample {highcharts|highstock} highcharts/series/legendindex/
+         *         Legend in opposite order
          *
-         * @augments Highcharts.Series
+         * @type      {number}
+         * @apioption series.legendIndex
          */
-        BaseSeries.seriesType('scatter', 'line', 
         /**
-         * A scatter plot uses cartesian coordinates to display values for two
-         * variables for a set of data.
+         * The name of the series as shown in the legend, tooltip etc.
          *
-         * @sample {highcharts} highcharts/demo/scatter/
-         *         Scatter plot
+         * @sample {highcharts} highcharts/series/name/
+         *         Series name
+         * @sample {highmaps} maps/demo/category-map/
+         *         Series name
          *
-         * @extends      plotOptions.line
-         * @excluding    cropThreshold, pointPlacement, shadow, useOhlcData
-         * @product      highcharts highstock
-         * @optionparent plotOptions.scatter
+         * @type      {string}
+         * @apioption series.name
          */
-        {
-            /**
-             * The width of the line connecting the data points.
-             *
-             * @sample {highcharts} highcharts/plotoptions/scatter-linewidth-none/
-             *         0 by default
-             * @sample {highcharts} highcharts/plotoptions/scatter-linewidth-1/
-             *         1px
-             *
-             * @product highcharts highstock
-             */
-            lineWidth: 0,
-            findNearestPointBy: 'xy',
-            /**
-             * Apply a jitter effect for the rendered markers. When plotting
-             * discrete values, a little random noise may help telling the points
-             * apart. The jitter setting applies a random displacement of up to `n`
-             * axis units in either direction. So for example on a horizontal X
-             * axis, setting the `jitter.x` to 0.24 will render the point in a
-             * random position between 0.24 units to the left and 0.24 units to the
-             * right of the true axis position. On a category axis, setting it to
-             * 0.5 will fill up the bin and make the data appear continuous.
-             *
-             * When rendered on top of a box plot or a column series, a jitter value
-             * of 0.24 will correspond to the underlying series' default
-             * [groupPadding](
-             * https://api.highcharts.com/highcharts/plotOptions.column.groupPadding)
-             * and [pointPadding](
-             * https://api.highcharts.com/highcharts/plotOptions.column.pointPadding)
-             * settings.
-             *
-             * @sample {highcharts} highcharts/series-scatter/jitter
-             *         Jitter on a scatter plot
-             *
-             * @sample {highcharts} highcharts/series-scatter/jitter-boxplot
-             *         Jittered scatter plot on top of a box plot
-             *
-             * @product highcharts highstock
-             * @since 7.0.2
-             */
-            jitter: {
-                /**
-                 * The maximal X offset for the random jitter effect.
-                 */
-                x: 0,
-                /**
-                 * The maximal Y offset for the random jitter effect.
-                 */
-                y: 0
-            },
-            marker: {
-                enabled: true // Overrides auto-enabling in line series (#3647)
-            },
-            /**
-             * Sticky tracking of mouse events. When true, the `mouseOut` event
-             * on a series isn't triggered until the mouse moves over another
-             * series, or out of the plot area. When false, the `mouseOut` event on
-             * a series is triggered when the mouse leaves the area around the
-             * series' graph or markers. This also implies the tooltip. When
-             * `stickyTracking` is false and `tooltip.shared` is false, the tooltip
-             * will be hidden when moving the mouse between series.
-             *
-             * @type      {boolean}
-             * @default   false
-             * @product   highcharts highstock
-             * @apioption plotOptions.scatter.stickyTracking
-             */
-            /**
-             * A configuration object for the tooltip rendering of each single
-             * series. Properties are inherited from [tooltip](#tooltip).
-             * Overridable properties are `headerFormat`, `pointFormat`,
-             * `yDecimals`, `xDateFormat`, `yPrefix` and `ySuffix`. Unlike other
-             * series, in a scatter plot the series.name by default shows in the
-             * headerFormat and point.x and point.y in the pointFormat.
-             *
-             * @product highcharts highstock
-             */
-            tooltip: {
-                headerFormat: '<span style="color:{point.color}">\u25CF</span> ' +
-                    '<span style="font-size: 10px"> {series.name}</span><br/>',
-                pointFormat: 'x: <b>{point.x}</b><br/>y: <b>{point.y}</b><br/>'
-            }
-            // Prototype members
-        }, {
-            sorted: false,
-            requireSorting: false,
-            noSharedTooltip: true,
-            trackerGroups: ['group', 'markerGroup', 'dataLabelsGroup'],
-            takeOrdinalPosition: false,
-            /* eslint-disable valid-jsdoc */
-            /**
-             * @private
-             * @function Highcharts.seriesTypes.scatter#drawGraph
-             */
-            drawGraph: function () {
-                if (this.options.lineWidth ||
-                    // In case we have a graph from before and we update the line
-                    // width to 0 (#13816)
-                    (this.options.lineWidth === 0 &&
-                        this.graph &&
-                        this.graph.strokeWidth())) {
-                    Series.prototype.drawGraph.call(this);
-                }
-            },
-            // Optionally add the jitter effect
-            applyJitter: function () {
-                var series = this,
-                    jitter = this.options.jitter,
-                    len = this.points.length;
-                /**
-                 * Return a repeatable, pseudo-random number based on an integer
-                 * seed.
-                 * @private
-                 */
-                function unrandom(seed) {
-                    var rand = Math.sin(seed) * 10000;
-                    return rand - Math.floor(rand);
-                }
-                if (jitter) {
-                    this.points.forEach(function (point, i) {
-                        ['x', 'y'].forEach(function (dim, j) {
-                            var axis,
-                                plotProp = 'plot' + dim.toUpperCase(),
-                                min,
-                                max,
-                                translatedJitter;
-                            if (jitter[dim] && !point.isNull) {
-                                axis = series[dim + 'Axis'];
-                                translatedJitter =
-                                    jitter[dim] * axis.transA;
-                                if (axis && !axis.isLog) {
-                                    // Identify the outer bounds of the jitter range
-                                    min = Math.max(0, point[plotProp] - translatedJitter);
-                                    max = Math.min(axis.len, point[plotProp] + translatedJitter);
-                                    // Find a random position within this range
-                                    point[plotProp] = min +
-                                        (max - min) * unrandom(i + j * len);
-                                    // Update clientX for the tooltip k-d-tree
-                                    if (dim === 'x') {
-                                        point.clientX = point.plotX;
-                                    }
-                                }
-                            }
-                        });
-                    });
-                }
-            }
-            /* eslint-enable valid-jsdoc */
-        });
-        /* eslint-disable no-invalid-this */
-        addEvent(Series, 'afterTranslate', function () {
-            if (this.applyJitter) {
-                this.applyJitter();
-            }
-        });
-        /* eslint-enable no-invalid-this */
         /**
-         * A `scatter` series. If the [type](#series.scatter.type) option is
-         * not specified, it is inherited from [chart.type](#chart.type).
-         *
-         * @extends   series,plotOptions.scatter
-         * @excluding cropThreshold, dataParser, dataURL, useOhlcData
-         * @product   highcharts highstock
-         * @apioption series.scatter
-         */
-        /**
-         * An array of data points for the series. For the `scatter` series
-         * type, points can be given in the following ways:
-         *
-         * 1. An array of numerical values. In this case, the numerical values will be
-         *    interpreted as `y` options. The `x` values will be automatically
-         *    calculated, either starting at 0 and incremented by 1, or from
-         *    `pointStart` and `pointInterval` given in the series options. If the axis
-         *    has categories, these will be used. Example:
-         *    ```js
-         *    data: [0, 5, 3, 5]
-         *    ```
-         *
-         * 2. An array of arrays with 2 values. In this case, the values correspond to
-         *    `x,y`. If the first value is a string, it is applied as the name of the
-         *    point, and the `x` value is inferred.
-         *    ```js
-         *    data: [
-         *        [0, 0],
-         *        [1, 8],
-         *        [2, 9]
-         *    ]
-         *    ```
-         *
-         * 3. An array of objects with named values. The following snippet shows only a
-         *    few settings, see the complete options set below. If the total number of
-         *    data points exceeds the series'
-         *    [turboThreshold](#series.scatter.turboThreshold), this option is not
-         *    available.
-         *    ```js
-         *    data: [{
-         *        x: 1,
-         *        y: 2,
-         *        name: "Point2",
-         *        color: "#00FF00"
-         *    }, {
-         *        x: 1,
-         *        y: 4,
-         *        name: "Point1",
-         *        color: "#FF00FF"
-         *    }]
-         *    ```
-         *
-         * @sample {highcharts} highcharts/chart/reflow-true/
-         *         Numerical values
-         * @sample {highcharts} highcharts/series/data-array-of-arrays/
-         *         Arrays of numeric x and y
-         * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
-         *         Arrays of datetime x and y
-         * @sample {highcharts} highcharts/series/data-array-of-name-value/
-         *         Arrays of point.name and y
-         * @sample {highcharts} highcharts/series/data-array-of-objects/
-         *         Config objects
-         *
-         * @type      {Array<number|Array<(number|string),(number|null)>|null|*>}
-         * @extends   series.line.data
-         * @product   highcharts highstock
-         * @apioption series.scatter.data
-         */
-        ''; // adds doclets above to transpilat
-
-    });
-    _registerModule(_modules, 'Mixins/CenteredSeries.js', [_modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (H, U) {
-        /* *
-         *
-         *  (c) 2010-2020 Torstein Honsi
-         *
-         *  License: www.highcharts.com/license
-         *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+         * This option allows grouping series in a stacked chart. The stack option
+         * can be a string or anything else, as long as the grouped series' stack
+         * options match each other after conversion into a string.
          *
-         * */
-        /**
-         * @private
-         * @interface Highcharts.RadianAngles
-         */ /**
-        * @name Highcharts.RadianAngles#end
-        * @type {number}
-        */ /**
-        * @name Highcharts.RadianAngles#start
-        * @type {number}
-        */
-        var isNumber = U.isNumber,
-            pick = U.pick,
-            relativeLength = U.relativeLength;
-        var deg2rad = H.deg2rad;
-        /* eslint-disable valid-jsdoc */
-        /**
-         * @private
-         * @mixin Highcharts.CenteredSeriesMixin
-         */
-        var centeredSeriesMixin = H.CenteredSeriesMixin = {
-                /**
-                 * Get the center of the pie based on the size and center options relative
-                 * to the plot area. Borrowed by the polar and gauge series types.
-                 *
-                 * @private
-                 * @function Highcharts.CenteredSeriesMixin.getCenter
-                 *
-                 * @return {Array<number>}
-                 */
-                getCenter: function () {
-                    var options = this.options,
-            chart = this.chart,
-            slicingRoom = 2 * (options.slicedOffset || 0),
-            handleSlicingRoom,
-            plotWidth = chart.plotWidth - 2 * slicingRoom,
-            plotHeight = chart.plotHeight - 2 * slicingRoom,
-            centerOption = options.center,
-            smallestSize = Math.min(plotWidth,
-            plotHeight),
-            size = options.size,
-            innerSize = options.innerSize || 0,
-            positions,
-            i,
-            value;
-                if (typeof size === 'string') {
-                    size = parseFloat(size);
-                }
-                if (typeof innerSize === 'string') {
-                    innerSize = parseFloat(innerSize);
-                }
-                positions = [
-                    pick(centerOption[0], '50%'),
-                    pick(centerOption[1], '50%'),
-                    // Prevent from negative values
-                    pick(size && size < 0 ? void 0 : options.size, '100%'),
-                    pick(innerSize && innerSize < 0 ? void 0 : options.innerSize || 0, '0%')
-                ];
-                // No need for inner size in angular (gauges) series but still required
-                // for pie series
-                if (chart.angular && !(this instanceof H.Series)) {
-                    positions[3] = 0;
-                }
-                for (i = 0; i < 4; ++i) {
-                    value = positions[i];
-                    handleSlicingRoom = i < 2 || (i === 2 && /%$/.test(value));
-                    // i == 0: centerX, relative to width
-                    // i == 1: centerY, relative to height
-                    // i == 2: size, relative to smallestSize
-                    // i == 3: innerSize, relative to size
-                    positions[i] = relativeLength(value, [plotWidth, plotHeight, smallestSize, positions[2]][i]) + (handleSlicingRoom ? slicingRoom : 0);
-                }
-                // innerSize cannot be larger than size (#3632)
-                if (positions[3] > positions[2]) {
-                    positions[3] = positions[2];
-                }
-                return positions;
-            },
-            /**
-             * getStartAndEndRadians - Calculates start and end angles in radians.
-             * Used in series types such as pie and sunburst.
-             *
-             * @private
-             * @function Highcharts.CenteredSeriesMixin.getStartAndEndRadians
-             *
-             * @param {number} [start]
-             *        Start angle in degrees.
-             *
-             * @param {number} [end]
-             *        Start angle in degrees.
-             *
-             * @return {Highcharts.RadianAngles}
-             *         Returns an object containing start and end angles as radians.
-             */
-            getStartAndEndRadians: function (start, end) {
-                var startAngle = isNumber(start) ? start : 0, // must be a number
-                    endAngle = ((isNumber(end) && // must be a number
-                        end > startAngle && // must be larger than the start angle
-                        // difference must be less than 360 degrees
-                        (end - startAngle) < 360) ?
-                        end :
-                        startAngle + 360),
-                    correction = -90;
-                return {
-                    start: deg2rad * (startAngle + correction),
-                    end: deg2rad * (endAngle + correction)
-                };
-            }
-        };
-
-        return centeredSeriesMixin;
-    });
-    _registerModule(_modules, 'Series/PieSeries.js', [_modules['Core/Animation/AnimationUtilities.js'], _modules['Core/Series/Series.js'], _modules['Mixins/CenteredSeries.js'], _modules['Core/Globals.js'], _modules['Mixins/LegendSymbol.js'], _modules['Series/LineSeries.js'], _modules['Core/Series/Point.js'], _modules['Core/Renderer/SVG/SVGRenderer.js'], _modules['Core/Utilities.js']], function (A, BaseSeries, CenteredSeriesMixin, H, LegendSymbolMixin, LineSeries, Point, SVGRenderer, U) {
-        /* *
+         * @sample {highcharts} highcharts/series/stack/
+         *         Stacked and grouped columns
          *
-         *  (c) 2010-2020 Torstein Honsi
+         * @type      {number|string}
+         * @since     2.1
+         * @product   highcharts highstock
+         * @apioption series.stack
+         */
+        /**
+         * The type of series, for example `line` or `column`. By default, the
+         * series type is inherited from [chart.type](#chart.type), so unless the
+         * chart is a combination of series types, there is no need to set it on the
+         * series level.
          *
-         *  License: www.highcharts.com/license
+         * @sample {highcharts} highcharts/series/type/
+         *         Line and column in the same chart
+         * @sample highcharts/series/type-dynamic/
+         *         Dynamic types with button selector
+         * @sample {highmaps} maps/demo/mapline-mappoint/
+         *         Multiple types in the same map
          *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+         * @type      {string}
+         * @apioption series.type
+         */
+        /**
+         * When using dual or multiple x axes, this number defines which xAxis the
+         * particular series is connected to. It refers to either the
+         * {@link #xAxis.id|axis id}
+         * or the index of the axis in the xAxis array, with 0 being the first.
          *
-         * */
-        var setAnimation = A.setAnimation;
-        var getStartAndEndRadians = CenteredSeriesMixin.getStartAndEndRadians;
-        var noop = H.noop;
-        var addEvent = U.addEvent,
-            clamp = U.clamp,
-            defined = U.defined,
-            fireEvent = U.fireEvent,
-            isNumber = U.isNumber,
-            merge = U.merge,
-            pick = U.pick,
-            relativeLength = U.relativeLength;
-        /**
-         * Pie series type.
+         * @type      {number|string}
+         * @default   0
+         * @product   highcharts highstock
+         * @apioption series.xAxis
+         */
+        /**
+         * When using dual or multiple y axes, this number defines which yAxis the
+         * particular series is connected to. It refers to either the
+         * {@link #yAxis.id|axis id}
+         * or the index of the axis in the yAxis array, with 0 being the first.
          *
-         * @private
-         * @class
-         * @name Highcharts.seriesTypes.pie
+         * @sample {highcharts} highcharts/series/yaxis/
+         *         Apply the column series to the secondary Y axis
          *
-         * @augments Highcharts.Series
+         * @type      {number|string}
+         * @default   0
+         * @product   highcharts highstock
+         * @apioption series.yAxis
          */
-        BaseSeries.seriesType('pie', 'line', 
         /**
-         * A pie chart is a circular graphic which is divided into slices to
-         * illustrate numerical proportion.
+         * Define the visual z index of the series.
          *
-         * @sample highcharts/demo/pie-basic/
-         *         Pie chart
+         * @sample {highcharts} highcharts/plotoptions/series-zindex-default/
+         *         With no z index, the series defined last are on top
+         * @sample {highcharts} highcharts/plotoptions/series-zindex/
+         *         With a z index, the series with the highest z index is on top
+         * @sample {highstock} highcharts/plotoptions/series-zindex-default/
+         *         With no z index, the series defined last are on top
+         * @sample {highstock} highcharts/plotoptions/series-zindex/
+         *         With a z index, the series with the highest z index is on top
          *
-         * @extends      plotOptions.line
-         * @excluding    animationLimit, boostThreshold, connectEnds, connectNulls,
-         *               cropThreshold, dashStyle, dataSorting, dragDrop,
-         *               findNearestPointBy, getExtremesFromAll, label, lineWidth,
-         *               marker, negativeColor, pointInterval, pointIntervalUnit,
-         *               pointPlacement, pointStart, softThreshold, stacking, step,
-         *               threshold, turboThreshold, zoneAxis, zones, dataSorting,
-         *               boostBlending
-         * @product      highcharts
-         * @optionparent plotOptions.pie
+         * @type      {number}
+         * @product   highcharts highstock
+         * @apioption series.zIndex
+         */
+        void 0,
+        /**
+         * General options for all series types.
+         *
+         * @optionparent plotOptions.series
          */
         {
-            /**
-             * @excluding legendItemClick
-             * @apioption plotOptions.pie.events
+          /**
+           * The SVG value used for the `stroke-linecap` and `stroke-linejoin`
+           * of a line graph. Round means that lines are rounded in the ends and
+           * bends.
+           *
+           * @type       {Highcharts.SeriesLinecapValue}
+           * @default    round
+           * @since      3.0.7
+           * @apioption  plotOptions.line.linecap
+           */
+          /**
+           * Pixel width of the graph line.
+           *
+           * @see In styled mode, the line stroke-width can be set with the
+           *      `.highcharts-graph` class name.
+           *
+           * @sample {highcharts} highcharts/plotoptions/series-linewidth-general/
+           *         On all series
+           * @sample {highcharts} highcharts/plotoptions/series-linewidth-specific/
+           *         On one single series
+           *
+           * @product highcharts highstock
+           *
+           * @private
+           */
+          lineWidth: 2,
+          /**
+           * For some series, there is a limit that shuts down initial animation
+           * by default when the total number of points in the chart is too high.
+           * For example, for a column chart and its derivatives, animation does
+           * not run if there is more than 250 points totally. To disable this
+           * cap, set `animationLimit` to `Infinity`.
+           *
+           * @type      {number}
+           * @apioption plotOptions.series.animationLimit
+           */
+          /**
+           * Allow this series' points to be selected by clicking on the graphic
+           * (columns, point markers, pie slices, map areas etc).
+           *
+           * The selected points can be handled by point select and unselect
+           * events, or collectively by the [getSelectedPoints
+           * ](/class-reference/Highcharts.Chart#getSelectedPoints) function.
+           *
+           * And alternative way of selecting points is through dragging.
+           *
+           * @sample {highcharts} highcharts/plotoptions/series-allowpointselect-line/
+           *         Line
+           * @sample {highcharts} highcharts/plotoptions/series-allowpointselect-column/
+           *         Column
+           * @sample {highcharts} highcharts/plotoptions/series-allowpointselect-pie/
+           *         Pie
+           * @sample {highcharts} highcharts/chart/events-selection-points/
+           *         Select a range of points through a drag selection
+           * @sample {highmaps} maps/plotoptions/series-allowpointselect/
+           *         Map area
+           * @sample {highmaps} maps/plotoptions/mapbubble-allowpointselect/
+           *         Map bubble
+           *
+           * @since 1.2.0
+           *
+           * @private
+           */
+          allowPointSelect: false,
+          /**
+           * When true, each point or column edge is rounded to its nearest pixel
+           * in order to render sharp on screen. In some cases, when there are a
+           * lot of densely packed columns, this leads to visible difference
+           * in column widths or distance between columns. In these cases,
+           * setting `crisp` to `false` may look better, even though each column
+           * is rendered blurry.
+           *
+           * @sample {highcharts} highcharts/plotoptions/column-crisp-false/
+           *         Crisp is false
+           *
+           * @since   5.0.10
+           * @product highcharts highstock gantt
+           *
+           * @private
+           */
+          crisp: true,
+          /**
+           * If true, a checkbox is displayed next to the legend item to allow
+           * selecting the series. The state of the checkbox is determined by
+           * the `selected` option.
+           *
+           * @productdesc {highmaps}
+           * Note that if a `colorAxis` is defined, the color axis is represented
+           * in the legend, not the series.
+           *
+           * @sample {highcharts} highcharts/plotoptions/series-showcheckbox-true/
+           *         Show select box
+           *
+           * @since 1.2.0
+           *
+           * @private
+           */
+          showCheckbox: false,
+          /**
+           * Enable or disable the initial animation when a series is displayed.
+           * The animation can also be set as a configuration object. Please
+           * note that this option only applies to the initial animation of the
+           * series itself. For other animations, see [chart.animation](
+           * #chart.animation) and the animation parameter under the API methods.
+           * The following properties are supported:
+           *
+           * - `defer`: The animation delay time in milliseconds.
+           *
+           * - `duration`: The duration of the animation in milliseconds.
+           *
+           * - `easing`: Can be a string reference to an easing function set on
+           *   the `Math` object or a function. See the _Custom easing function_
+           *   demo below.
+           *
+           * Due to poor performance, animation is disabled in old IE browsers
+           * for several chart types.
+           *
+           * @sample {highcharts} highcharts/plotoptions/series-animation-disabled/
+           *         Animation disabled
+           * @sample {highcharts} highcharts/plotoptions/series-animation-slower/
+           *         Slower animation
+           * @sample {highcharts} highcharts/plotoptions/series-animation-easing/
+           *         Custom easing function
+           * @sample {highstock} stock/plotoptions/animation-slower/
+           *         Slower animation
+           * @sample {highstock} stock/plotoptions/animation-easing/
+           *         Custom easing function
+           * @sample {highmaps} maps/plotoptions/series-animation-true/
+           *         Animation enabled on map series
+           * @sample {highmaps} maps/plotoptions/mapbubble-animation-false/
+           *         Disabled on mapbubble series
+           *
+           * @type    {boolean|Partial<Highcharts.AnimationOptionsObject>}
+           * @default {highcharts} true
+           * @default {highstock} true
+           * @default {highmaps} false
+           *
+           * @private
+           */
+          animation: {
+            /** @internal */
+            duration: 1000,
+          },
+          /**
+           * @default   0
+           * @type      {number}
+           * @since     8.2.0
+           * @apioption plotOptions.series.animation.defer
+           */
+          /**
+           * An additional class name to apply to the series' graphical elements.
+           * This option does not replace default class names of the graphical
+           * element.
+           *
+           * @type      {string}
+           * @since     5.0.0
+           * @apioption plotOptions.series.className
+           */
+          /**
+           * Disable this option to allow series rendering in the whole plotting
+           * area.
+           *
+           * **Note:** Clipping should be always enabled when
+           * [chart.zoomType](#chart.zoomType) is set
+           *
+           * @sample {highcharts} highcharts/plotoptions/series-clip/
+           *         Disabled clipping
+           *
+           * @default   true
+           * @type      {boolean}
+           * @since     3.0.0
+           * @apioption plotOptions.series.clip
+           */
+          /**
+           * The main color of the series. In line type series it applies to the
+           * line and the point markers unless otherwise specified. In bar type
+           * series it applies to the bars unless a color is specified per point.
+           * The default value is pulled from the `options.colors` array.
+           *
+           * In styled mode, the color can be defined by the
+           * [colorIndex](#plotOptions.series.colorIndex) option. Also, the series
+           * color can be set with the `.highcharts-series`,
+           * `.highcharts-color-{n}`, `.highcharts-{type}-series` or
+           * `.highcharts-series-{n}` class, or individual classes given by the
+           * `className` option.
+           *
+           * @productdesc {highmaps}
+           * In maps, the series color is rarely used, as most choropleth maps use
+           * the color to denote the value of each point. The series color can
+           * however be used in a map with multiple series holding categorized
+           * data.
+           *
+           * @sample {highcharts} highcharts/plotoptions/series-color-general/
+           *         General plot option
+           * @sample {highcharts} highcharts/plotoptions/series-color-specific/
+           *         One specific series
+           * @sample {highcharts} highcharts/plotoptions/series-color-area/
+           *         Area color
+           * @sample {highcharts} highcharts/series/infographic/
+           *         Pattern fill
+           * @sample {highmaps} maps/demo/category-map/
+           *         Category map by multiple series
+           *
+           * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+           * @apioption plotOptions.series.color
+           */
+          /**
+           * Styled mode only. A specific color index to use for the series, so
+           * its graphic representations are given the class name
+           * `highcharts-color-{n}`.
+           *
+           * @type      {number}
+           * @since     5.0.0
+           * @apioption plotOptions.series.colorIndex
+           */
+          /**
+           * Whether to connect a graph line across null points, or render a gap
+           * between the two points on either side of the null.
+           *
+           * @sample {highcharts} highcharts/plotoptions/series-connectnulls-false/
+           *         False by default
+           * @sample {highcharts} highcharts/plotoptions/series-connectnulls-true/
+           *         True
+           *
+           * @type      {boolean}
+           * @default   false
+           * @product   highcharts highstock
+           * @apioption plotOptions.series.connectNulls
+           */
+          /**
+           * You can set the cursor to "pointer" if you have click events attached
+           * to the series, to signal to the user that the points and lines can
+           * be clicked.
+           *
+           * In styled mode, the series cursor can be set with the same classes
+           * as listed under [series.color](#plotOptions.series.color).
+           *
+           * @sample {highcharts} highcharts/plotoptions/series-cursor-line/
+           *         On line graph
+           * @sample {highcharts} highcharts/plotoptions/series-cursor-column/
+           *         On columns
+           * @sample {highcharts} highcharts/plotoptions/series-cursor-scatter/
+           *         On scatter markers
+           * @sample {highstock} stock/plotoptions/cursor/
+           *         Pointer on a line graph
+           * @sample {highmaps} maps/plotoptions/series-allowpointselect/
+           *         Map area
+           * @sample {highmaps} maps/plotoptions/mapbubble-allowpointselect/
+           *         Map bubble
+           *
+           * @type      {string|Highcharts.CursorValue}
+           * @apioption plotOptions.series.cursor
+           */
+          /**
+           * A reserved subspace to store options and values for customized
+           * functionality. Here you can add additional data for your own event
+           * callbacks and formatter callbacks.
+           *
+           * @sample {highcharts} highcharts/point/custom/
+           *         Point and series with custom data
+           *
+           * @type      {Highcharts.Dictionary<*>}
+           * @apioption plotOptions.series.custom
+           */
+          /**
+           * Name of the dash style to use for the graph, or for some series types
+           * the outline of each shape.
+           *
+           * In styled mode, the
+           * [stroke dash-array](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/css/series-dashstyle/)
+           * can be set with the same classes as listed under
+           * [series.color](#plotOptions.series.color).
+           *
+           * @sample {highcharts} highcharts/plotoptions/series-dashstyle-all/
+           *         Possible values demonstrated
+           * @sample {highcharts} highcharts/plotoptions/series-dashstyle/
+           *         Chart suitable for printing in black and white
+           * @sample {highstock} highcharts/plotoptions/series-dashstyle-all/
+           *         Possible values demonstrated
+           * @sample {highmaps} highcharts/plotoptions/series-dashstyle-all/
+           *         Possible values demonstrated
+           * @sample {highmaps} maps/plotoptions/series-dashstyle/
+           *         Dotted borders on a map
+           *
+           * @type      {Highcharts.DashStyleValue}
+           * @default   Solid
+           * @since     2.1
+           * @apioption plotOptions.series.dashStyle
+           */
+          /**
+           * A description of the series to add to the screen reader information
+           * about the series.
+           *
+           * @type      {string}
+           * @since     5.0.0
+           * @requires  modules/accessibility
+           * @apioption plotOptions.series.description
+           */
+          /**
+           * Options for the series data sorting.
+           *
+           * @type      {Highcharts.DataSortingOptionsObject}
+           * @since     8.0.0
+           * @product   highcharts highstock
+           * @apioption plotOptions.series.dataSorting
+           */
+          /**
+           * Enable or disable data sorting for the series. Use [xAxis.reversed](
+           * #xAxis.reversed) to change the sorting order.
+           *
+           * @sample {highcharts} highcharts/datasorting/animation/
+           *         Data sorting in scatter-3d
+           * @sample {highcharts} highcharts/datasorting/labels-animation/
+           *         Axis labels animation
+           * @sample {highcharts} highcharts/datasorting/dependent-sorting/
+           *         Dependent series sorting
+           * @sample {highcharts} highcharts/datasorting/independent-sorting/
+           *         Independent series sorting
+           *
+           * @type      {boolean}
+           * @since     8.0.0
+           * @apioption plotOptions.series.dataSorting.enabled
+           */
+          /**
+           * Whether to allow matching points by name in an update. If this option
+           * is disabled, points will be matched by order.
+           *
+           * @sample {highcharts} highcharts/datasorting/match-by-name/
+           *         Enabled match by name
+           *
+           * @type      {boolean}
+           * @since     8.0.0
+           * @apioption plotOptions.series.dataSorting.matchByName
+           */
+          /**
+           * Determines what data value should be used to sort by.
+           *
+           * @sample {highcharts} highcharts/datasorting/sort-key/
+           *         Sort key as `z` value
+           *
+           * @type      {string}
+           * @since     8.0.0
+           * @default   y
+           * @apioption plotOptions.series.dataSorting.sortKey
+           */
+          /**
+           * Enable or disable the mouse tracking for a specific series. This
+           * includes point tooltips and click events on graphs and points. For
+           * large datasets it improves performance.
+           *
+           * @sample {highcharts} highcharts/plotoptions/series-enablemousetracking-false/
+           *         No mouse tracking
+           * @sample {highmaps} maps/plotoptions/series-enablemousetracking-false/
+           *         No mouse tracking
+           *
+           * @type      {boolean}
+           * @default   true
+           * @apioption plotOptions.series.enableMouseTracking
+           */
+          /**
+           * Whether to use the Y extremes of the total chart width or only the
+           * zoomed area when zooming in on parts of the X axis. By default, the
+           * Y axis adjusts to the min and max of the visible data. Cartesian
+           * series only.
+           *
+           * @type      {boolean}
+           * @default   false
+           * @since     4.1.6
+           * @product   highcharts highstock gantt
+           * @apioption plotOptions.series.getExtremesFromAll
+           */
+          /**
+           * An array specifying which option maps to which key in the data point
+           * array. This makes it convenient to work with unstructured data arrays
+           * from different sources.
+           *
+           * @see [series.data](#series.line.data)
+           *
+           * @sample {highcharts|highstock} highcharts/series/data-keys/
+           *         An extended data array with keys
+           * @sample {highcharts|highstock} highcharts/series/data-nested-keys/
+           *         Nested keys used to access object properties
+           *
+           * @type      {Array<string>}
+           * @since     4.1.6
+           * @apioption plotOptions.series.keys
+           */
+          /**
+           * The line cap used for line ends and line joins on the graph.
+           *
+           * @type       {Highcharts.SeriesLinecapValue}
+           * @default    round
+           * @product    highcharts highstock
+           * @apioption  plotOptions.series.linecap
+           */
+          /**
+           * The [id](#series.id) of another series to link to. Additionally,
+           * the value can be ":previous" to link to the previous series. When
+           * two series are linked, only the first one appears in the legend.
+           * Toggling the visibility of this also toggles the linked series.
+           *
+           * If master series uses data sorting and linked series does not have
+           * its own sorting definition, the linked series will be sorted in the
+           * same order as the master one.
+           *
+           * @sample {highcharts|highstock} highcharts/demo/arearange-line/
+           *         Linked series
+           *
+           * @type      {string}
+           * @since     3.0
+           * @product   highcharts highstock gantt
+           * @apioption plotOptions.series.linkedTo
+           */
+          /**
+           * Options for the corresponding navigator series if `showInNavigator`
+           * is `true` for this series. Available options are the same as any
+           * series, documented at [plotOptions](#plotOptions.series) and
+           * [series](#series).
+           *
+           * These options are merged with options in [navigator.series](
+           * #navigator.series), and will take precedence if the same option is
+           * defined both places.
+           *
+           * @see [navigator.series](#navigator.series)
+           *
+           * @type      {Highcharts.PlotSeriesOptions}
+           * @since     5.0.0
+           * @product   highstock
+           * @apioption plotOptions.series.navigatorOptions
+           */
+          /**
+           * The color for the parts of the graph or points that are below the
+           * [threshold](#plotOptions.series.threshold). Note that `zones` takes
+           * precedence over the negative color. Using `negativeColor` is
+           * equivalent to applying a zone with value of 0.
+           *
+           * @see In styled mode, a negative color is applied by setting this option
+           *      to `true` combined with the `.highcharts-negative` class name.
+           *
+           * @sample {highcharts} highcharts/plotoptions/series-negative-color/
+           *         Spline, area and column
+           * @sample {highcharts} highcharts/plotoptions/arearange-negativecolor/
+           *         Arearange
+           * @sample {highcharts} highcharts/css/series-negative-color/
+           *         Styled mode
+           * @sample {highstock} highcharts/plotoptions/series-negative-color/
+           *         Spline, area and column
+           * @sample {highstock} highcharts/plotoptions/arearange-negativecolor/
+           *         Arearange
+           * @sample {highmaps} highcharts/plotoptions/series-negative-color/
+           *         Spline, area and column
+           * @sample {highmaps} highcharts/plotoptions/arearange-negativecolor/
+           *         Arearange
+           *
+           * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+           * @since     3.0
+           * @apioption plotOptions.series.negativeColor
+           */
+          /**
+           * Same as
+           * [accessibility.pointDescriptionFormatter](#accessibility.pointDescriptionFormatter),
+           * but for an individual series. Overrides the chart wide configuration.
+           *
+           * @type      {Function}
+           * @since     5.0.12
+           * @apioption plotOptions.series.pointDescriptionFormatter
+           */
+          /**
+           * If no x values are given for the points in a series, `pointInterval`
+           * defines the interval of the x values. For example, if a series
+           * contains one value every decade starting from year 0, set
+           * `pointInterval` to `10`. In true `datetime` axes, the `pointInterval`
+           * is set in milliseconds.
+           *
+           * It can be also be combined with `pointIntervalUnit` to draw irregular
+           * time intervals.
+           *
+           * Please note that this options applies to the _series data_, not the
+           * interval of the axis ticks, which is independent.
+           *
+           * @sample {highcharts} highcharts/plotoptions/series-pointstart-datetime/
+           *         Datetime X axis
+           * @sample {highstock} stock/plotoptions/pointinterval-pointstart/
+           *         Using pointStart and pointInterval
+           *
+           * @type      {number}
+           * @default   1
+           * @product   highcharts highstock gantt
+           * @apioption plotOptions.series.pointInterval
+           */
+          /**
+           * On datetime series, this allows for setting the
+           * [pointInterval](#plotOptions.series.pointInterval) to irregular time
+           * units, `day`, `month` and `year`. A day is usually the same as 24
+           * hours, but `pointIntervalUnit` also takes the DST crossover into
+           * consideration when dealing with local time. Combine this option with
+           * `pointInterval` to draw weeks, quarters, 6 months, 10 years etc.
+           *
+           * Please note that this options applies to the _series data_, not the
+           * interval of the axis ticks, which is independent.
+           *
+           * @sample {highcharts} highcharts/plotoptions/series-pointintervalunit/
+           *         One point a month
+           * @sample {highstock} highcharts/plotoptions/series-pointintervalunit/
+           *         One point a month
+           *
+           * @type       {string}
+           * @since      4.1.0
+           * @product    highcharts highstock gantt
+           * @validvalue ["day", "month", "year"]
+           * @apioption  plotOptions.series.pointIntervalUnit
+           */
+          /**
+           * Possible values: `"on"`, `"between"`, `number`.
+           *
+           * In a column chart, when pointPlacement is `"on"`, the point will not
+           * create any padding of the X axis. In a polar column chart this means
+           * that the first column points directly north. If the pointPlacement is
+           * `"between"`, the columns will be laid out between ticks. This is
+           * useful for example for visualising an amount between two points in
+           * time or in a certain sector of a polar chart.
+           *
+           * Since Highcharts 3.0.2, the point placement can also be numeric,
+           * where 0 is on the axis value, -0.5 is between this value and the
+           * previous, and 0.5 is between this value and the next. Unlike the
+           * textual options, numeric point placement options won't affect axis
+           * padding.
+           *
+           * Note that pointPlacement needs a [pointRange](
+           * #plotOptions.series.pointRange) to work. For column series this is
+           * computed, but for line-type series it needs to be set.
+           *
+           * For the `xrange` series type and gantt charts, if the Y axis is a
+           * category axis, the `pointPlacement` applies to the Y axis rather than
+           * the (typically datetime) X axis.
+           *
+           * Defaults to `undefined` in cartesian charts, `"between"` in polar
+           * charts.
+           *
+           * @see [xAxis.tickmarkPlacement](#xAxis.tickmarkPlacement)
+           *
+           * @sample {highcharts|highstock} highcharts/plotoptions/series-pointplacement-between/
+           *         Between in a column chart
+           * @sample {highcharts|highstock} highcharts/plotoptions/series-pointplacement-numeric/
+           *         Numeric placement for custom layout
+           * @sample {highcharts|highstock} maps/plotoptions/heatmap-pointplacement/
+           *         Placement in heatmap
+           *
+           * @type      {string|number}
+           * @since     2.3.0
+           * @product   highcharts highstock gantt
+           * @apioption plotOptions.series.pointPlacement
+           */
+          /**
+           * If no x values are given for the points in a series, pointStart
+           * defines on what value to start. For example, if a series contains one
+           * yearly value starting from 1945, set pointStart to 1945.
+           *
+           * @sample {highcharts} highcharts/plotoptions/series-pointstart-linear/
+           *         Linear
+           * @sample {highcharts} highcharts/plotoptions/series-pointstart-datetime/
+           *         Datetime
+           * @sample {highstock} stock/plotoptions/pointinterval-pointstart/
+           *         Using pointStart and pointInterval
+           *
+           * @type      {number}
+           * @default   0
+           * @product   highcharts highstock gantt
+           * @apioption plotOptions.series.pointStart
+           */
+          /**
+           * Whether to select the series initially. If `showCheckbox` is true,
+           * the checkbox next to the series name in the legend will be checked
+           * for a selected series.
+           *
+           * @sample {highcharts} highcharts/plotoptions/series-selected/
+           *         One out of two series selected
+           *
+           * @type      {boolean}
+           * @default   false
+           * @since     1.2.0
+           * @apioption plotOptions.series.selected
+           */
+          /**
+           * Whether to apply a drop shadow to the graph line. Since 2.3 the
+           * shadow can be an object configuration containing `color`, `offsetX`,
+           * `offsetY`, `opacity` and `width`.
+           *
+           * @sample {highcharts} highcharts/plotoptions/series-shadow/
+           *         Shadow enabled
+           *
+           * @type      {boolean|Highcharts.ShadowOptionsObject}
+           * @default   false
+           * @apioption plotOptions.series.shadow
+           */
+          /**
+           * Whether to display this particular series or series type in the
+           * legend. Standalone series are shown in legend by default, and linked
+           * series are not. Since v7.2.0 it is possible to show series that use
+           * colorAxis by setting this option to `true`.
+           *
+           * @sample {highcharts} highcharts/plotoptions/series-showinlegend/
+           *         One series in the legend, one hidden
+           *
+           * @type      {boolean}
+           * @apioption plotOptions.series.showInLegend
+           */
+          /**
+           * Whether or not to show the series in the navigator. Takes precedence
+           * over [navigator.baseSeries](#navigator.baseSeries) if defined.
+           *
+           * @type      {boolean}
+           * @since     5.0.0
+           * @product   highstock
+           * @apioption plotOptions.series.showInNavigator
+           */
+          /**
+           * If set to `true`, the accessibility module will skip past the points
+           * in this series for keyboard navigation.
+           *
+           * @type      {boolean}
+           * @since     5.0.12
+           * @apioption plotOptions.series.skipKeyboardNavigation
+           */
+          /**
+           * Whether to stack the values of each series on top of each other.
+           * Possible values are `undefined` to disable, `"normal"` to stack by
+           * value or `"percent"`.
+           *
+           * When stacking is enabled, data must be sorted
+           * in ascending X order.
+           *
+           * Some stacking options are related to specific series types. In the
+           * streamgraph series type, the stacking option is set to `"stream"`.
+           * The second one is `"overlap"`, which only applies to waterfall
+           * series.
+           *
+           * @see [yAxis.reversedStacks](#yAxis.reversedStacks)
+           *
+           * @sample {highcharts} highcharts/plotoptions/series-stacking-line/
+           *         Line
+           * @sample {highcharts} highcharts/plotoptions/series-stacking-column/
+           *         Column
+           * @sample {highcharts} highcharts/plotoptions/series-stacking-bar/
+           *         Bar
+           * @sample {highcharts} highcharts/plotoptions/series-stacking-area/
+           *         Area
+           * @sample {highcharts} highcharts/plotoptions/series-stacking-percent-line/
+           *         Line
+           * @sample {highcharts} highcharts/plotoptions/series-stacking-percent-column/
+           *         Column
+           * @sample {highcharts} highcharts/plotoptions/series-stacking-percent-bar/
+           *         Bar
+           * @sample {highcharts} highcharts/plotoptions/series-stacking-percent-area/
+           *         Area
+           * @sample {highcharts} highcharts/plotoptions/series-waterfall-with-normal-stacking
+           *         Waterfall with normal stacking
+           * @sample {highcharts} highcharts/plotoptions/series-waterfall-with-overlap-stacking
+           *         Waterfall with overlap stacking
+           * @sample {highstock} stock/plotoptions/stacking/
+           *         Area
+           *
+           * @type       {string}
+           * @product    highcharts highstock
+           * @validvalue ["normal", "overlap", "percent", "stream"]
+           * @apioption  plotOptions.series.stacking
+           */
+          /**
+           * Whether to apply steps to the line. Possible values are `left`,
+           * `center` and `right`.
+           *
+           * @sample {highcharts} highcharts/plotoptions/line-step/
+           *         Different step line options
+           * @sample {highcharts} highcharts/plotoptions/area-step/
+           *         Stepped, stacked area
+           * @sample {highstock} stock/plotoptions/line-step/
+           *         Step line
+           *
+           * @type       {string}
+           * @since      1.2.5
+           * @product    highcharts highstock
+           * @validvalue ["left", "center", "right"]
+           * @apioption  plotOptions.series.step
+           */
+          /**
+           * The threshold, also called zero level or base level. For line type
+           * series this is only used in conjunction with
+           * [negativeColor](#plotOptions.series.negativeColor).
+           *
+           * @see [softThreshold](#plotOptions.series.softThreshold).
+           *
+           * @type      {number}
+           * @default   0
+           * @since     3.0
+           * @product   highcharts highstock
+           * @apioption plotOptions.series.threshold
+           */
+          /**
+           * Set the initial visibility of the series.
+           *
+           * @sample {highcharts} highcharts/plotoptions/series-visible/
+           *         Two series, one hidden and one visible
+           * @sample {highstock} stock/plotoptions/series-visibility/
+           *         Hidden series
+           *
+           * @type      {boolean}
+           * @default   true
+           * @apioption plotOptions.series.visible
+           */
+          /**
+           * Defines the Axis on which the zones are applied.
+           *
+           * @see [zones](#plotOptions.series.zones)
+           *
+           * @sample {highcharts} highcharts/series/color-zones-zoneaxis-x/
+           *         Zones on the X-Axis
+           * @sample {highstock} highcharts/series/color-zones-zoneaxis-x/
+           *         Zones on the X-Axis
+           *
+           * @type      {string}
+           * @default   y
+           * @since     4.1.0
+           * @product   highcharts highstock
+           * @apioption plotOptions.series.zoneAxis
+           */
+          /**
+           * General event handlers for the series items. These event hooks can
+           * also be attached to the series at run time using the
+           * `Highcharts.addEvent` function.
+           *
+           * @declare Highcharts.SeriesEventsOptionsObject
+           *
+           * @private
+           */
+          events: {},
+          /**
+           * Fires after the series has finished its initial animation, or in case
+           * animation is disabled, immediately as the series is displayed.
+           *
+           * @sample {highcharts} highcharts/plotoptions/series-events-afteranimate/
+           *         Show label after animate
+           * @sample {highstock} highcharts/plotoptions/series-events-afteranimate/
+           *         Show label after animate
+           *
+           * @type      {Highcharts.SeriesAfterAnimateCallbackFunction}
+           * @since     4.0
+           * @product   highcharts highstock gantt
+           * @context   Highcharts.Series
+           * @apioption plotOptions.series.events.afterAnimate
+           */
+          /**
+           * Fires when the checkbox next to the series' name in the legend is
+           * clicked. One parameter, `event`, is passed to the function. The state
+           * of the checkbox is found by `event.checked`. The checked item is
+           * found by `event.item`. Return `false` to prevent the default action
+           * which is to toggle the select state of the series.
+           *
+           * @sample {highcharts} highcharts/plotoptions/series-events-checkboxclick/
+           *         Alert checkbox status
+           *
+           * @type      {Highcharts.SeriesCheckboxClickCallbackFunction}
+           * @since     1.2.0
+           * @context   Highcharts.Series
+           * @apioption plotOptions.series.events.checkboxClick
+           */
+          /**
+           * Fires when the series is clicked. One parameter, `event`, is passed
+           * to the function, containing common event information. Additionally,
+           * `event.point` holds a pointer to the nearest point on the graph.
+           *
+           * @sample {highcharts} highcharts/plotoptions/series-events-click/
+           *         Alert click info
+           * @sample {highstock} stock/plotoptions/series-events-click/
+           *         Alert click info
+           * @sample {highmaps} maps/plotoptions/series-events-click/
+           *         Display click info in subtitle
+           *
+           * @type      {Highcharts.SeriesClickCallbackFunction}
+           * @context   Highcharts.Series
+           * @apioption plotOptions.series.events.click
+           */
+          /**
+           * Fires when the series is hidden after chart generation time, either
+           * by clicking the legend item or by calling `.hide()`.
+           *
+           * @sample {highcharts} highcharts/plotoptions/series-events-hide/
+           *         Alert when the series is hidden by clicking the legend item
+           *
+           * @type      {Highcharts.SeriesHideCallbackFunction}
+           * @since     1.2.0
+           * @context   Highcharts.Series
+           * @apioption plotOptions.series.events.hide
+           */
+          /**
+           * Fires when the legend item belonging to the series is clicked. One
+           * parameter, `event`, is passed to the function. The default action
+           * is to toggle the visibility of the series. This can be prevented
+           * by returning `false` or calling `event.preventDefault()`.
+           *
+           * @sample {highcharts} highcharts/plotoptions/series-events-legenditemclick/
+           *         Confirm hiding and showing
+           *
+           * @type      {Highcharts.SeriesLegendItemClickCallbackFunction}
+           * @context   Highcharts.Series
+           * @apioption plotOptions.series.events.legendItemClick
+           */
+          /**
+           * Fires when the mouse leaves the graph. One parameter, `event`, is
+           * passed to the function, containing common event information. If the
+           * [stickyTracking](#plotOptions.series) option is true, `mouseOut`
+           * doesn't happen before the mouse enters another graph or leaves the
+           * plot area.
+           *
+           * @sample {highcharts} highcharts/plotoptions/series-events-mouseover-sticky/
+           *         With sticky tracking by default
+           * @sample {highcharts} highcharts/plotoptions/series-events-mouseover-no-sticky/
+           *         Without sticky tracking
+           *
+           * @type      {Highcharts.SeriesMouseOutCallbackFunction}
+           * @context   Highcharts.Series
+           * @apioption plotOptions.series.events.mouseOut
+           */
+          /**
+           * Fires when the mouse enters the graph. One parameter, `event`, is
+           * passed to the function, containing common event information.
+           *
+           * @sample {highcharts} highcharts/plotoptions/series-events-mouseover-sticky/
+           *         With sticky tracking by default
+           * @sample {highcharts} highcharts/plotoptions/series-events-mouseover-no-sticky/
+           *         Without sticky tracking
+           *
+           * @type      {Highcharts.SeriesMouseOverCallbackFunction}
+           * @context   Highcharts.Series
+           * @apioption plotOptions.series.events.mouseOver
+           */
+          /**
+           * Fires when the series is shown after chart generation time, either
+           * by clicking the legend item or by calling `.show()`.
+           *
+           * @sample {highcharts} highcharts/plotoptions/series-events-show/
+           *         Alert when the series is shown by clicking the legend item.
+           *
+           * @type      {Highcharts.SeriesShowCallbackFunction}
+           * @since     1.2.0
+           * @context   Highcharts.Series
+           * @apioption plotOptions.series.events.show
+           */
+          /**
+           * Options for the point markers of line-like series. Properties like
+           * `fillColor`, `lineColor` and `lineWidth` define the visual appearance
+           * of the markers. Other series types, like column series, don't have
+           * markers, but have visual options on the series level instead.
+           *
+           * In styled mode, the markers can be styled with the
+           * `.highcharts-point`, `.highcharts-point-hover` and
+           * `.highcharts-point-select` class names.
+           *
+           * @declare Highcharts.PointMarkerOptionsObject
+           *
+           * @private
+           */
+          marker: {
+            /**
+             * Enable or disable the point marker. If `undefined`, the markers
+             * are hidden when the data is dense, and shown for more widespread
+             * data points.
+             *
+             * @sample {highcharts} highcharts/plotoptions/series-marker-enabled/
+             *         Disabled markers
+             * @sample {highcharts} highcharts/plotoptions/series-marker-enabled-false/
+             *         Disabled in normal state but enabled on hover
+             * @sample {highstock} stock/plotoptions/series-marker/
+             *         Enabled markers
+             *
+             * @type      {boolean}
+             * @default   {highcharts} undefined
+             * @default   {highstock} false
+             * @apioption plotOptions.series.marker.enabled
              */
             /**
-             * Fires when the checkbox next to the point name in the legend is
-             * clicked. One parameter, event, is passed to the function. The state
-             * of the checkbox is found by event.checked. The checked item is found
-             * by event.item. Return false to prevent the default action which is to
-             * toggle the select state of the series.
+             * The threshold for how dense the point markers should be before
+             * they are hidden, given that `enabled` is not defined. The number
+             * indicates the horizontal distance between the two closest points
+             * in the series, as multiples of the `marker.radius`. In other
+             * words, the default value of 2 means points are hidden if
+             * overlapping horizontally.
              *
-             * @sample {highcharts} highcharts/plotoptions/series-events-checkboxclick/
-             *         Alert checkbox status
+             * @sample highcharts/plotoptions/series-marker-enabledthreshold
+             *         A higher threshold
              *
-             * @type      {Function}
-             * @since     1.2.0
-             * @product   highcharts
-             * @context   Highcharts.Point
-             * @apioption plotOptions.pie.events.checkboxClick
+             * @since 6.0.5
              */
+            enabledThreshold: 2,
             /**
-             * Fires when the legend item belonging to the pie point (slice) is
-             * clicked. The `this` keyword refers to the point itself. One
-             * parameter, `event`, is passed to the function, containing common
-             * event information. The default action is to toggle the visibility of
-             * the point. This can be prevented by calling `event.preventDefault()`.
+             * The fill color of the point marker. When `undefined`, the series'
+             * or point's color is used.
              *
-             * @sample {highcharts} highcharts/plotoptions/pie-point-events-legenditemclick/
-             *         Confirm toggle visibility
+             * @sample {highcharts} highcharts/plotoptions/series-marker-fillcolor/
+             *         White fill
              *
-             * @type      {Highcharts.PointLegendItemClickCallbackFunction}
-             * @since     1.2.0
-             * @product   highcharts
-             * @apioption plotOptions.pie.point.events.legendItemClick
+             * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+             * @apioption plotOptions.series.marker.fillColor
              */
             /**
-             * The center of the pie chart relative to the plot area. Can be
-             * percentages or pixel values. The default behaviour (as of 3.0) is to
-             * center the pie so that all slices and data labels are within the plot
-             * area. As a consequence, the pie may actually jump around in a chart
-             * with dynamic values, as the data labels move. In that case, the
-             * center should be explicitly set, for example to `["50%", "50%"]`.
-             *
-             * @sample {highcharts} highcharts/plotoptions/pie-center/
-             *         Centered at 100, 100
-             *
-             * @type    {Array<(number|string|null),(number|string|null)>}
-             * @default [null, null]
-             * @product highcharts
+             * Image markers only. Set the image width explicitly. When using
+             * this option, a `width` must also be set.
              *
-             * @private
+             * @sample {highcharts} highcharts/plotoptions/series-marker-width-height/
+             *         Fixed width and height
+             * @sample {highstock} highcharts/plotoptions/series-marker-width-height/
+             *         Fixed width and height
+             *
+             * @type      {number}
+             * @since     4.0.4
+             * @apioption plotOptions.series.marker.height
              */
-            center: [null, null],
             /**
-             * The color of the pie series. A pie series is represented as an empty
-             * circle if the total sum of its values is 0. Use this property to
-             * define the color of its border.
+             * The color of the point marker's outline. When `undefined`, the
+             * series' or point's color is used.
              *
-             * In styled mode, the color can be defined by the
-             * [colorIndex](#plotOptions.series.colorIndex) option. Also, the series
-             * color can be set with the `.highcharts-series`,
-             * `.highcharts-color-{n}`, `.highcharts-{type}-series` or
-             * `.highcharts-series-{n}` class, or individual classes given by the
-             * `className` option.
+             * @sample {highcharts} highcharts/plotoptions/series-marker-fillcolor/
+             *         Inherit from series color (undefined)
              *
-             * @sample {highcharts} highcharts/plotoptions/pie-emptyseries/
-             *         Empty pie series
+             * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+             */
+            lineColor: "#ffffff",
+            /**
+             * The width of the point marker's outline.
              *
-             * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-             * @default   #cccccc
-             * @apioption plotOptions.pie.color
+             * @sample {highcharts} highcharts/plotoptions/series-marker-fillcolor/
+             *         2px blue marker
              */
+            lineWidth: 0,
             /**
-             * @product highcharts
+             * The radius of the point marker.
              *
-             * @private
+             * @sample {highcharts} highcharts/plotoptions/series-marker-radius/
+             *         Bigger markers
+             *
+             * @default {highstock} 2
              */
-            clip: false,
+            radius: 4,
             /**
-             * @ignore-option
+             * A predefined shape or symbol for the marker. When undefined, the
+             * symbol is pulled from options.symbols. Other possible values are
+             * `'circle'`, `'square'`,`'diamond'`, `'triangle'` and
+             * `'triangle-down'`.
              *
-             * @private
+             * Additionally, the URL to a graphic can be given on this form:
+             * `'url(graphic.png)'`. Note that for the image to be applied to
+             * exported charts, its URL needs to be accessible by the export
+             * server.
+             *
+             * Custom callbacks for symbol path generation can also be added to
+             * `Highcharts.SVGRenderer.prototype.symbols`. The callback is then
+             * used by its method name, as shown in the demo.
+             *
+             * @sample {highcharts} highcharts/plotoptions/series-marker-symbol/
+             *         Predefined, graphic and custom markers
+             * @sample {highstock} highcharts/plotoptions/series-marker-symbol/
+             *         Predefined, graphic and custom markers
+             *
+             * @type      {string}
+             * @apioption plotOptions.series.marker.symbol
              */
-            colorByPoint: true,
             /**
-             * A series specific or series type specific color set to use instead
-             * of the global [colors](#colors).
+             * Image markers only. Set the image width explicitly. When using
+             * this option, a `height` must also be set.
              *
-             * @sample {highcharts} highcharts/demo/pie-monochrome/
-             *         Set default colors for all pies
+             * @sample {highcharts} highcharts/plotoptions/series-marker-width-height/
+             *         Fixed width and height
+             * @sample {highstock} highcharts/plotoptions/series-marker-width-height/
+             *         Fixed width and height
              *
-             * @type      {Array<Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject>}
-             * @since     3.0
-             * @product   highcharts
-             * @apioption plotOptions.pie.colors
+             * @type      {number}
+             * @since     4.0.4
+             * @apioption plotOptions.series.marker.width
              */
             /**
-             * @declare   Highcharts.SeriesPieDataLabelsOptionsObject
-             * @extends   plotOptions.series.dataLabels
-             * @excluding align, allowOverlap, inside, staggerLines, step
-             * @private
+             * States for a single point marker.
+             *
+             * @declare Highcharts.PointStatesOptionsObject
              */
-            dataLabels: {
+            states: {
+              /**
+               * The normal state of a single point marker. Currently only
+               * used for setting animation when returning to normal state
+               * from hover.
+               *
+               * @declare Highcharts.PointStatesNormalOptionsObject
+               */
+              normal: {
+                /**
+                 * Animation when returning to normal state after hovering.
+                 *
+                 * @type {boolean|Partial<Highcharts.AnimationOptionsObject>}
+                 */
+                animation: true,
+              },
+              /**
+               * The hover state for a single point marker.
+               *
+               * @declare Highcharts.PointStatesHoverOptionsObject
+               */
+              hover: {
+                /**
+                 * Animation when hovering over the marker.
+                 *
+                 * @type {boolean|Partial<Highcharts.AnimationOptionsObject>}
+                 */
+                animation: {
+                  /** @internal */
+                  duration: 50,
+                },
                 /**
-                 * Alignment method for data labels. Possible values are:
-                 *
-                 * - `toPlotEdges`: Each label touches the nearest vertical edge of
-                 *   the plot area.
-                 *
-                 * - `connectors`: Connectors have the same x position and the
-                 *   widest label of each half (left & right) touches the nearest
-                 *   vertical edge of the plot area.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/pie-datalabels-alignto-connectors/
-                 *         alignTo: connectors
-                 * @sample {highcharts} highcharts/plotoptions/pie-datalabels-alignto-plotedges/
-                 *         alignTo: plotEdges
+                 * Enable or disable the point marker.
                  *
-                 * @type      {string}
-                 * @since     7.0.0
-                 * @product   highcharts
-                 * @apioption plotOptions.pie.dataLabels.alignTo
+                 * @sample {highcharts} highcharts/plotoptions/series-marker-states-hover-enabled/
+                 *         Disabled hover state
                  */
-                allowOverlap: true,
+                enabled: true,
                 /**
-                 * The color of the line connecting the data label to the pie slice.
-                 * The default color is the same as the point's color.
-                 *
-                 * In styled mode, the connector stroke is given in the
-                 * `.highcharts-data-label-connector` class.
-                 *
-                 * @sample {highcharts} highcharts/plotoptions/pie-datalabels-connectorcolor/
-                 *         Blue connectors
-                 * @sample {highcharts} highcharts/css/pie-point/
-                 *         Styled connectors
+                 * The fill color of the marker in hover state. When
+                 * `undefined`, the series' or point's fillColor for normal
+                 * state is used.
                  *
                  * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-                 * @since     2.1
-                 * @product   highcharts
-                 * @apioption plotOptions.pie.dataLabels.connectorColor
+                 * @apioption plotOptions.series.marker.states.hover.fillColor
                  */
                 /**
-                 * The distance from the data label to the connector. Note that
-                 * data labels also have a default `padding`, so in order for the
-                 * connector to touch the text, the `padding` must also be 0.
+                 * The color of the point marker's outline. When
+                 * `undefined`, the series' or point's lineColor for normal
+                 * state is used.
                  *
-                 * @sample {highcharts} highcharts/plotoptions/pie-datalabels-connectorpadding/
-                 *         No padding
+                 * @sample {highcharts} highcharts/plotoptions/series-marker-states-hover-linecolor/
+                 *         White fill color, black line color
                  *
-                 * @since   2.1
-                 * @product highcharts
+                 * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+                 * @apioption plotOptions.series.marker.states.hover.lineColor
                  */
-                connectorPadding: 5,
                 /**
-                 * Specifies the method that is used to generate the connector path.
-                 * Highcharts provides 3 built-in connector shapes: `'fixedOffset'`
-                 * (default), `'straight'` and `'crookedLine'`. Using
-                 * `'crookedLine'` has the most sense (in most of the cases) when
-                 * `'alignTo'` is set.
+                 * The width of the point marker's outline. When
+                 * `undefined`, the series' or point's lineWidth for normal
+                 * state is used.
                  *
-                 * Users can provide their own method by passing a function instead
-                 * of a String. 3 arguments are passed to the callback:
+                 * @sample {highcharts} highcharts/plotoptions/series-marker-states-hover-linewidth/
+                 *         3px line width
                  *
-                 * - Object that holds the information about the coordinates of the
-                 *   label (`x` & `y` properties) and how the label is located in
-                 *   relation to the pie (`alignment` property). `alignment` can by
-                 *   one of the following:
-                 *   `'left'` (pie on the left side of the data label),
-                 *   `'right'` (pie on the right side of the data label) or
-                 *   `'center'` (data label overlaps the pie).
-                 *
-                 * - Object that holds the information about the position of the
-                 *   connector. Its `touchingSliceAt`  porperty tells the position
-                 *   of the place where the connector touches the slice.
-                 *
-                 * - Data label options
-                 *
-                 * The function has to return an SVG path definition in array form
-                 * (see the example).
+                 * @type      {number}
+                 * @apioption plotOptions.series.marker.states.hover.lineWidth
+                 */
+                /**
+                 * The radius of the point marker. In hover state, it
+                 * defaults to the normal state's radius + 2 as per the
+                 * [radiusPlus](#plotOptions.series.marker.states.hover.radiusPlus)
+                 * option.
                  *
-                 * @sample {highcharts} highcharts/plotoptions/pie-datalabels-connectorshape-string/
-                 *         connectorShape is a String
-                 * @sample {highcharts} highcharts/plotoptions/pie-datalabels-connectorshape-function/
-                 *         connectorShape is a function
+                 * @sample {highcharts} highcharts/plotoptions/series-marker-states-hover-radius/
+                 *         10px radius
                  *
-                 * @type    {string|Function}
-                 * @since   7.0.0
-                 * @product highcharts
+                 * @type      {number}
+                 * @apioption plotOptions.series.marker.states.hover.radius
                  */
-                connectorShape: 'fixedOffset',
                 /**
-                 * The width of the line connecting the data label to the pie slice.
-                 *
-                 * In styled mode, the connector stroke width is given in the
-                 * `.highcharts-data-label-connector` class.
+                 * The number of pixels to increase the radius of the
+                 * hovered point.
                  *
-                 * @sample {highcharts} highcharts/plotoptions/pie-datalabels-connectorwidth-disabled/
-                 *         Disable the connector
-                 * @sample {highcharts} highcharts/css/pie-point/
-                 *         Styled connectors
+                 * @sample {highcharts} highcharts/plotoptions/series-states-hover-linewidthplus/
+                 *         5 pixels greater radius on hover
+                 * @sample {highstock} highcharts/plotoptions/series-states-hover-linewidthplus/
+                 *         5 pixels greater radius on hover
                  *
-                 * @type      {number}
-                 * @default   1
-                 * @since     2.1
-                 * @product   highcharts
-                 * @apioption plotOptions.pie.dataLabels.connectorWidth
+                 * @since 4.0.3
                  */
+                radiusPlus: 2,
                 /**
-                 * Works only if `connectorShape` is `'crookedLine'`. It defines how
-                 * far from the vertical plot edge the coonnector path should be
-                 * crooked.
+                 * The additional line width for a hovered point.
                  *
-                 * @sample {highcharts} highcharts/plotoptions/pie-datalabels-crookdistance/
-                 *         crookDistance set to 90%
+                 * @sample {highcharts} highcharts/plotoptions/series-states-hover-linewidthplus/
+                 *         2 pixels wider on hover
+                 * @sample {highstock} highcharts/plotoptions/series-states-hover-linewidthplus/
+                 *         2 pixels wider on hover
                  *
-                 * @since   7.0.0
-                 * @product highcharts
+                 * @since 4.0.3
                  */
-                crookDistance: '70%',
+                lineWidthPlus: 1,
+              },
+              /**
+               * The appearance of the point marker when selected. In order to
+               * allow a point to be selected, set the
+               * `series.allowPointSelect` option to true.
+               *
+               * @declare Highcharts.PointStatesSelectOptionsObject
+               */
+              select: {
                 /**
-                 * The distance of the data label from the pie's edge. Negative
-                 * numbers put the data label on top of the pie slices. Can also be
-                 * defined as a percentage of pie's radius. Connectors are only
-                 * shown for data labels outside the pie.
+                 * Enable or disable visible feedback for selection.
                  *
-                 * @sample {highcharts} highcharts/plotoptions/pie-datalabels-distance/
-                 *         Data labels on top of the pie
+                 * @sample {highcharts} highcharts/plotoptions/series-marker-states-select-enabled/
+                 *         Disabled select state
                  *
-                 * @type    {number|string}
-                 * @since   2.1
-                 * @product highcharts
+                 * @type      {boolean}
+                 * @default   true
+                 * @apioption plotOptions.series.marker.states.select.enabled
                  */
-                distance: 30,
-                enabled: true,
                 /**
-                 * A
-                 * [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting)
-                 * for the data label. Available variables are the same as for
-                 * `formatter`.
+                 * The radius of the point marker. In hover state, it
+                 * defaults to the normal state's radius + 2.
                  *
-                 * @sample {highcharts} highcharts/plotoptions/series-datalabels-format/
-                 *         Add a unit
+                 * @sample {highcharts} highcharts/plotoptions/series-marker-states-select-radius/
+                 *         10px radius for selected points
                  *
-                 * @type      {string}
-                 * @default   undefined
-                 * @since     3.0
-                 * @apioption plotOptions.pie.dataLabels.format
+                 * @type      {number}
+                 * @apioption plotOptions.series.marker.states.select.radius
                  */
-                // eslint-disable-next-line valid-jsdoc
                 /**
-                 * Callback JavaScript function to format the data label. Note that
-                 * if a `format` is defined, the format takes precedence and the
-                 * formatter is ignored.
+                 * The fill color of the point marker.
                  *
-                 * @type {Highcharts.DataLabelsFormatterCallbackFunction}
-                 * @default function () { return this.point.isNull ? void 0 : this.point.name; }
+                 * @sample {highcharts} highcharts/plotoptions/series-marker-states-select-fillcolor/
+                 *         Solid red discs for selected points
+                 *
+                 * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
                  */
-                formatter: function () {
-                    return this.point.isNull ? void 0 : this.point.name;
-                },
+                fillColor: "#cccccc",
                 /**
-                 * Whether to render the connector as a soft arc or a line with
-                 * sharp break. Works only if `connectorShape` equals to
-                 * `fixedOffset`.
+                 * The color of the point marker's outline. When
+                 * `undefined`, the series' or point's color is used.
                  *
-                 * @sample {highcharts} highcharts/plotoptions/pie-datalabels-softconnector-true/
-                 *         Soft
-                 * @sample {highcharts} highcharts/plotoptions/pie-datalabels-softconnector-false/
-                 *         Non soft
+                 * @sample {highcharts} highcharts/plotoptions/series-marker-states-select-linecolor/
+                 *         Red line color for selected points
                  *
-                 * @since   2.1.7
-                 * @product highcharts
+                 * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
                  */
-                softConnector: true,
+                lineColor: "#000000",
                 /**
-                 * @sample {highcharts} highcharts/plotoptions/pie-datalabels-overflow
-                 *         Long labels truncated with an ellipsis
-                 * @sample {highcharts} highcharts/plotoptions/pie-datalabels-overflow-wrap
-                 *         Long labels are wrapped
+                 * The width of the point marker's outline.
                  *
-                 * @type      {Highcharts.CSSObject}
-                 * @apioption plotOptions.pie.dataLabels.style
+                 * @sample {highcharts} highcharts/plotoptions/series-marker-states-select-linewidth/
+                 *         3px line width for selected points
                  */
-                x: 0
+                lineWidth: 2,
+              },
             },
+          },
+          /**
+           * Properties for each single point.
+           *
+           * @declare Highcharts.PlotSeriesPointOptions
+           *
+           * @private
+           */
+          point: {
+            /**
+             * Fires when a point is clicked. One parameter, `event`, is passed
+             * to the function, containing common event information.
+             *
+             * If the `series.allowPointSelect` option is true, the default
+             * action for the point's click event is to toggle the point's
+             * select state. Returning `false` cancels this action.
+             *
+             * @sample {highcharts} highcharts/plotoptions/series-point-events-click/
+             *         Click marker to alert values
+             * @sample {highcharts} highcharts/plotoptions/series-point-events-click-column/
+             *         Click column
+             * @sample {highcharts} highcharts/plotoptions/series-point-events-click-url/
+             *         Go to URL
+             * @sample {highmaps} maps/plotoptions/series-point-events-click/
+             *         Click marker to display values
+             * @sample {highmaps} maps/plotoptions/series-point-events-click-url/
+             *         Go to URL
+             *
+             * @type      {Highcharts.PointClickCallbackFunction}
+             * @context   Highcharts.Point
+             * @apioption plotOptions.series.point.events.click
+             */
             /**
-             * If the total sum of the pie's values is 0, the series is represented
-             * as an empty circle . The `fillColor` option defines the color of that
-             * circle. Use [pie.borderWidth](#plotOptions.pie.borderWidth) to set
-             * the border thickness.
+             * Fires when the mouse leaves the area close to the point. One
+             * parameter, `event`, is passed to the function, containing common
+             * event information.
              *
-             * @sample {highcharts} highcharts/plotoptions/pie-emptyseries/
-             *         Empty pie series
+             * @sample {highcharts} highcharts/plotoptions/series-point-events-mouseover/
+             *         Show values in the chart's corner on mouse over
              *
-             * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-             * @private
+             * @type      {Highcharts.PointMouseOutCallbackFunction}
+             * @context   Highcharts.Point
+             * @apioption plotOptions.series.point.events.mouseOut
+             */
+            /**
+             * Fires when the mouse enters the area close to the point. One
+             * parameter, `event`, is passed to the function, containing common
+             * event information.
+             *
+             * @sample {highcharts} highcharts/plotoptions/series-point-events-mouseover/
+             *         Show values in the chart's corner on mouse over
+             *
+             * @type      {Highcharts.PointMouseOverCallbackFunction}
+             * @context   Highcharts.Point
+             * @apioption plotOptions.series.point.events.mouseOver
+             */
+            /**
+             * Fires when the point is removed using the `.remove()` method. One
+             * parameter, `event`, is passed to the function. Returning `false`
+             * cancels the operation.
+             *
+             * @sample {highcharts} highcharts/plotoptions/series-point-events-remove/
+             *         Remove point and confirm
+             *
+             * @type      {Highcharts.PointRemoveCallbackFunction}
+             * @since     1.2.0
+             * @context   Highcharts.Point
+             * @apioption plotOptions.series.point.events.remove
+             */
+            /**
+             * Fires when the point is selected either programmatically or
+             * following a click on the point. One parameter, `event`, is passed
+             * to the function. Returning `false` cancels the operation.
+             *
+             * @sample {highcharts} highcharts/plotoptions/series-point-events-select/
+             *         Report the last selected point
+             * @sample {highmaps} maps/plotoptions/series-allowpointselect/
+             *         Report select and unselect
+             *
+             * @type      {Highcharts.PointSelectCallbackFunction}
+             * @since     1.2.0
+             * @context   Highcharts.Point
+             * @apioption plotOptions.series.point.events.select
+             */
+            /**
+             * Fires when the point is unselected either programmatically or
+             * following a click on the point. One parameter, `event`, is passed
+             * to the function.
+             *  Returning `false` cancels the operation.
+             *
+             * @sample {highcharts} highcharts/plotoptions/series-point-events-unselect/
+             *         Report the last unselected point
+             * @sample {highmaps} maps/plotoptions/series-allowpointselect/
+             *         Report select and unselect
+             *
+             * @type      {Highcharts.PointUnselectCallbackFunction}
+             * @since     1.2.0
+             * @context   Highcharts.Point
+             * @apioption plotOptions.series.point.events.unselect
+             */
+            /**
+             * Fires when the point is updated programmatically through the
+             * `.update()` method. One parameter, `event`, is passed to the
+             * function. The new point options can be accessed through
+             * `event.options`. Returning `false` cancels the operation.
+             *
+             * @sample {highcharts} highcharts/plotoptions/series-point-events-update/
+             *         Confirm point updating
+             *
+             * @type      {Highcharts.PointUpdateCallbackFunction}
+             * @since     1.2.0
+             * @context   Highcharts.Point
+             * @apioption plotOptions.series.point.events.update
              */
-            fillColor: void 0,
             /**
-             * The end angle of the pie in degrees where 0 is top and 90 is right.
-             * Defaults to `startAngle` plus 360.
+             * Events for each single point.
              *
-             * @sample {highcharts} highcharts/demo/pie-semi-circle/
-             *         Semi-circle donut
+             * @declare Highcharts.PointEventsOptionsObject
+             */
+            events: {},
+          },
+          /**
+           * Options for the series data labels, appearing next to each data
+           * point.
+           *
+           * Since v6.2.0, multiple data labels can be applied to each single
+           * point by defining them as an array of configs.
+           *
+           * In styled mode, the data labels can be styled with the
+           * `.highcharts-data-label-box` and `.highcharts-data-label` class names
+           * ([see example](https://www.highcharts.com/samples/highcharts/css/series-datalabels)).
+           *
+           * @sample {highcharts} highcharts/plotoptions/series-datalabels-enabled
+           *         Data labels enabled
+           * @sample {highcharts} highcharts/plotoptions/series-datalabels-multiple
+           *         Multiple data labels on a bar series
+           * @sample {highcharts} highcharts/css/series-datalabels
+           *         Style mode example
+           *
+           * @type    {*|Array<*>}
+           * @product highcharts highstock highmaps gantt
+           *
+           * @private
+           */
+          dataLabels: {
+            /**
+             * Enable or disable the initial animation when a series is
+             * displayed for the `dataLabels`. The animation can also be set as
+             * a configuration object. Please note that this option only
+             * applies to the initial animation.
+             * For other animations, see [chart.animation](#chart.animation)
+             * and the animation parameter under the API methods.
+             * The following properties are supported:
+             *
+             * - `defer`: The animation delay time in milliseconds.
+             *
+             * @sample {highcharts} highcharts/plotoptions/animation-defer/
+             *          Animation defer settings
+             *
+             * @type      {boolean|Partial<Highcharts.AnimationOptionsObject>}
+             * @since     8.2.0
+             * @apioption plotOptions.series.dataLabels.animation
+             */
+            animation: {},
+            /**
+             * The animation delay time in milliseconds.
+             * Set to `0` renders dataLabel immediately.
+             * As `undefined` inherits defer time from the [series.animation.defer](#plotOptions.series.animation.defer).
              *
              * @type      {number}
-             * @since     1.3.6
-             * @product   highcharts
-             * @apioption plotOptions.pie.endAngle
+             * @since     8.2.0
+             * @apioption plotOptions.series.dataLabels.animation.defer
              */
             /**
-             * Equivalent to [chart.ignoreHiddenSeries](#chart.ignoreHiddenSeries),
-             * this option tells whether the series shall be redrawn as if the
-             * hidden point were `null`.
+             * The alignment of the data label compared to the point. If
+             * `right`, the right side of the label should be touching the
+             * point. For points with an extent, like columns, the alignments
+             * also dictates how to align it inside the box, as given with the
+             * [inside](#plotOptions.column.dataLabels.inside)
+             * option. Can be one of `left`, `center` or `right`.
              *
-             * The default value changed from `false` to `true` with Highcharts
-             * 3.0.
+             * @sample {highcharts} highcharts/plotoptions/series-datalabels-align-left/
+             *         Left aligned
+             * @sample {highcharts} highcharts/plotoptions/bar-datalabels-align-inside-bar/
+             *         Data labels inside the bar
              *
-             * @sample {highcharts} highcharts/plotoptions/pie-ignorehiddenpoint/
-             *         True, the hiddden point is ignored
+             * @type {Highcharts.AlignValue|null}
+             */
+            align: "center",
+            /**
+             * Whether to allow data labels to overlap. To make the labels less
+             * sensitive for overlapping, the
+             * [dataLabels.padding](#plotOptions.series.dataLabels.padding)
+             * can be set to 0.
              *
-             * @since   2.3.0
-             * @product highcharts
+             * @sample {highcharts} highcharts/plotoptions/series-datalabels-allowoverlap-false/
+             *         Don't allow overlap
              *
-             * @private
+             * @type      {boolean}
+             * @default   false
+             * @since     4.1.0
+             * @apioption plotOptions.series.dataLabels.allowOverlap
              */
-            ignoreHiddenPoint: true,
             /**
-             * @ignore-option
+             * The background color or gradient for the data label.
              *
-             * @private
+             * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/
+             *         Data labels box options
+             * @sample {highmaps} maps/plotoptions/series-datalabels-box/
+             *         Data labels box options
+             *
+             * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+             * @since     2.2.1
+             * @apioption plotOptions.series.dataLabels.backgroundColor
              */
-            inactiveOtherPoints: true,
             /**
-             * The size of the inner diameter for the pie. A size greater than 0
-             * renders a donut chart. Can be a percentage or pixel value.
-             * Percentages are relative to the pie size. Pixel values are given as
-             * integers.
+             * The border color for the data label. Defaults to `undefined`.
              *
+             * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/
+             *         Data labels box options
              *
-             * Note: in Highcharts < 4.1.2, the percentage was relative to the plot
-             * area, not the pie size.
+             * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+             * @since     2.2.1
+             * @apioption plotOptions.series.dataLabels.borderColor
+             */
+            /**
+             * The border radius in pixels for the data label.
              *
-             * @sample {highcharts} highcharts/plotoptions/pie-innersize-80px/
-             *         80px inner size
-             * @sample {highcharts} highcharts/plotoptions/pie-innersize-50percent/
-             *         50% of the plot area
-             * @sample {highcharts} highcharts/demo/3d-pie-donut/
-             *         3D donut
+             * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/
+             *         Data labels box options
+             * @sample {highmaps} maps/plotoptions/series-datalabels-box/
+             *         Data labels box options
              *
-             * @type      {number|string}
+             * @type      {number}
              * @default   0
-             * @since     2.0
-             * @product   highcharts
-             * @apioption plotOptions.pie.innerSize
+             * @since     2.2.1
+             * @apioption plotOptions.series.dataLabels.borderRadius
              */
             /**
-             * @ignore-option
+             * The border width in pixels for the data label.
              *
-             * @private
+             * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/
+             *         Data labels box options
+             *
+             * @type      {number}
+             * @default   0
+             * @since     2.2.1
+             * @apioption plotOptions.series.dataLabels.borderWidth
              */
-            legendType: 'point',
             /**
-             * @ignore-option
+             * A class name for the data label. Particularly in styled mode,
+             * this can be used to give each series' or point's data label
+             * unique styling. In addition to this option, a default color class
+             * name is added so that we can give the labels a contrast text
+             * shadow.
              *
-             * @private
+             * @sample {highcharts} highcharts/css/data-label-contrast/
+             *         Contrast text shadow
+             * @sample {highcharts} highcharts/css/series-datalabels/
+             *         Styling by CSS
+             *
+             * @type      {string}
+             * @since     5.0.0
+             * @apioption plotOptions.series.dataLabels.className
              */
-            marker: null,
             /**
-             * The minimum size for a pie in response to auto margins. The pie will
-             * try to shrink to make room for data labels in side the plot area,
-             *  but only to this size.
+             * The text color for the data labels. Defaults to `undefined`. For
+             * certain series types, like column or map, the data labels can be
+             * drawn inside the points. In this case the data label will be
+             * drawn with maximum contrast by default. Additionally, it will be
+             * given a `text-outline` style with the opposite color, to further
+             * increase the contrast. This can be overridden by setting the
+             * `text-outline` style to `none` in the `dataLabels.style` option.
              *
-             * @type      {number|string}
-             * @default   80
-             * @since     3.0
-             * @product   highcharts
-             * @apioption plotOptions.pie.minSize
+             * @sample {highcharts} highcharts/plotoptions/series-datalabels-color/
+             *         Red data labels
+             * @sample {highmaps} maps/demo/color-axis/
+             *         White data labels
+             *
+             * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+             * @apioption plotOptions.series.dataLabels.color
              */
             /**
-             * The diameter of the pie relative to the plot area. Can be a
-             * percentage or pixel value. Pixel values are given as integers. The
-             * default behaviour (as of 3.0) is to scale to the plot area and give
-             * room for data labels within the plot area.
-             * [slicedOffset](#plotOptions.pie.slicedOffset) is also included in the
-             * default size calculation. As a consequence, the size of the pie may
-             * vary when points are updated and data labels more around. In that
-             * case it is best to set a fixed value, for example `"75%"`.
-             *
-             * @sample {highcharts} highcharts/plotoptions/pie-size/
-             *         Smaller pie
-             *
-             * @type    {number|string|null}
-             * @product highcharts
+             * Whether to hide data labels that are outside the plot area. By
+             * default, the data label is moved inside the plot area according
+             * to the
+             * [overflow](#plotOptions.series.dataLabels.overflow)
+             * option.
              *
-             * @private
+             * @type      {boolean}
+             * @default   true
+             * @since     2.3.3
+             * @apioption plotOptions.series.dataLabels.crop
              */
-            size: null,
             /**
-             * Whether to display this particular series or series type in the
-             * legend. Since 2.1, pies are not shown in the legend by default.
+             * Whether to defer displaying the data labels until the initial
+             * series animation has finished. Setting to `false` renders the
+             * data label immediately. If set to `true` inherits the defer
+             * time set in [plotOptions.series.animation](#plotOptions.series.animation).
              *
-             * @sample {highcharts} highcharts/plotoptions/series-showinlegend/
-             *         One series in the legend, one hidden
+             * @sample highcharts/plotoptions/animation-defer
+             *         Set defer time
              *
-             * @product highcharts
+             * @since     4.0.0
+             * @product   highcharts highstock gantt
+             */
+            defer: true,
+            /**
+             * Enable or disable the data labels.
              *
-             * @private
+             * @sample {highcharts} highcharts/plotoptions/series-datalabels-enabled/
+             *         Data labels enabled
+             * @sample {highmaps} maps/demo/color-axis/
+             *         Data labels enabled
+             *
+             * @type      {boolean}
+             * @default   false
+             * @apioption plotOptions.series.dataLabels.enabled
              */
-            showInLegend: false,
             /**
-             * If a point is sliced, moved out from the center, how many pixels
-             * should it be moved?.
+             * A declarative filter to control of which data labels to display.
+             * The declarative filter is designed for use when callback
+             * functions are not available, like when the chart options require
+             * a pure JSON structure or for use with graphical editors. For
+             * programmatic control, use the `formatter` instead, and return
+             * `undefined` to disable a single data label.
              *
-             * @sample {highcharts} highcharts/plotoptions/pie-slicedoffset-20/
-             *         20px offset
+             * @example
+             * filter: {
+             *     property: 'percentage',
+             *     operator: '>',
+             *     value: 4
+             * }
              *
-             * @product highcharts
+             * @sample {highcharts} highcharts/demo/pie-monochrome
+             *         Data labels filtered by percentage
              *
-             * @private
+             * @declare   Highcharts.DataLabelsFilterOptionsObject
+             * @since     6.0.3
+             * @apioption plotOptions.series.dataLabels.filter
+             */
+            /**
+             * The operator to compare by. Can be one of `>`, `<`, `>=`, `<=`,
+             * `==`, and `===`.
+             *
+             * @type       {string}
+             * @validvalue [">", "<", ">=", "<=", "==", "==="]
+             * @apioption  plotOptions.series.dataLabels.filter.operator
              */
-            slicedOffset: 10,
             /**
-             * The start angle of the pie slices in degrees where 0 is top and 90
-             * right.
+             * The point property to filter by. Point options are passed
+             * directly to properties, additionally there are `y` value,
+             * `percentage` and others listed under {@link Highcharts.Point}
+             * members.
              *
-             * @sample {highcharts} highcharts/plotoptions/pie-startangle-90/
-             *         Start from right
+             * @type      {string}
+             * @apioption plotOptions.series.dataLabels.filter.property
+             */
+            /**
+             * The value to compare against.
              *
              * @type      {number}
-             * @default   0
-             * @since     2.3.4
-             * @product   highcharts
-             * @apioption plotOptions.pie.startAngle
+             * @apioption plotOptions.series.dataLabels.filter.value
              */
             /**
-             * Sticky tracking of mouse events. When true, the `mouseOut` event
-             * on a series isn't triggered until the mouse moves over another
-             * series, or out of the plot area. When false, the `mouseOut` event on
-             * a series is triggered when the mouse leaves the area around the
-             * series'  graph or markers. This also implies the tooltip. When
-             * `stickyTracking` is false and `tooltip.shared` is false, the tooltip
-             * will be hidden when moving the mouse between series.
+             * A
+             * [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting)
+             * for the data label. Available variables are the same as for
+             * `formatter`.
+             *
+             * @sample {highcharts} highcharts/plotoptions/series-datalabels-format/
+             *         Add a unit
+             * @sample {highmaps} maps/plotoptions/series-datalabels-format/
+             *         Formatted value in the data label
+             *
+             * @type      {string}
+             * @default   y
+             * @default   point.value
+             * @since     3.0
+             * @apioption plotOptions.series.dataLabels.format
+             */
+            // eslint-disable-next-line valid-jsdoc
+            /**
+             * Callback JavaScript function to format the data label. Note that
+             * if a `format` is defined, the format takes precedence and the
+             * formatter is ignored.
              *
-             * @product highcharts
+             * @sample {highmaps} maps/plotoptions/series-datalabels-format/
+             *         Formatted value
              *
-             * @private
+             * @type {Highcharts.DataLabelsFormatterCallbackFunction}
              */
-            stickyTracking: false,
-            tooltip: {
-                followPointer: true
+            formatter: function () {
+              var numberFormatter = this.series.chart.numberFormatter;
+              return typeof this.y !== "number"
+                ? ""
+                : numberFormatter(this.y, -1);
             },
             /**
-             * The color of the border surrounding each slice. When `null`, the
-             * border takes the same color as the slice fill. This can be used
-             * together with a `borderWidth` to fill drawing gaps created by
-             * antialiazing artefacts in borderless pies.
-             *
-             * In styled mode, the border stroke is given in the `.highcharts-point`
-             * class.
-             *
-             * @sample {highcharts} highcharts/plotoptions/pie-bordercolor-black/
-             *         Black border
+             * For points with an extent, like columns or map areas, whether to
+             * align the data label inside the box or to the actual value point.
+             * Defaults to `false` in most cases, `true` in stacked columns.
              *
-             * @type    {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
-             * @default #ffffff
-             * @product highcharts
-             *
-             * @private
+             * @type      {boolean}
+             * @since     3.0
+             * @apioption plotOptions.series.dataLabels.inside
              */
-            borderColor: '#ffffff',
             /**
-             * The width of the border surrounding each slice.
-             *
-             * When setting the border width to 0, there may be small gaps between
-             * the slices due to SVG antialiasing artefacts. To work around this,
-             * keep the border width at 0.5 or 1, but set the `borderColor` to
-             * `null` instead.
-             *
-             * In styled mode, the border stroke width is given in the
-             * `.highcharts-point` class.
-             *
-             * @sample {highcharts} highcharts/plotoptions/pie-borderwidth/
-             *         3px border
+             * Format for points with the value of null. Works analogously to
+             * [format](#plotOptions.series.dataLabels.format). `nullFormat` can
+             * be applied only to series which support displaying null points.
              *
-             * @product highcharts
+             * @sample {highcharts} highcharts/plotoptions/series-datalabels-format/
+             *         Format data label and tooltip for null point.
              *
-             * @private
-             */
-            borderWidth: 1,
-            /**
-             * @ignore-options
-             * @private
+             * @type      {boolean|string}
+             * @since     7.1.0
+             * @apioption plotOptions.series.dataLabels.nullFormat
              */
-            lineWidth: void 0,
-            states: {
-                /**
-                 * @extends   plotOptions.series.states.hover
-                 * @excluding marker, lineWidth, lineWidthPlus
-                 * @product   highcharts
-                 */
-                hover: {
-                    /**
-                     * How much to brighten the point on interaction. Requires the
-                     * main color to be defined in hex or rgb(a) format.
-                     *
-                     * In styled mode, the hover brightness is by default replaced
-                     * by a fill-opacity given in the `.highcharts-point-hover`
-                     * class.
-                     *
-                     * @sample {highcharts} highcharts/plotoptions/pie-states-hover-brightness/
-                     *         Brightened by 0.5
-                     *
-                     * @product highcharts
-                     */
-                    brightness: 0.1
-                }
-            }
-        }, 
-        /* eslint-disable valid-jsdoc */
-        /**
-         * @lends seriesTypes.pie.prototype
-         */
-        {
-            isCartesian: false,
-            requireSorting: false,
-            directTouch: true,
-            noSharedTooltip: true,
-            trackerGroups: ['group', 'dataLabelsGroup'],
-            axisTypes: [],
-            pointAttribs: BaseSeries.seriesTypes.column.prototype.pointAttribs,
             /**
-             * Animate the pies in
+             * Callback JavaScript function that defines formatting for points
+             * with the value of null. Works analogously to
+             * [formatter](#plotOptions.series.dataLabels.formatter).
+             * `nullPointFormatter` can be applied only to series which support
+             * displaying null points.
              *
-             * @private
-             * @function Highcharts.seriesTypes.pie#animate
+             * @sample {highcharts} highcharts/plotoptions/series-datalabels-format/
+             *         Format data label and tooltip for null point.
              *
-             * @param {boolean} [init=false]
+             * @type      {Highcharts.DataLabelsFormatterCallbackFunction}
+             * @since     7.1.0
+             * @apioption plotOptions.series.dataLabels.nullFormatter
              */
-            animate: function (init) {
-                var series = this,
-                    points = series.points,
-                    startAngleRad = series.startAngleRad;
-                if (!init) {
-                    points.forEach(function (point) {
-                        var graphic = point.graphic,
-                            args = point.shapeArgs;
-                        if (graphic && args) {
-                            // start values
-                            graphic.attr({
-                                // animate from inner radius (#779)
-                                r: pick(point.startR, (series.center && series.center[3] / 2)),
-                                start: startAngleRad,
-                                end: startAngleRad
-                            });
-                            // animate
-                            graphic.animate({
-                                r: args.r,
-                                start: args.start,
-                                end: args.end
-                            }, series.options.animation);
-                        }
-                    });
-                }
-            },
-            // Define hasData function for non-cartesian series.
-            // Returns true if the series has points at all.
-            hasData: function () {
-                return !!this.processedXData.length; // != 0
-            },
             /**
-             * Recompute total chart sum and update percentages of points.
+             * How to handle data labels that flow outside the plot area. The
+             * default is `"justify"`, which aligns them inside the plot area.
+             * For columns and bars, this means it will be moved inside the bar.
+             * To display data labels outside the plot area, set `crop` to
+             * `false` and `overflow` to `"allow"`.
              *
-             * @private
-             * @function Highcharts.seriesTypes.pie#updateTotals
-             * @return {void}
+             * @type       {Highcharts.DataLabelsOverflowValue}
+             * @default    justify
+             * @since      3.0.6
+             * @apioption  plotOptions.series.dataLabels.overflow
              */
-            updateTotals: function () {
-                var i,
-                    total = 0,
-                    points = this.points,
-                    len = points.length,
-                    point,
-                    ignoreHiddenPoint = this.options.ignoreHiddenPoint;
-                // Get the total sum
-                for (i = 0; i < len; i++) {
-                    point = points[i];
-                    total += (ignoreHiddenPoint && !point.visible) ?
-                        0 :
-                        point.isNull ?
-                            0 :
-                            point.y;
-                }
-                this.total = total;
-                // Set each point's properties
-                for (i = 0; i < len; i++) {
-                    point = points[i];
-                    point.percentage =
-                        (total > 0 && (point.visible || !ignoreHiddenPoint)) ?
-                            point.y / total * 100 :
-                            0;
-                    point.total = total;
-                }
-            },
             /**
-             * Extend the generatePoints method by adding total and percentage
-             * properties to each point
+             * When either the `borderWidth` or the `backgroundColor` is set,
+             * this is the padding within the box.
              *
-             * @private
-             * @function Highcharts.seriesTypes.pie#generatePoints
-             * @return {void}
+             * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/
+             *         Data labels box options
+             * @sample {highmaps} maps/plotoptions/series-datalabels-box/
+             *         Data labels box options
+             *
+             * @since 2.2.1
              */
-            generatePoints: function () {
-                LineSeries.prototype.generatePoints.call(this);
-                this.updateTotals();
-            },
+            padding: 5,
             /**
-             * Utility for getting the x value from a given y, used for
-             * anticollision logic in data labels. Added point for using specific
-             * points' label distance.
-             * @private
+             * Aligns data labels relative to points. If `center` alignment is
+             * not possible, it defaults to `right`.
+             *
+             * @type      {Highcharts.AlignValue}
+             * @default   center
+             * @apioption plotOptions.series.dataLabels.position
              */
-            getX: function (y, left, point) {
-                var center = this.center, 
-                    // Variable pie has individual radius
-                    radius = this.radii ?
-                        this.radii[point.index] :
-                        center[2] / 2,
-                    angle,
-                    x;
-                angle = Math.asin(clamp((y - center[1]) / (radius + point.labelDistance), -1, 1));
-                x = center[0] +
-                    (left ? -1 : 1) *
-                        (Math.cos(angle) * (radius + point.labelDistance)) +
-                    (point.labelDistance > 0 ?
-                        (left ? -1 : 1) * this.options.dataLabels.padding :
-                        0);
-                return x;
-            },
             /**
-             * Do translation for pie slices
+             * Text rotation in degrees. Note that due to a more complex
+             * structure, backgrounds, borders and padding will be lost on a
+             * rotated data label.
              *
-             * @private
-             * @function Highcharts.seriesTypes.pie#translate
-             * @param {Array<number>} [positions]
-             * @return {void}
+             * @sample {highcharts} highcharts/plotoptions/series-datalabels-rotation/
+             *         Vertical labels
+             *
+             * @type      {number}
+             * @default   0
+             * @apioption plotOptions.series.dataLabels.rotation
              */
-            translate: function (positions) {
-                this.generatePoints();
-                var series = this,
-                    cumulative = 0,
-                    precision = 1000, // issue #172
-                    options = series.options,
-                    slicedOffset = options.slicedOffset,
-                    connectorOffset = slicedOffset + (options.borderWidth || 0),
-                    finalConnectorOffset,
-                    start,
-                    end,
-                    angle,
-                    radians = getStartAndEndRadians(options.startAngle,
-                    options.endAngle),
-                    startAngleRad = series.startAngleRad = radians.start,
-                    endAngleRad = series.endAngleRad = radians.end,
-                    circ = endAngleRad - startAngleRad, // 2 * Math.PI,
-                    points = series.points, 
-                    // the x component of the radius vector for a given point
-                    radiusX,
-                    radiusY,
-                    labelDistance = options.dataLabels.distance,
-                    ignoreHiddenPoint = options.ignoreHiddenPoint,
-                    i,
-                    len = points.length,
-                    point;
-                // Get positions - either an integer or a percentage string must be
-                // given. If positions are passed as a parameter, we're in a
-                // recursive loop for adjusting space for data labels.
-                if (!positions) {
-                    series.center = positions = series.getCenter();
-                }
-                // Calculate the geometry for each point
-                for (i = 0; i < len; i++) {
-                    point = points[i];
-                    // set start and end angle
-                    start = startAngleRad + (cumulative * circ);
-                    if (!ignoreHiddenPoint || point.visible) {
-                        cumulative += point.percentage / 100;
-                    }
-                    end = startAngleRad + (cumulative * circ);
-                    // set the shape
-                    point.shapeType = 'arc';
-                    point.shapeArgs = {
-                        x: positions[0],
-                        y: positions[1],
-                        r: positions[2] / 2,
-                        innerR: positions[3] / 2,
-                        start: Math.round(start * precision) / precision,
-                        end: Math.round(end * precision) / precision
-                    };
-                    // Used for distance calculation for specific point.
-                    point.labelDistance = pick((point.options.dataLabels &&
-                        point.options.dataLabels.distance), labelDistance);
-                    // Compute point.labelDistance if it's defined as percentage
-                    // of slice radius (#8854)
-                    point.labelDistance = relativeLength(point.labelDistance, point.shapeArgs.r);
-                    // Saved for later dataLabels distance calculation.
-                    series.maxLabelDistance = Math.max(series.maxLabelDistance || 0, point.labelDistance);
-                    // The angle must stay within -90 and 270 (#2645)
-                    angle = (end + start) / 2;
-                    if (angle > 1.5 * Math.PI) {
-                        angle -= 2 * Math.PI;
-                    }
-                    else if (angle < -Math.PI / 2) {
-                        angle += 2 * Math.PI;
-                    }
-                    // Center for the sliced out slice
-                    point.slicedTranslation = {
-                        translateX: Math.round(Math.cos(angle) * slicedOffset),
-                        translateY: Math.round(Math.sin(angle) * slicedOffset)
-                    };
-                    // set the anchor point for tooltips
-                    radiusX = Math.cos(angle) * positions[2] / 2;
-                    radiusY = Math.sin(angle) * positions[2] / 2;
-                    point.tooltipPos = [
-                        positions[0] + radiusX * 0.7,
-                        positions[1] + radiusY * 0.7
-                    ];
-                    point.half = angle < -Math.PI / 2 || angle > Math.PI / 2 ?
-                        1 :
-                        0;
-                    point.angle = angle;
-                    // Set the anchor point for data labels. Use point.labelDistance
-                    // instead of labelDistance // #1174
-                    // finalConnectorOffset - not override connectorOffset value.
-                    finalConnectorOffset = Math.min(connectorOffset, point.labelDistance / 5); // #1678
-                    point.labelPosition = {
-                        natural: {
-                            // initial position of the data label - it's utilized for
-                            // finding the final position for the label
-                            x: positions[0] + radiusX + Math.cos(angle) *
-                                point.labelDistance,
-                            y: positions[1] + radiusY + Math.sin(angle) *
-                                point.labelDistance
-                        },
-                        'final': {
-                        // used for generating connector path -
-                        // initialized later in drawDataLabels function
-                        // x: undefined,
-                        // y: undefined
-                        },
-                        // left - pie on the left side of the data label
-                        // right - pie on the right side of the data label
-                        // center - data label overlaps the pie
-                        alignment: point.labelDistance < 0 ?
-                            'center' : point.half ? 'right' : 'left',
-                        connectorPosition: {
-                            breakAt: {
-                                x: positions[0] + radiusX + Math.cos(angle) *
-                                    finalConnectorOffset,
-                                y: positions[1] + radiusY + Math.sin(angle) *
-                                    finalConnectorOffset
-                            },
-                            touchingSliceAt: {
-                                x: positions[0] + radiusX,
-                                y: positions[1] + radiusY
-                            }
-                        }
-                    };
-                }
-                fireEvent(series, 'afterTranslate');
-            },
             /**
-             * Called internally to draw auxiliary graph in pie-like series in
-             * situtation when the default graph is not sufficient enough to present
-             * the data well. Auxiliary graph is saved in the same object as
-             * regular graph.
+             * The shadow of the box. Works best with `borderWidth` or
+             * `backgroundColor`. Since 2.3 the shadow can be an object
+             * configuration containing `color`, `offsetX`, `offsetY`, `opacity`
+             * and `width`.
              *
-             * @private
-             * @function Highcharts.seriesTypes.pie#drawEmpty
+             * @sample {highcharts} highcharts/plotoptions/series-datalabels-box/
+             *         Data labels box options
+             *
+             * @type      {boolean|Highcharts.ShadowOptionsObject}
+             * @default   false
+             * @since     2.2.1
+             * @apioption plotOptions.series.dataLabels.shadow
              */
-            drawEmpty: function () {
-                var centerX,
-                    centerY,
-                    start = this.startAngleRad,
-                    end = this.endAngleRad,
-                    options = this.options;
-                // Draw auxiliary graph if there're no visible points.
-                if (this.total === 0 && this.center) {
-                    centerX = this.center[0];
-                    centerY = this.center[1];
-                    if (!this.graph) {
-                        this.graph = this.chart.renderer
-                            .arc(centerX, centerY, this.center[1] / 2, 0, start, end)
-                            .addClass('highcharts-empty-series')
-                            .add(this.group);
-                    }
-                    this.graph.attr({
-                        d: SVGRenderer.prototype.symbols.arc(centerX, centerY, this.center[2] / 2, 0, {
-                            start: start,
-                            end: end,
-                            innerR: this.center[3] / 2
-                        })
-                    });
-                    if (!this.chart.styledMode) {
-                        this.graph.attr({
-                            'stroke-width': options.borderWidth,
-                            fill: options.fillColor || 'none',
-                            stroke: options.color ||
-                                '#cccccc'
-                        });
-                    }
-                }
-                else if (this.graph) { // Destroy the graph object.
-                    this.graph = this.graph.destroy();
-                }
-            },
             /**
-             * Draw the data points
+             * The name of a symbol to use for the border around the label.
+             * Symbols are predefined functions on the Renderer object.
              *
-             * @private
-             * @function Highcharts.seriesTypes.pie#drawPoints
-             * @return {void}
-             */
-            redrawPoints: function () {
-                var series = this,
-                    chart = series.chart,
-                    renderer = chart.renderer,
-                    groupTranslation,
-                    graphic,
-                    pointAttr,
-                    shapeArgs,
-                    shadow = series.options.shadow;
-                this.drawEmpty();
-                if (shadow && !series.shadowGroup && !chart.styledMode) {
-                    series.shadowGroup = renderer.g('shadow')
-                        .attr({ zIndex: -1 })
-                        .add(series.group);
-                }
-                // draw the slices
-                series.points.forEach(function (point) {
-                    var animateTo = {};
-                    graphic = point.graphic;
-                    if (!point.isNull && graphic) {
-                        shapeArgs = point.shapeArgs;
-                        // If the point is sliced, use special translation, else use
-                        // plot area translation
-                        groupTranslation = point.getTranslate();
-                        if (!chart.styledMode) {
-                            // Put the shadow behind all points
-                            var shadowGroup = point.shadowGroup;
-                            if (shadow && !shadowGroup) {
-                                shadowGroup = point.shadowGroup = renderer
-                                    .g('shadow')
-                                    .add(series.shadowGroup);
-                            }
-                            if (shadowGroup) {
-                                shadowGroup.attr(groupTranslation);
-                            }
-                            pointAttr = series.pointAttribs(point, (point.selected && 'select'));
-                        }
-                        // Draw the slice
-                        if (!point.delayedRendering) {
-                            graphic
-                                .setRadialReference(series.center);
-                            if (!chart.styledMode) {
-                                merge(true, animateTo, pointAttr);
-                            }
-                            merge(true, animateTo, shapeArgs, groupTranslation);
-                            graphic.animate(animateTo);
-                        }
-                        else {
-                            graphic
-                                .setRadialReference(series.center)
-                                .attr(shapeArgs)
-                                .attr(groupTranslation);
-                            if (!chart.styledMode) {
-                                graphic
-                                    .attr(pointAttr)
-                                    .attr({ 'stroke-linejoin': 'round' })
-                                    .shadow(shadow, shadowGroup);
-                            }
-                            point.delayedRendering = false;
-                        }
-                        graphic.attr({
-                            visibility: point.visible ? 'inherit' : 'hidden'
-                        });
-                        graphic.addClass(point.getClassName());
-                    }
-                    else if (graphic) {
-                        point.graphic = graphic.destroy();
-                    }
-                });
+             * @sample {highcharts} highcharts/plotoptions/series-datalabels-shape/
+             *         A callout for annotations
+             *
+             * @type      {string}
+             * @default   square
+             * @since     4.1.2
+             * @apioption plotOptions.series.dataLabels.shape
+             */
+            /**
+             * Styles for the label. The default `color` setting is
+             * `"contrast"`, which is a pseudo color that Highcharts picks up
+             * and applies the maximum contrast to the underlying point item,
+             * for example the bar in a bar chart.
+             *
+             * The `textOutline` is a pseudo property that applies an outline of
+             * the given width with the given color, which by default is the
+             * maximum contrast to the text. So a bright text color will result
+             * in a black text outline for maximum readability on a mixed
+             * background. In some cases, especially with grayscale text, the
+             * text outline doesn't work well, in which cases it can be disabled
+             * by setting it to `"none"`. When `useHTML` is true, the
+             * `textOutline` will not be picked up. In this, case, the same
+             * effect can be acheived through the `text-shadow` CSS property.
+             *
+             * For some series types, where each point has an extent, like for
+             * example tree maps, the data label may overflow the point. There
+             * are two strategies for handling overflow. By default, the text
+             * will wrap to multiple lines. The other strategy is to set
+             * `style.textOverflow` to `ellipsis`, which will keep the text on
+             * one line plus it will break inside long words.
+             *
+             * @sample {highcharts} highcharts/plotoptions/series-datalabels-style/
+             *         Bold labels
+             * @sample {highcharts} highcharts/plotoptions/pie-datalabels-overflow/
+             *         Long labels truncated with an ellipsis in a pie
+             * @sample {highcharts} highcharts/plotoptions/pie-datalabels-overflow-wrap/
+             *         Long labels are wrapped in a pie
+             * @sample {highmaps} maps/demo/color-axis/
+             *         Bold labels
+             *
+             * @type      {Highcharts.CSSObject}
+             * @since     4.1.0
+             * @apioption plotOptions.series.dataLabels.style
+             */
+            style: {
+              /** @internal */
+              fontSize: "11px",
+              /** @internal */
+              fontWeight: "bold",
+              /** @internal */
+              color: "contrast",
+              /** @internal */
+              textOutline: "1px contrast",
             },
             /**
-             * Slices in pie chart are initialized in DOM, but it's shapes and
-             * animations are normally run in `drawPoints()`.
-             * @private
+             * Options for a label text which should follow marker's shape.
+             * Border and background are disabled for a label that follows a
+             * path.
+             *
+             * **Note:** Only SVG-based renderer supports this option. Setting
+             * `useHTML` to true will disable this option.
+             *
+             * @declare   Highcharts.DataLabelsTextPathOptionsObject
+             * @since     7.1.0
+             * @apioption plotOptions.series.dataLabels.textPath
              */
-            drawPoints: function () {
-                var renderer = this.chart.renderer;
-                this.points.forEach(function (point) {
-                    // When updating a series between 2d and 3d or cartesian and
-                    // polar, the shape type changes.
-                    if (point.graphic && point.hasNewShapeType()) {
-                        point.graphic = point.graphic.destroy();
-                    }
-                    if (!point.graphic) {
-                        point.graphic = renderer[point.shapeType](point.shapeArgs)
-                            .add(point.series.group);
-                        point.delayedRendering = true;
-                    }
-                });
-            },
             /**
-             * @private
-             * @deprecated
-             * @function Highcharts.seriesTypes.pie#searchPoint
+             * Presentation attributes for the text path.
+             *
+             * @type      {Highcharts.SVGAttributes}
+             * @since     7.1.0
+             * @apioption plotOptions.series.dataLabels.textPath.attributes
              */
-            searchPoint: noop,
             /**
-             * Utility for sorting data labels
+             * Enable or disable `textPath` option for link's or marker's data
+             * labels.
              *
-             * @private
-             * @function Highcharts.seriesTypes.pie#sortByAngle
-             * @param {Array<Highcharts.Point>} points
-             * @param {number} sign
-             * @return {void}
+             * @type      {boolean}
+             * @since     7.1.0
+             * @apioption plotOptions.series.dataLabels.textPath.enabled
              */
-            sortByAngle: function (points, sign) {
-                points.sort(function (a, b) {
-                    return ((typeof a.angle !== 'undefined') &&
-                        (b.angle - a.angle) * sign);
-                });
-            },
             /**
-             * Use a simple symbol from LegendSymbolMixin.
+             * Whether to
+             * [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html)
+             * to render the labels.
              *
-             * @private
-             * @borrows Highcharts.LegendSymbolMixin.drawRectangle as Highcharts.seriesTypes.pie#drawLegendSymbol
+             * @type      {boolean}
+             * @default   false
+             * @apioption plotOptions.series.dataLabels.useHTML
              */
-            drawLegendSymbol: LegendSymbolMixin.drawRectangle,
             /**
-             * Use the getCenter method from drawLegendSymbol.
+             * The vertical alignment of a data label. Can be one of `top`,
+             * `middle` or `bottom`. The default value depends on the data, for
+             * instance in a column chart, the label is above positive values
+             * and below negative values.
              *
-             * @private
-             * @borrows Highcharts.CenteredSeriesMixin.getCenter as Highcharts.seriesTypes.pie#getCenter
+             * @type  {Highcharts.VerticalAlignValue|null}
+             * @since 2.3.3
              */
-            getCenter: CenteredSeriesMixin.getCenter,
+            verticalAlign: "bottom",
             /**
-             * Pies don't have point marker symbols.
+             * The x position offset of the label relative to the point in
+             * pixels.
              *
-             * @deprecated
-             * @private
-             * @function Highcharts.seriesTypes.pie#getSymbol
+             * @sample {highcharts} highcharts/plotoptions/series-datalabels-rotation/
+             *         Vertical and positioned
+             * @sample {highcharts} highcharts/plotoptions/bar-datalabels-align-inside-bar/
+             *         Data labels inside the bar
              */
-            getSymbol: noop,
+            x: 0,
             /**
-             * @private
-             * @type {null}
+             * The Z index of the data labels. The default Z index puts it above
+             * the series. Use a Z index of 2 to display it behind the series.
+             *
+             * @type      {number}
+             * @default   6
+             * @since     2.3.5
+             * @apioption plotOptions.series.dataLabels.z
              */
-            drawGraph: null
-        }, 
-        /**
-         * @lends seriesTypes.pie.prototype.pointClass.prototype
-         */
-        {
             /**
-             * Initialize the pie slice
+             * The y position offset of the label relative to the point in
+             * pixels.
              *
-             * @private
-             * @function Highcharts.seriesTypes.pie#pointClass#init
-             * @return {Highcharts.Point}
-             */
-            init: function () {
-                Point.prototype.init.apply(this, arguments);
-                var point = this,
-                    toggleSlice;
-                point.name = pick(point.name, 'Slice');
-                // add event listener for select
-                toggleSlice = function (e) {
-                    point.slice(e.type === 'select');
-                };
-                addEvent(point, 'select', toggleSlice);
-                addEvent(point, 'unselect', toggleSlice);
-                return point;
+             * @sample {highcharts} highcharts/plotoptions/series-datalabels-rotation/
+             *         Vertical and positioned
+             */
+            y: 0,
+          },
+          /**
+           * When the series contains less points than the crop threshold, all
+           * points are drawn, even if the points fall outside the visible plot
+           * area at the current zoom. The advantage of drawing all points
+           * (including markers and columns), is that animation is performed on
+           * updates. On the other hand, when the series contains more points than
+           * the crop threshold, the series data is cropped to only contain points
+           * that fall within the plot area. The advantage of cropping away
+           * invisible points is to increase performance on large series.
+           *
+           * @since   2.2
+           * @product highcharts highstock
+           *
+           * @private
+           */
+          cropThreshold: 300,
+          /**
+           * Opacity of a series parts: line, fill (e.g. area) and dataLabels.
+           *
+           * @see [states.inactive.opacity](#plotOptions.series.states.inactive.opacity)
+           *
+           * @since 7.1.0
+           *
+           * @private
+           */
+          opacity: 1,
+          /**
+           * The width of each point on the x axis. For example in a column chart
+           * with one value each day, the pointRange would be 1 day (= 24 * 3600
+           * * 1000 milliseconds). This is normally computed automatically, but
+           * this option can be used to override the automatic value.
+           *
+           * @product highstock
+           *
+           * @private
+           */
+          pointRange: 0,
+          /**
+           * When this is true, the series will not cause the Y axis to cross
+           * the zero plane (or [threshold](#plotOptions.series.threshold) option)
+           * unless the data actually crosses the plane.
+           *
+           * For example, if `softThreshold` is `false`, a series of 0, 1, 2,
+           * 3 will make the Y axis show negative values according to the
+           * `minPadding` option. If `softThreshold` is `true`, the Y axis starts
+           * at 0.
+           *
+           * @since   4.1.9
+           * @product highcharts highstock
+           *
+           * @private
+           */
+          softThreshold: true,
+          /**
+           * @declare Highcharts.SeriesStatesOptionsObject
+           *
+           * @private
+           */
+          states: {
+            /**
+             * The normal state of a series, or for point items in column, pie
+             * and similar series. Currently only used for setting animation
+             * when returning to normal state from hover.
+             *
+             * @declare Highcharts.SeriesStatesNormalOptionsObject
+             */
+            normal: {
+              /**
+               * Animation when returning to normal state after hovering.
+               *
+               * @type {boolean|Partial<Highcharts.AnimationOptionsObject>}
+               */
+              animation: true,
             },
             /**
-             * Negative points are not valid (#1530, #3623, #5322)
-             *
-             * @private
-             * @function Highcharts.seriesTypes.pie#pointClass#isValid
-             * @return {boolean}
-             */
-            isValid: function () {
-                return isNumber(this.y) && this.y >= 0;
+             * Options for the hovered series. These settings override the
+             * normal state options when a series is moused over or touched.
+             *
+             * @declare Highcharts.SeriesStatesHoverOptionsObject
+             */
+            hover: {
+              /**
+               * Enable separate styles for the hovered series to visualize
+               * that the user hovers either the series itself or the legend.
+               *
+               * @sample {highcharts} highcharts/plotoptions/series-states-hover-enabled/
+               *         Line
+               * @sample {highcharts} highcharts/plotoptions/series-states-hover-enabled-column/
+               *         Column
+               * @sample {highcharts} highcharts/plotoptions/series-states-hover-enabled-pie/
+               *         Pie
+               *
+               * @type      {boolean}
+               * @default   true
+               * @since     1.2
+               * @apioption plotOptions.series.states.hover.enabled
+               */
+              /**
+               * Animation setting for hovering the graph in line-type series.
+               *
+               * @type {boolean|Partial<Highcharts.AnimationOptionsObject>}
+               * @since   5.0.8
+               * @product highcharts highstock
+               */
+              animation: {
+                /**
+                 * The duration of the hover animation in milliseconds. By
+                 * default the hover state animates quickly in, and slowly
+                 * back to normal.
+                 *
+                 * @internal
+                 */
+                duration: 50,
+              },
+              /**
+               * Pixel width of the graph line. By default this property is
+               * undefined, and the `lineWidthPlus` property dictates how much
+               * to increase the linewidth from normal state.
+               *
+               * @sample {highcharts} highcharts/plotoptions/series-states-hover-linewidth/
+               *         5px line on hover
+               *
+               * @type      {number}
+               * @product   highcharts highstock
+               * @apioption plotOptions.series.states.hover.lineWidth
+               */
+              /**
+               * The additional line width for the graph of a hovered series.
+               *
+               * @sample {highcharts} highcharts/plotoptions/series-states-hover-linewidthplus/
+               *         5 pixels wider
+               * @sample {highstock} highcharts/plotoptions/series-states-hover-linewidthplus/
+               *         5 pixels wider
+               *
+               * @since   4.0.3
+               * @product highcharts highstock
+               */
+              lineWidthPlus: 1,
+              /**
+               * In Highcharts 1.0, the appearance of all markers belonging
+               * to the hovered series. For settings on the hover state of the
+               * individual point, see
+               * [marker.states.hover](#plotOptions.series.marker.states.hover).
+               *
+               * @deprecated
+               *
+               * @extends   plotOptions.series.marker
+               * @excluding states
+               * @product   highcharts highstock
+               */
+              marker: {
+                // lineWidth: base + 1,
+                // radius: base + 1
+              },
+              /**
+               * Options for the halo appearing around the hovered point in
+               * line-type series as well as outside the hovered slice in pie
+               * charts. By default the halo is filled by the current point or
+               * series color with an opacity of 0.25\. The halo can be
+               * disabled by setting the `halo` option to `null`.
+               *
+               * In styled mode, the halo is styled with the
+               * `.highcharts-halo` class, with colors inherited from
+               * `.highcharts-color-{n}`.
+               *
+               * @sample {highcharts} highcharts/plotoptions/halo/
+               *         Halo options
+               * @sample {highstock} highcharts/plotoptions/halo/
+               *         Halo options
+               *
+               * @declare Highcharts.SeriesStatesHoverHaloOptionsObject
+               * @type    {null|*}
+               * @since   4.0
+               * @product highcharts highstock
+               */
+              halo: {
+                /**
+                 * A collection of SVG attributes to override the appearance
+                 * of the halo, for example `fill`, `stroke` and
+                 * `stroke-width`.
+                 *
+                 * @type      {Highcharts.SVGAttributes}
+                 * @since     4.0
+                 * @product   highcharts highstock
+                 * @apioption plotOptions.series.states.hover.halo.attributes
+                 */
+                /**
+                 * The pixel size of the halo. For point markers this is the
+                 * radius of the halo. For pie slices it is the width of the
+                 * halo outside the slice. For bubbles it defaults to 5 and
+                 * is the width of the halo outside the bubble.
+                 *
+                 * @since   4.0
+                 * @product highcharts highstock
+                 */
+                size: 10,
+                /**
+                 * Opacity for the halo unless a specific fill is overridden
+                 * using the `attributes` setting. Note that Highcharts is
+                 * only able to apply opacity to colors of hex or rgb(a)
+                 * formats.
+                 *
+                 * @since   4.0
+                 * @product highcharts highstock
+                 */
+                opacity: 0.25,
+              },
             },
             /**
-             * Toggle the visibility of the pie slice
+             * Specific options for point in selected states, after being
+             * selected by
+             * [allowPointSelect](#plotOptions.series.allowPointSelect)
+             * or programmatically.
              *
-             * @private
-             * @function Highcharts.seriesTypes.pie#pointClass#setVisible
-             * @param {boolean} vis
-             *        Whether to show the slice or not. If undefined, the visibility
-             *        is toggled.
-             * @param {boolean} [redraw=false]
-             * @return {void}
+             * @sample maps/plotoptions/series-allowpointselect/
+             *         Allow point select demo
+             *
+             * @declare   Highcharts.SeriesStatesSelectOptionsObject
+             * @extends   plotOptions.series.states.hover
+             * @excluding brightness
              */
-            setVisible: function (vis, redraw) {
-                var point = this,
-                    series = point.series,
-                    chart = series.chart,
-                    ignoreHiddenPoint = series.options.ignoreHiddenPoint;
-                redraw = pick(redraw, ignoreHiddenPoint);
-                if (vis !== point.visible) {
-                    // If called without an argument, toggle visibility
-                    point.visible = point.options.visible = vis =
-                        typeof vis === 'undefined' ? !point.visible : vis;
-                    // update userOptions.data
-                    series.options.data[series.data.indexOf(point)] =
-                        point.options;
-                    // Show and hide associated elements. This is performed
-                    // regardless of redraw or not, because chart.redraw only
-                    // handles full series.
-                    ['graphic', 'dataLabel', 'connector', 'shadowGroup'].forEach(function (key) {
-                        if (point[key]) {
-                            point[key][vis ? 'show' : 'hide'](true);
-                        }
-                    });
-                    if (point.legendItem) {
-                        chart.legend.colorizeItem(point, vis);
-                    }
-                    // #4170, hide halo after hiding point
-                    if (!vis && point.state === 'hover') {
-                        point.setState('');
+            select: {
+              animation: {
+                /** @internal */
+                duration: 0,
+              },
+            },
+            /**
+             * The opposite state of a hover for series.
+             *
+             * @sample highcharts/plotoptions/series-states-inactive-disabled
+             *         Disabled inactive state
+             *
+             * @declare Highcharts.SeriesStatesInactiveOptionsObject
+             */
+            inactive: {
+              /**
+               * Enable or disable the inactive state for a series
+               *
+               * @sample highcharts/plotoptions/series-states-inactive-disabled
+               *         Disabled inactive state
+               *
+               * @type {boolean}
+               * @default true
+               * @apioption plotOptions.series.states.inactive.enabled
+               */
+              /**
+               * The animation for entering the inactive state.
+               *
+               * @type {boolean|Partial<Highcharts.AnimationOptionsObject>}
+               */
+              animation: {
+                /** @internal */
+                duration: 50,
+              },
+              /**
+               * Opacity of series elements (dataLabels, line, area).
+               *
+               * @type {number}
+               */
+              opacity: 0.2,
+            },
+          },
+          /**
+           * Sticky tracking of mouse events. When true, the `mouseOut` event on a
+           * series isn't triggered until the mouse moves over another series, or
+           * out of the plot area. When false, the `mouseOut` event on a series is
+           * triggered when the mouse leaves the area around the series' graph or
+           * markers. This also implies the tooltip when not shared. When
+           * `stickyTracking` is false and `tooltip.shared` is false, the tooltip
+           * will be hidden when moving the mouse between series. Defaults to true
+           * for line and area type series, but to false for columns, pies etc.
+           *
+           * **Note:** The boost module will force this option because of
+           * technical limitations.
+           *
+           * @sample {highcharts} highcharts/plotoptions/series-stickytracking-true/
+           *         True by default
+           * @sample {highcharts} highcharts/plotoptions/series-stickytracking-false/
+           *         False
+           *
+           * @default {highcharts} true
+           * @default {highstock} true
+           * @default {highmaps} false
+           * @since   2.0
+           *
+           * @private
+           */
+          stickyTracking: true,
+          /**
+           * A configuration object for the tooltip rendering of each single
+           * series. Properties are inherited from [tooltip](#tooltip), but only
+           * the following properties can be defined on a series level.
+           *
+           * @declare   Highcharts.SeriesTooltipOptionsObject
+           * @since     2.3
+           * @extends   tooltip
+           * @excluding animation, backgroundColor, borderColor, borderRadius,
+           *            borderWidth, className, crosshairs, enabled, formatter,
+           *            headerShape, hideDelay, outside, padding, positioner,
+           *            shadow, shape, shared, snap, split, stickOnContact,
+           *            style, useHTML
+           * @apioption plotOptions.series.tooltip
+           */
+          /**
+           * When a series contains a data array that is longer than this, only
+           * one dimensional arrays of numbers, or two dimensional arrays with
+           * x and y values are allowed. Also, only the first point is tested,
+           * and the rest are assumed to be the same format. This saves expensive
+           * data checking and indexing in long series. Set it to `0` disable.
+           *
+           * Note:
+           * In boost mode turbo threshold is forced. Only array of numbers or
+           * two dimensional arrays are allowed.
+           *
+           * @since   2.2
+           * @product highcharts highstock gantt
+           *
+           * @private
+           */
+          turboThreshold: 1000,
+          /**
+           * An array defining zones within a series. Zones can be applied to the
+           * X axis, Y axis or Z axis for bubbles, according to the `zoneAxis`
+           * option. The zone definitions have to be in ascending order regarding
+           * to the value.
+           *
+           * In styled mode, the color zones are styled with the
+           * `.highcharts-zone-{n}` class, or custom classed from the `className`
+           * option
+           * ([view live demo](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/css/color-zones/)).
+           *
+           * @see [zoneAxis](#plotOptions.series.zoneAxis)
+           *
+           * @sample {highcharts} highcharts/series/color-zones-simple/
+           *         Color zones
+           * @sample {highstock} highcharts/series/color-zones-simple/
+           *         Color zones
+           *
+           * @declare   Highcharts.SeriesZonesOptionsObject
+           * @type      {Array<*>}
+           * @since     4.1.0
+           * @product   highcharts highstock
+           * @apioption plotOptions.series.zones
+           */
+          /**
+           * Styled mode only. A custom class name for the zone.
+           *
+           * @sample highcharts/css/color-zones/
+           *         Zones styled by class name
+           *
+           * @type      {string}
+           * @since     5.0.0
+           * @apioption plotOptions.series.zones.className
+           */
+          /**
+           * Defines the color of the series.
+           *
+           * @see [series color](#plotOptions.series.color)
+           *
+           * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+           * @since     4.1.0
+           * @product   highcharts highstock
+           * @apioption plotOptions.series.zones.color
+           */
+          /**
+           * A name for the dash style to use for the graph.
+           *
+           * @see [plotOptions.series.dashStyle](#plotOptions.series.dashStyle)
+           *
+           * @sample {highcharts|highstock} highcharts/series/color-zones-dashstyle-dot/
+           *         Dashed line indicates prognosis
+           *
+           * @type      {Highcharts.DashStyleValue}
+           * @since     4.1.0
+           * @product   highcharts highstock
+           * @apioption plotOptions.series.zones.dashStyle
+           */
+          /**
+           * Defines the fill color for the series (in area type series)
+           *
+           * @see [fillColor](#plotOptions.area.fillColor)
+           *
+           * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+           * @since     4.1.0
+           * @product   highcharts highstock
+           * @apioption plotOptions.series.zones.fillColor
+           */
+          /**
+           * The value up to where the zone extends, if undefined the zones
+           * stretches to the last value in the series.
+           *
+           * @type      {number}
+           * @since     4.1.0
+           * @product   highcharts highstock
+           * @apioption plotOptions.series.zones.value
+           */
+          /**
+           * When using dual or multiple color axes, this number defines which
+           * colorAxis the particular series is connected to. It refers to
+           * either the
+           * {@link #colorAxis.id|axis id}
+           * or the index of the axis in the colorAxis array, with 0 being the
+           * first. Set this option to false to prevent a series from connecting
+           * to the default color axis.
+           *
+           * Since v7.2.0 the option can also be an axis id or an axis index
+           * instead of a boolean flag.
+           *
+           * @sample highcharts/coloraxis/coloraxis-with-pie/
+           *         Color axis with pie series
+           * @sample highcharts/coloraxis/multiple-coloraxis/
+           *         Multiple color axis
+           *
+           * @type      {number|string|boolean}
+           * @default   0
+           * @product   highcharts highstock highmaps
+           * @apioption plotOptions.series.colorAxis
+           */
+          /**
+           * Determines what data value should be used to calculate point color
+           * if `colorAxis` is used. Requires to set `min` and `max` if some
+           * custom point property is used or if approximation for data grouping
+           * is set to `'sum'`.
+           *
+           * @sample highcharts/coloraxis/custom-color-key/
+           *         Custom color key
+           * @sample highcharts/coloraxis/changed-default-color-key/
+           *         Changed default color key
+           *
+           * @type      {string}
+           * @default   y
+           * @since     7.2.0
+           * @product   highcharts highstock highmaps
+           * @apioption plotOptions.series.colorKey
+           */
+          /**
+           * Determines whether the series should look for the nearest point
+           * in both dimensions or just the x-dimension when hovering the series.
+           * Defaults to `'xy'` for scatter series and `'x'` for most other
+           * series. If the data has duplicate x-values, it is recommended to
+           * set this to `'xy'` to allow hovering over all points.
+           *
+           * Applies only to series types using nearest neighbor search (not
+           * direct hover) for tooltip.
+           *
+           * @sample {highcharts} highcharts/series/findnearestpointby/
+           *         Different hover behaviors
+           * @sample {highstock} highcharts/series/findnearestpointby/
+           *         Different hover behaviors
+           * @sample {highmaps} highcharts/series/findnearestpointby/
+           *         Different hover behaviors
+           *
+           * @since      5.0.10
+           * @validvalue ["x", "xy"]
+           *
+           * @private
+           */
+          findNearestPointBy: "x",
+        },
+        /* eslint-disable no-invalid-this, valid-jsdoc */
+        /** @lends Highcharts.Series.prototype */
+        {
+          axisTypes: ["xAxis", "yAxis"],
+          coll: "series",
+          colorCounter: 0,
+          cropShoulder: 1,
+          directTouch: false,
+          isCartesian: true,
+          // each point's x and y values are stored in this.xData and this.yData
+          parallelArrays: ["x", "y"],
+          pointClass: Point,
+          requireSorting: true,
+          sorted: true,
+          init: function (chart, options) {
+            fireEvent(this, "init", { options: options });
+            var series = this,
+              events,
+              chartSeries = chart.series,
+              lastSeries;
+            // A lookup over those events that are added by _options_ (not
+            // programmatically). These are updated through Series.update()
+            // (#10861).
+            this.eventOptions = this.eventOptions || {};
+            // The 'eventsToUnbind' property moved from prototype into the
+            // Series init to avoid reference to the same array between
+            // the different series and charts. #12959, #13937
+            this.eventsToUnbind = [];
+            /**
+             * Read only. The chart that the series belongs to.
+             *
+             * @name Highcharts.Series#chart
+             * @type {Highcharts.Chart}
+             */
+            series.chart = chart;
+            /**
+             * Read only. The series' type, like "line", "area", "column" etc.
+             * The type in the series options anc can be altered using
+             * {@link Series#update}.
+             *
+             * @name Highcharts.Series#type
+             * @type {string}
+             */
+            /**
+             * Read only. The series' current options. To update, use
+             * {@link Series#update}.
+             *
+             * @name Highcharts.Series#options
+             * @type {Highcharts.SeriesOptionsType}
+             */
+            series.options = options = series.setOptions(options);
+            series.linkedSeries = [];
+            // bind the axes
+            series.bindAxes();
+            // set some variables
+            extend(series, {
+              /**
+               * The series name as given in the options. Defaults to
+               * "Series {n}".
+               *
+               * @name Highcharts.Series#name
+               * @type {string}
+               */
+              name: options.name,
+              state: "",
+              /**
+               * Read only. The series' visibility state as set by {@link
+               * Series#show}, {@link Series#hide}, or in the initial
+               * configuration.
+               *
+               * @name Highcharts.Series#visible
+               * @type {boolean}
+               */
+              visible: options.visible !== false,
+              /**
+               * Read only. The series' selected state as set by {@link
+               * Highcharts.Series#select}.
+               *
+               * @name Highcharts.Series#selected
+               * @type {boolean}
+               */
+              selected: options.selected === true, // false by default
+            });
+            // Register event listeners
+            events = options.events;
+            objectEach(events, function (event, eventType) {
+              if (isFunction(event)) {
+                // If event does not exist, or is changed by Series.update
+                if (series.eventOptions[eventType] !== event) {
+                  // Remove existing if set by option
+                  if (isFunction(series.eventOptions[eventType])) {
+                    removeEvent(
+                      series,
+                      eventType,
+                      series.eventOptions[eventType]
+                    );
+                  }
+                  series.eventOptions[eventType] = event;
+                  addEvent(series, eventType, event);
+                }
+              }
+            });
+            if (
+              (events && events.click) ||
+              (options.point &&
+                options.point.events &&
+                options.point.events.click) ||
+              options.allowPointSelect
+            ) {
+              chart.runTrackerClick = true;
+            }
+            series.getColor();
+            series.getSymbol();
+            // Initialize the parallel data arrays
+            series.parallelArrays.forEach(function (key) {
+              if (!series[key + "Data"]) {
+                series[key + "Data"] = [];
+              }
+            });
+            // Mark cartesian
+            if (series.isCartesian) {
+              chart.hasCartesianSeries = true;
+            }
+            // Get the index and register the series in the chart. The index is
+            // one more than the current latest series index (#5960).
+            if (chartSeries.length) {
+              lastSeries = chartSeries[chartSeries.length - 1];
+            }
+            series._i = pick(lastSeries && lastSeries._i, -1) + 1;
+            series.opacity = series.options.opacity;
+            // Insert the series and re-order all series above the insertion
+            // point.
+            chart.orderSeries(this.insert(chartSeries));
+            // Set options for series with sorting and set data later.
+            if (options.dataSorting && options.dataSorting.enabled) {
+              series.setDataSortingOptions();
+            } else if (!series.points && !series.data) {
+              series.setData(options.data, false);
+            }
+            fireEvent(this, "afterInit");
+          },
+          /**
+           * Check whether the series item is itself or inherits from a certain
+           * series type.
+           *
+           * @function Highcharts.Series#is
+           * @param {string} type The type of series to check for, can be either
+           *        featured or custom series types. For example `column`, `pie`,
+           *        `ohlc` etc.
+           *
+           * @return {boolean}
+           *        True if this item is or inherits from the given type.
+           */
+          is: function (type) {
+            return seriesTypes[type] && this instanceof seriesTypes[type];
+          },
+          /**
+           * Insert the series in a collection with other series, either the chart
+           * series or yAxis series, in the correct order according to the index
+           * option. Used internally when adding series.
+           *
+           * @private
+           * @function Highcharts.Series#insert
+           * @param {Array<Highcharts.Series>} collection
+           *        A collection of series, like `chart.series` or `xAxis.series`.
+           * @return {number}
+           *         The index of the series in the collection.
+           */
+          insert: function (collection) {
+            var indexOption = this.options.index,
+              i;
+            // Insert by index option
+            if (isNumber(indexOption)) {
+              i = collection.length;
+              while (i--) {
+                // Loop down until the interted element has higher index
+                if (
+                  indexOption >=
+                  pick(collection[i].options.index, collection[i]._i)
+                ) {
+                  collection.splice(i + 1, 0, this);
+                  break;
+                }
+              }
+              if (i === -1) {
+                collection.unshift(this);
+              }
+              i = i + 1;
+              // Or just push it to the end
+            } else {
+              collection.push(this);
+            }
+            return pick(i, collection.length - 1);
+          },
+          /**
+           * Set the xAxis and yAxis properties of cartesian series, and register
+           * the series in the `axis.series` array.
+           *
+           * @private
+           * @function Highcharts.Series#bindAxes
+           * @return {void}
+           * @exception 18
+           */
+          bindAxes: function () {
+            var series = this,
+              seriesOptions = series.options,
+              chart = series.chart,
+              axisOptions;
+            fireEvent(this, "bindAxes", null, function () {
+              // repeat for xAxis and yAxis
+              (series.axisTypes || []).forEach(function (AXIS) {
+                // loop through the chart's axis objects
+                chart[AXIS].forEach(function (axis) {
+                  axisOptions = axis.options;
+                  // apply if the series xAxis or yAxis option mathches
+                  // the number of the axis, or if undefined, use the
+                  // first axis
+                  if (
+                    seriesOptions[AXIS] === axisOptions.index ||
+                    (typeof seriesOptions[AXIS] !== "undefined" &&
+                      seriesOptions[AXIS] === axisOptions.id) ||
+                    (typeof seriesOptions[AXIS] === "undefined" &&
+                      axisOptions.index === 0)
+                  ) {
+                    // register this series in the axis.series lookup
+                    series.insert(axis.series);
+                    // set this series.xAxis or series.yAxis reference
+                    /**
+                     * Read only. The unique xAxis object associated
+                     * with the series.
+                     *
+                     * @name Highcharts.Series#xAxis
+                     * @type {Highcharts.Axis}
+                     */
+                    /**
+                     * Read only. The unique yAxis object associated
+                     * with the series.
+                     *
+                     * @name Highcharts.Series#yAxis
+                     * @type {Highcharts.Axis}
+                     */
+                    series[AXIS] = axis;
+                    // mark dirty for redraw
+                    axis.isDirty = true;
+                  }
+                });
+                // The series needs an X and an Y axis
+                if (!series[AXIS] && series.optionalAxis !== AXIS) {
+                  error(18, true, chart);
+                }
+              });
+            });
+            fireEvent(this, "afterBindAxes");
+          },
+          /**
+           * For simple series types like line and column, the data values are
+           * held in arrays like xData and yData for quick lookup to find extremes
+           * and more. For multidimensional series like bubble and map, this can
+           * be extended with arrays like zData and valueData by adding to the
+           * `series.parallelArrays` array.
+           *
+           * @private
+           * @function Highcharts.Series#updateParallelArrays
+           * @param {Highcharts.Point} point
+           * @param {number|string} i
+           * @return {void}
+           */
+          updateParallelArrays: function (point, i) {
+            var series = point.series,
+              args = arguments,
+              fn = isNumber(i)
+                ? // Insert the value in the given position
+                  function (key) {
+                    var val =
+                      key === "y" && series.toYData
+                        ? series.toYData(point)
+                        : point[key];
+                    series[key + "Data"][i] = val;
+                  }
+                : // Apply the method specified in i with the following
+                  // arguments as arguments
+                  function (key) {
+                    Array.prototype[i].apply(
+                      series[key + "Data"],
+                      Array.prototype.slice.call(args, 2)
+                    );
+                  };
+            series.parallelArrays.forEach(fn);
+          },
+          /**
+           * Define hasData functions for series. These return true if there
+           * are data points on this series within the plot area.
+           *
+           * @private
+           * @function Highcharts.Series#hasData
+           * @return {boolean}
+           */
+          hasData: function () {
+            return (
+              (this.visible &&
+                typeof this.dataMax !== "undefined" &&
+                typeof this.dataMin !== "undefined") || // #3703
+              (this.visible && this.yData && this.yData.length > 0) // #9758
+            );
+          },
+          /**
+           * Return an auto incremented x value based on the pointStart and
+           * pointInterval options. This is only used if an x value is not given
+           * for the point that calls autoIncrement.
+           *
+           * @private
+           * @function Highcharts.Series#autoIncrement
+           * @return {number}
+           */
+          autoIncrement: function () {
+            var options = this.options,
+              xIncrement = this.xIncrement,
+              date,
+              pointInterval,
+              pointIntervalUnit = options.pointIntervalUnit,
+              time = this.chart.time;
+            xIncrement = pick(xIncrement, options.pointStart, 0);
+            this.pointInterval = pointInterval = pick(
+              this.pointInterval,
+              options.pointInterval,
+              1
+            );
+            // Added code for pointInterval strings
+            if (pointIntervalUnit) {
+              date = new time.Date(xIncrement);
+              if (pointIntervalUnit === "day") {
+                time.set("Date", date, time.get("Date", date) + pointInterval);
+              } else if (pointIntervalUnit === "month") {
+                time.set(
+                  "Month",
+                  date,
+                  time.get("Month", date) + pointInterval
+                );
+              } else if (pointIntervalUnit === "year") {
+                time.set(
+                  "FullYear",
+                  date,
+                  time.get("FullYear", date) + pointInterval
+                );
+              }
+              pointInterval = date.getTime() - xIncrement;
+            }
+            this.xIncrement = xIncrement + pointInterval;
+            return xIncrement;
+          },
+          /**
+           * Internal function to set properties for series if data sorting is
+           * enabled.
+           *
+           * @private
+           * @function Highcharts.Series#setDataSortingOptions
+           * @return {void}
+           */
+          setDataSortingOptions: function () {
+            var options = this.options;
+            extend(this, {
+              requireSorting: false,
+              sorted: false,
+              enabledDataSorting: true,
+              allowDG: false,
+            });
+            // To allow unsorted data for column series.
+            if (!defined(options.pointRange)) {
+              options.pointRange = 1;
+            }
+          },
+          /**
+           * Set the series options by merging from the options tree. Called
+           * internally on initializing and updating series. This function will
+           * not redraw the series. For API usage, use {@link Series#update}.
+           * @private
+           * @function Highcharts.Series#setOptions
+           * @param {Highcharts.SeriesOptionsType} itemOptions
+           *        The series options.
+           * @return {Highcharts.SeriesOptionsType}
+           * @fires Highcharts.Series#event:afterSetOptions
+           */
+          setOptions: function (itemOptions) {
+            var chart = this.chart,
+              chartOptions = chart.options,
+              plotOptions = chartOptions.plotOptions,
+              userOptions = chart.userOptions || {},
+              seriesUserOptions = merge(itemOptions),
+              options,
+              zones,
+              zone,
+              styledMode = chart.styledMode,
+              e = {
+                plotOptions: plotOptions,
+                userOptions: seriesUserOptions,
+              };
+            fireEvent(this, "setOptions", e);
+            // These may be modified by the event
+            var typeOptions = e.plotOptions[this.type],
+              userPlotOptions = userOptions.plotOptions || {};
+            // use copy to prevent undetected changes (#9762)
+            /**
+             * Contains series options by the user without defaults.
+             * @name Highcharts.Series#userOptions
+             * @type {Highcharts.SeriesOptionsType}
+             */
+            this.userOptions = e.userOptions;
+            options = merge(
+              typeOptions,
+              plotOptions.series,
+              // #3881, chart instance plotOptions[type] should trump
+              // plotOptions.series
+              userOptions.plotOptions && userOptions.plotOptions[this.type],
+              seriesUserOptions
+            );
+            // The tooltip options are merged between global and series specific
+            // options. Importance order asscendingly:
+            // globals: (1)tooltip, (2)plotOptions.series,
+            // (3)plotOptions[this.type]
+            // init userOptions with possible later updates: 4-6 like 1-3 and
+            // (7)this series options
+            this.tooltipOptions = merge(
+              defaultOptions.tooltip, // 1
+              defaultOptions.plotOptions.series &&
+                defaultOptions.plotOptions.series.tooltip, // 2
+              defaultOptions.plotOptions[this.type].tooltip, // 3
+              chartOptions.tooltip.userOptions, // 4
+              plotOptions.series && plotOptions.series.tooltip, // 5
+              plotOptions[this.type].tooltip, // 6
+              seriesUserOptions.tooltip // 7
+            );
+            // When shared tooltip, stickyTracking is true by default,
+            // unless user says otherwise.
+            this.stickyTracking = pick(
+              seriesUserOptions.stickyTracking,
+              userPlotOptions[this.type] &&
+                userPlotOptions[this.type].stickyTracking,
+              userPlotOptions.series && userPlotOptions.series.stickyTracking,
+              this.tooltipOptions.shared && !this.noSharedTooltip
+                ? true
+                : options.stickyTracking
+            );
+            // Delete marker object if not allowed (#1125)
+            if (typeOptions.marker === null) {
+              delete options.marker;
+            }
+            // Handle color zones
+            this.zoneAxis = options.zoneAxis;
+            zones = this.zones = (options.zones || []).slice();
+            if (
+              (options.negativeColor || options.negativeFillColor) &&
+              !options.zones
+            ) {
+              zone = {
+                value:
+                  options[this.zoneAxis + "Threshold"] ||
+                  options.threshold ||
+                  0,
+                className: "highcharts-negative",
+              };
+              if (!styledMode) {
+                zone.color = options.negativeColor;
+                zone.fillColor = options.negativeFillColor;
+              }
+              zones.push(zone);
+            }
+            if (zones.length) {
+              // Push one extra zone for the rest
+              if (defined(zones[zones.length - 1].value)) {
+                zones.push(
+                  styledMode
+                    ? {}
+                    : {
+                        color: this.color,
+                        fillColor: this.fillColor,
+                      }
+                );
+              }
+            }
+            fireEvent(this, "afterSetOptions", { options: options });
+            return options;
+          },
+          /**
+           * Return series name in "Series {Number}" format or the one defined by
+           * a user. This method can be simply overridden as series name format
+           * can vary (e.g. technical indicators).
+           *
+           * @function Highcharts.Series#getName
+           * @return {string}
+           *         The series name.
+           */
+          getName: function () {
+            // #4119
+            return pick(this.options.name, "Series " + (this.index + 1));
+          },
+          /**
+           * @private
+           * @function Highcharts.Series#getCyclic
+           * @param {string} prop
+           * @param {*} [value]
+           * @param {Highcharts.Dictionary<any>} [defaults]
+           * @return {void}
+           */
+          getCyclic: function (prop, value, defaults) {
+            var i,
+              chart = this.chart,
+              userOptions = this.userOptions,
+              indexName = prop + "Index",
+              counterName = prop + "Counter",
+              len = defaults
+                ? defaults.length
+                : pick(
+                    chart.options.chart[prop + "Count"],
+                    chart[prop + "Count"]
+                  ),
+              setting;
+            if (!value) {
+              // Pick up either the colorIndex option, or the _colorIndex
+              // after Series.update()
+              setting = pick(
+                userOptions[indexName],
+                userOptions["_" + indexName]
+              );
+              if (defined(setting)) {
+                // after Series.update()
+                i = setting;
+              } else {
+                // #6138
+                if (!chart.series.length) {
+                  chart[counterName] = 0;
+                }
+                userOptions["_" + indexName] = i = chart[counterName] % len;
+                chart[counterName] += 1;
+              }
+              if (defaults) {
+                value = defaults[i];
+              }
+            }
+            // Set the colorIndex
+            if (typeof i !== "undefined") {
+              this[indexName] = i;
+            }
+            this[prop] = value;
+          },
+          /**
+           * Get the series' color based on either the options or pulled from
+           * global options.
+           *
+           * @private
+           * @function Highcharts.Series#getColor
+           * @return {void}
+           */
+          getColor: function () {
+            if (this.chart.styledMode) {
+              this.getCyclic("color");
+            } else if (this.options.colorByPoint) {
+              // #4359, selected slice got series.color even when colorByPoint
+              // was set.
+              this.options.color = null;
+            } else {
+              this.getCyclic(
+                "color",
+                this.options.color ||
+                  defaultOptions.plotOptions[this.type].color,
+                this.chart.options.colors
+              );
+            }
+          },
+          /**
+           * Get all points' instances created for this series.
+           *
+           * @private
+           * @function Highcharts.Series#getPointsCollection
+           * @return {Array<Highcharts.Point>}
+           */
+          getPointsCollection: function () {
+            return (this.hasGroupedData ? this.points : this.data) || [];
+          },
+          /**
+           * Get the series' symbol based on either the options or pulled from
+           * global options.
+           *
+           * @private
+           * @function Highcharts.Series#getSymbol
+           * @return {void}
+           */
+          getSymbol: function () {
+            var seriesMarkerOption = this.options.marker;
+            this.getCyclic(
+              "symbol",
+              seriesMarkerOption.symbol,
+              this.chart.options.symbols
+            );
+          },
+          /**
+           * Finds the index of an existing point that matches the given point
+           * options.
+           *
+           * @private
+           * @function Highcharts.Series#findPointIndex
+           * @param    {Highcharts.PointOptionsObject} optionsObject
+           *           The options of the point.
+           * @param    {number} fromIndex
+           *           The index to start searching from, used for optimizing
+           *           series with required sorting.
+           * @returns  {number|undefined}
+           *           Returns the index of a matching point, or undefined if no
+           *           match is found.
+           */
+          findPointIndex: function (optionsObject, fromIndex) {
+            var id = optionsObject.id,
+              x = optionsObject.x,
+              oldData = this.points,
+              matchingPoint,
+              matchedById,
+              pointIndex,
+              matchKey,
+              dataSorting = this.options.dataSorting;
+            if (id) {
+              matchingPoint = this.chart.get(id);
+            } else if (this.linkedParent || this.enabledDataSorting) {
+              matchKey =
+                dataSorting && dataSorting.matchByName ? "name" : "index";
+              matchingPoint = find(oldData, function (oldPoint) {
+                return (
+                  !oldPoint.touched &&
+                  oldPoint[matchKey] === optionsObject[matchKey]
+                );
+              });
+              // Add unmatched point as a new point
+              if (!matchingPoint) {
+                return void 0;
+              }
+            }
+            if (matchingPoint) {
+              pointIndex = matchingPoint && matchingPoint.index;
+              if (typeof pointIndex !== "undefined") {
+                matchedById = true;
+              }
+            }
+            // Search for the same X in the existing data set
+            if (typeof pointIndex === "undefined" && isNumber(x)) {
+              pointIndex = this.xData.indexOf(x, fromIndex);
+            }
+            // Reduce pointIndex if data is cropped
+            if (
+              pointIndex !== -1 &&
+              typeof pointIndex !== "undefined" &&
+              this.cropped
+            ) {
+              pointIndex =
+                pointIndex >= this.cropStart
+                  ? pointIndex - this.cropStart
+                  : pointIndex;
+            }
+            if (
+              !matchedById &&
+              oldData[pointIndex] &&
+              oldData[pointIndex].touched
+            ) {
+              pointIndex = void 0;
+            }
+            return pointIndex;
+          },
+          /**
+           * @private
+           * @borrows LegendSymbolMixin.drawLineMarker as Highcharts.Series#drawLegendSymbol
+           */
+          drawLegendSymbol: LegendSymbolMixin.drawLineMarker,
+          /**
+           * Internal function called from setData. If the point count is the same
+           * as is was, or if there are overlapping X values, just run
+           * Point.update which is cheaper, allows animation, and keeps references
+           * to points. This also allows adding or removing points if the X-es
+           * don't match.
+           *
+           * @private
+           * @function Highcharts.Series#updateData
+           *
+           * @param {Array<Highcharts.PointOptionsType>} data
+           *
+           * @return {boolean}
+           */
+          updateData: function (data, animation) {
+            var options = this.options,
+              dataSorting = options.dataSorting,
+              oldData = this.points,
+              pointsToAdd = [],
+              hasUpdatedByKey,
+              i,
+              point,
+              lastIndex,
+              requireSorting = this.requireSorting,
+              equalLength = data.length === oldData.length,
+              succeeded = true;
+            this.xIncrement = null;
+            // Iterate the new data
+            data.forEach(function (pointOptions, i) {
+              var id,
+                x,
+                pointIndex,
+                optionsObject =
+                  (defined(pointOptions) &&
+                    this.pointClass.prototype.optionsToObject.call(
+                      { series: this },
+                      pointOptions
+                    )) ||
+                  {};
+              // Get the x of the new data point
+              x = optionsObject.x;
+              id = optionsObject.id;
+              if (id || isNumber(x)) {
+                pointIndex = this.findPointIndex(optionsObject, lastIndex);
+                // Matching X not found
+                // or used already due to ununique x values (#8995),
+                // add point (but later)
+                if (pointIndex === -1 || typeof pointIndex === "undefined") {
+                  pointsToAdd.push(pointOptions);
+                  // Matching X found, update
+                } else if (
+                  oldData[pointIndex] &&
+                  pointOptions !== options.data[pointIndex]
+                ) {
+                  oldData[pointIndex].update(pointOptions, false, null, false);
+                  // Mark it touched, below we will remove all points that
+                  // are not touched.
+                  oldData[pointIndex].touched = true;
+                  // Speed optimize by only searching after last known
+                  // index. Performs ~20% bettor on large data sets.
+                  if (requireSorting) {
+                    lastIndex = pointIndex + 1;
+                  }
+                  // Point exists, no changes, don't remove it
+                } else if (oldData[pointIndex]) {
+                  oldData[pointIndex].touched = true;
+                }
+                // If the length is equal and some of the nodes had a
+                // match in the same position, we don't want to remove
+                // non-matches.
+                if (
+                  !equalLength ||
+                  i !== pointIndex ||
+                  (dataSorting && dataSorting.enabled) ||
+                  this.hasDerivedData
+                ) {
+                  hasUpdatedByKey = true;
+                }
+              } else {
+                // Gather all points that are not matched
+                pointsToAdd.push(pointOptions);
+              }
+            }, this);
+            // Remove points that don't exist in the updated data set
+            if (hasUpdatedByKey) {
+              i = oldData.length;
+              while (i--) {
+                point = oldData[i];
+                if (point && !point.touched && point.remove) {
+                  point.remove(false, animation);
+                }
+              }
+              // If we did not find keys (ids or x-values), and the length is the
+              // same, update one-to-one
+            } else if (equalLength && (!dataSorting || !dataSorting.enabled)) {
+              data.forEach(function (point, i) {
+                // .update doesn't exist on a linked, hidden series (#3709)
+                // (#10187)
+                if (oldData[i].update && point !== oldData[i].y) {
+                  oldData[i].update(point, false, null, false);
+                }
+              });
+              // Don't add new points since those configs are used above
+              pointsToAdd.length = 0;
+              // Did not succeed in updating data
+            } else {
+              succeeded = false;
+            }
+            oldData.forEach(function (point) {
+              if (point) {
+                point.touched = false;
+              }
+            });
+            if (!succeeded) {
+              return false;
+            }
+            // Add new points
+            pointsToAdd.forEach(function (point) {
+              this.addPoint(point, false, null, null, false);
+            }, this);
+            if (this.xIncrement === null && this.xData && this.xData.length) {
+              this.xIncrement = arrayMax(this.xData);
+              this.autoIncrement();
+            }
+            return true;
+          },
+          /**
+           * Apply a new set of data to the series and optionally redraw it. The
+           * new data array is passed by reference (except in case of
+           * `updatePoints`), and may later be mutated when updating the chart
+           * data.
+           *
+           * Note the difference in behaviour when setting the same amount of
+           * points, or a different amount of points, as handled by the
+           * `updatePoints` parameter.
+           *
+           * @sample highcharts/members/series-setdata/
+           *         Set new data from a button
+           * @sample highcharts/members/series-setdata-pie/
+           *         Set data in a pie
+           * @sample stock/members/series-setdata/
+           *         Set new data in Highstock
+           * @sample maps/members/series-setdata/
+           *         Set new data in Highmaps
+           *
+           * @function Highcharts.Series#setData
+           *
+           * @param {Array<Highcharts.PointOptionsType>} data
+           *        Takes an array of data in the same format as described under
+           *        `series.{type}.data` for the given series type, for example a
+           *        line series would take data in the form described under
+           *        [series.line.data](https://api.highcharts.com/highcharts/series.line.data).
+           *
+           * @param {boolean} [redraw=true]
+           *        Whether to redraw the chart after the series is altered. If
+           *        doing more operations on the chart, it is a good idea to set
+           *        redraw to false and call {@link Chart#redraw} after.
+           *
+           * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation]
+           *        When the updated data is the same length as the existing data,
+           *        points will be updated by default, and animation visualizes
+           *        how the points are changed. Set false to disable animation, or
+           *        a configuration object to set duration or easing.
+           *
+           * @param {boolean} [updatePoints=true]
+           *        When this is true, points will be updated instead of replaced
+           *        whenever possible. This occurs a) when the updated data is the
+           *        same length as the existing data, b) when points are matched
+           *        by their id's, or c) when points can be matched by X values.
+           *        This allows updating with animation and performs better. In
+           *        this case, the original array is not passed by reference. Set
+           *        `false` to prevent.
+           *
+           * @return {void}
+           */
+          setData: function (data, redraw, animation, updatePoints) {
+            var series = this,
+              oldData = series.points,
+              oldDataLength = (oldData && oldData.length) || 0,
+              dataLength,
+              options = series.options,
+              chart = series.chart,
+              dataSorting = options.dataSorting,
+              firstPoint = null,
+              xAxis = series.xAxis,
+              i,
+              turboThreshold = options.turboThreshold,
+              pt,
+              xData = this.xData,
+              yData = this.yData,
+              pointArrayMap = series.pointArrayMap,
+              valueCount = pointArrayMap && pointArrayMap.length,
+              keys = options.keys,
+              indexOfX = 0,
+              indexOfY = 1,
+              updatedData;
+            data = data || [];
+            dataLength = data.length;
+            redraw = pick(redraw, true);
+            if (dataSorting && dataSorting.enabled) {
+              data = this.sortData(data);
+            }
+            // First try to run Point.update which is cheaper, allows animation,
+            // and keeps references to points.
+            if (
+              updatePoints !== false &&
+              dataLength &&
+              oldDataLength &&
+              !series.cropped &&
+              !series.hasGroupedData &&
+              series.visible &&
+              // Soft updating has no benefit in boost, and causes JS error
+              // (#8355)
+              !series.isSeriesBoosting
+            ) {
+              updatedData = this.updateData(data, animation);
+            }
+            if (!updatedData) {
+              // Reset properties
+              series.xIncrement = null;
+              series.colorCounter = 0; // for series with colorByPoint (#1547)
+              // Update parallel arrays
+              this.parallelArrays.forEach(function (key) {
+                series[key + "Data"].length = 0;
+              });
+              // In turbo mode, only one- or twodimensional arrays of numbers
+              // are allowed. The first value is tested, and we assume that
+              // all the rest are defined the same way. Although the 'for'
+              // loops are similar, they are repeated inside each if-else
+              // conditional for max performance.
+              if (turboThreshold && dataLength > turboThreshold) {
+                firstPoint = series.getFirstValidPoint(data);
+                if (isNumber(firstPoint)) {
+                  // assume all points are numbers
+                  for (i = 0; i < dataLength; i++) {
+                    xData[i] = this.autoIncrement();
+                    yData[i] = data[i];
+                  }
+                  // Assume all points are arrays when first point is
+                } else if (isArray(firstPoint)) {
+                  if (valueCount) {
+                    // [x, low, high] or [x, o, h, l, c]
+                    for (i = 0; i < dataLength; i++) {
+                      pt = data[i];
+                      xData[i] = pt[0];
+                      yData[i] = pt.slice(1, valueCount + 1);
+                    }
+                  } else {
+                    // [x, y]
+                    if (keys) {
+                      indexOfX = keys.indexOf("x");
+                      indexOfY = keys.indexOf("y");
+                      indexOfX = indexOfX >= 0 ? indexOfX : 0;
+                      indexOfY = indexOfY >= 0 ? indexOfY : 1;
                     }
-                    // Handle ignore hidden slices
-                    if (ignoreHiddenPoint) {
-                        series.isDirty = true;
+                    for (i = 0; i < dataLength; i++) {
+                      pt = data[i];
+                      xData[i] = pt[indexOfX];
+                      yData[i] = pt[indexOfY];
                     }
-                    if (redraw) {
-                        chart.redraw();
+                  }
+                } else {
+                  // Highcharts expects configs to be numbers or arrays in
+                  // turbo mode
+                  error(12, false, chart);
+                }
+              } else {
+                for (i = 0; i < dataLength; i++) {
+                  // stray commas in oldIE:
+                  if (typeof data[i] !== "undefined") {
+                    pt = { series: series };
+                    series.pointClass.prototype.applyOptions.apply(pt, [
+                      data[i],
+                    ]);
+                    series.updateParallelArrays(pt, i);
+                  }
+                }
+              }
+              // Forgetting to cast strings to numbers is a common caveat when
+              // handling CSV or JSON
+              if (yData && isString(yData[0])) {
+                error(14, true, chart);
+              }
+              series.data = [];
+              series.options.data = series.userOptions.data = data;
+              // destroy old points
+              i = oldDataLength;
+              while (i--) {
+                if (oldData[i] && oldData[i].destroy) {
+                  oldData[i].destroy();
+                }
+              }
+              // reset minRange (#878)
+              if (xAxis) {
+                xAxis.minRange = xAxis.userMinRange;
+              }
+              // redraw
+              series.isDirty = chart.isDirtyBox = true;
+              series.isDirtyData = !!oldData;
+              animation = false;
+            }
+            // Typically for pie series, points need to be processed and
+            // generated prior to rendering the legend
+            if (options.legendType === "point") {
+              this.processData();
+              this.generatePoints();
+            }
+            if (redraw) {
+              chart.redraw(animation);
+            }
+          },
+          /**
+           * Internal function to sort series data
+           *
+           * @private
+           * @function Highcharts.Series#sortData
+           * @param {Array<Highcharts.PointOptionsType>} data
+           *        Force data grouping.
+           * @return {Array<Highcharts.PointOptionsObject>}
+           */
+          sortData: function (data) {
+            var series = this,
+              options = series.options,
+              dataSorting = options.dataSorting,
+              sortKey = dataSorting.sortKey || "y",
+              sortedData,
+              getPointOptionsObject = function (series, pointOptions) {
+                return (
+                  (defined(pointOptions) &&
+                    series.pointClass.prototype.optionsToObject.call(
+                      {
+                        series: series,
+                      },
+                      pointOptions
+                    )) ||
+                  {}
+                );
+              };
+            data.forEach(function (pointOptions, i) {
+              data[i] = getPointOptionsObject(series, pointOptions);
+              data[i].index = i;
+            }, this);
+            // Sorting
+            sortedData = data.concat().sort(function (a, b) {
+              var aValue = getNestedProperty(sortKey, a);
+              var bValue = getNestedProperty(sortKey, b);
+              return bValue < aValue ? -1 : bValue > aValue ? 1 : 0;
+            });
+            // Set x value depending on the position in the array
+            sortedData.forEach(function (point, i) {
+              point.x = i;
+            }, this);
+            // Set the same x for linked series points if they don't have their
+            // own sorting
+            if (series.linkedSeries) {
+              series.linkedSeries.forEach(function (linkedSeries) {
+                var options = linkedSeries.options,
+                  seriesData = options.data;
+                if (
+                  (!options.dataSorting || !options.dataSorting.enabled) &&
+                  seriesData
+                ) {
+                  seriesData.forEach(function (pointOptions, i) {
+                    seriesData[i] = getPointOptionsObject(
+                      linkedSeries,
+                      pointOptions
+                    );
+                    if (data[i]) {
+                      seriesData[i].x = data[i].x;
+                      seriesData[i].index = i;
                     }
+                  });
+                  linkedSeries.setData(seriesData, false);
                 }
-            },
-            /**
-             * Set or toggle whether the slice is cut out from the pie
-             *
-             * @private
-             * @function Highcharts.seriesTypes.pie#pointClass#slice
-             * @param {boolean} sliced
-             *        When undefined, the slice state is toggled.
-             * @param {boolean} redraw
-             *        Whether to redraw the chart. True by default.
-             * @param {boolean|Partial<Highcharts.AnimationOptionsObject>}
-             *        Animation options.
-             * @return {void}
-             */
-            slice: function (sliced, redraw, animation) {
-                var point = this,
-                    series = point.series,
-                    chart = series.chart;
-                setAnimation(animation, chart);
-                // redraw is true by default
-                redraw = pick(redraw, true);
+              });
+            }
+            return data;
+          },
+          /**
+           * Internal function to process the data by cropping away unused data
+           * points if the series is longer than the crop threshold. This saves
+           * computing time for large series.
+           *
+           * @private
+           * @function Highcharts.Series#getProcessedData
+           * @param {boolean} [forceExtremesFromAll]
+           *        Force getting extremes of a total series data range.
+           * @return {Highcharts.SeriesProcessedDataObject}
+           */
+          getProcessedData: function (forceExtremesFromAll) {
+            var series = this,
+              // copied during slice operation:
+              processedXData = series.xData,
+              processedYData = series.yData,
+              dataLength = processedXData.length,
+              croppedData,
+              cropStart = 0,
+              cropped,
+              distance,
+              closestPointRange,
+              xAxis = series.xAxis,
+              i, // loop variable
+              options = series.options,
+              cropThreshold = options.cropThreshold,
+              getExtremesFromAll =
+                forceExtremesFromAll ||
+                series.getExtremesFromAll ||
+                options.getExtremesFromAll, // #4599
+              isCartesian = series.isCartesian,
+              xExtremes,
+              val2lin = xAxis && xAxis.val2lin,
+              isLog = !!(xAxis && xAxis.logarithmic),
+              throwOnUnsorted = series.requireSorting,
+              min,
+              max;
+            if (xAxis) {
+              // corrected for log axis (#3053)
+              xExtremes = xAxis.getExtremes();
+              min = xExtremes.min;
+              max = xExtremes.max;
+            }
+            // optionally filter out points outside the plot area
+            if (
+              isCartesian &&
+              series.sorted &&
+              !getExtremesFromAll &&
+              (!cropThreshold || dataLength > cropThreshold || series.forceCrop)
+            ) {
+              // it's outside current extremes
+              if (
+                processedXData[dataLength - 1] < min ||
+                processedXData[0] > max
+              ) {
+                processedXData = [];
+                processedYData = [];
+                // only crop if it's actually spilling out
+              } else if (
+                series.yData &&
+                (processedXData[0] < min ||
+                  processedXData[dataLength - 1] > max)
+              ) {
+                croppedData = this.cropData(
+                  series.xData,
+                  series.yData,
+                  min,
+                  max
+                );
+                processedXData = croppedData.xData;
+                processedYData = croppedData.yData;
+                cropStart = croppedData.start;
+                cropped = true;
+              }
+            }
+            // Find the closest distance between processed points
+            i = processedXData.length || 1;
+            while (--i) {
+              distance = isLog
+                ? val2lin(processedXData[i]) - val2lin(processedXData[i - 1])
+                : processedXData[i] - processedXData[i - 1];
+              if (
+                distance > 0 &&
+                (typeof closestPointRange === "undefined" ||
+                  distance < closestPointRange)
+              ) {
+                closestPointRange = distance;
+                // Unsorted data is not supported by the line tooltip, as well
+                // as data grouping and navigation in Stock charts (#725) and
+                // width calculation of columns (#1900)
+              } else if (distance < 0 && throwOnUnsorted) {
+                error(15, false, series.chart);
+                throwOnUnsorted = false; // Only once
+              }
+            }
+            return {
+              xData: processedXData,
+              yData: processedYData,
+              cropped: cropped,
+              cropStart: cropStart,
+              closestPointRange: closestPointRange,
+            };
+          },
+          /**
+           * Internal function to apply processed data.
+           * In Highstock, this function is extended to provide data grouping.
+           *
+           * @private
+           * @function Highcharts.Series#processData
+           * @param {boolean} [force]
+           *        Force data grouping.
+           * @return {boolean|undefined}
+           */
+          processData: function (force) {
+            var series = this,
+              xAxis = series.xAxis,
+              processedData;
+            // If the series data or axes haven't changed, don't go through
+            // this. Return false to pass the message on to override methods
+            // like in data grouping.
+            if (
+              series.isCartesian &&
+              !series.isDirty &&
+              !xAxis.isDirty &&
+              !series.yAxis.isDirty &&
+              !force
+            ) {
+              return false;
+            }
+            processedData = series.getProcessedData();
+            // Record the properties
+            series.cropped = processedData.cropped; // undefined or true
+            series.cropStart = processedData.cropStart;
+            series.processedXData = processedData.xData;
+            series.processedYData = processedData.yData;
+            series.closestPointRange = series.basePointRange =
+              processedData.closestPointRange;
+          },
+          /**
+           * Iterate over xData and crop values between min and max. Returns
+           * object containing crop start/end cropped xData with corresponding
+           * part of yData, dataMin and dataMax within the cropped range.
+           *
+           * @private
+           * @function Highcharts.Series#cropData
+           * @param {Array<number>} xData
+           * @param {Array<number>} yData
+           * @param {number} min
+           * @param {number} max
+           * @param {number} [cropShoulder]
+           * @return {Highcharts.SeriesCropDataObject}
+           */
+          cropData: function (xData, yData, min, max, cropShoulder) {
+            var dataLength = xData.length,
+              cropStart = 0,
+              cropEnd = dataLength,
+              i,
+              j;
+            // line-type series need one point outside
+            cropShoulder = pick(cropShoulder, this.cropShoulder);
+            // iterate up to find slice start
+            for (i = 0; i < dataLength; i++) {
+              if (xData[i] >= min) {
+                cropStart = Math.max(0, i - cropShoulder);
+                break;
+              }
+            }
+            // proceed to find slice end
+            for (j = i; j < dataLength; j++) {
+              if (xData[j] > max) {
+                cropEnd = j + cropShoulder;
+                break;
+              }
+            }
+            return {
+              xData: xData.slice(cropStart, cropEnd),
+              yData: yData.slice(cropStart, cropEnd),
+              start: cropStart,
+              end: cropEnd,
+            };
+          },
+          /**
+           * Generate the data point after the data has been processed by cropping
+           * away unused points and optionally grouped in Highcharts Stock.
+           *
+           * @private
+           * @function Highcharts.Series#generatePoints
+           */
+          generatePoints: function () {
+            var series = this,
+              options = series.options,
+              dataOptions = options.data,
+              data = series.data,
+              dataLength,
+              processedXData = series.processedXData,
+              processedYData = series.processedYData,
+              PointClass = series.pointClass,
+              processedDataLength = processedXData.length,
+              cropStart = series.cropStart || 0,
+              cursor,
+              hasGroupedData = series.hasGroupedData,
+              keys = options.keys,
+              point,
+              points = [],
+              i;
+            if (!data && !hasGroupedData) {
+              var arr = [];
+              arr.length = dataOptions.length;
+              data = series.data = arr;
+            }
+            if (keys && hasGroupedData) {
+              // grouped data has already applied keys (#6590)
+              series.options.keys = false;
+            }
+            for (i = 0; i < processedDataLength; i++) {
+              cursor = cropStart + i;
+              if (!hasGroupedData) {
+                point = data[cursor];
+                // #970:
+                if (!point && typeof dataOptions[cursor] !== "undefined") {
+                  data[cursor] = point = new PointClass().init(
+                    series,
+                    dataOptions[cursor],
+                    processedXData[i]
+                  );
+                }
+              } else {
+                // splat the y data in case of ohlc data array
+                point = new PointClass().init(
+                  series,
+                  [processedXData[i]].concat(splat(processedYData[i]))
+                );
                 /**
-                 * Pie series only. Whether to display a slice offset from the
-                 * center.
-                 * @name Highcharts.Point#sliced
-                 * @type {boolean|undefined}
+                 * Highstock only. If a point object is created by data
+                 * grouping, it doesn't reflect actual points in the raw
+                 * data. In this case, the `dataGroup` property holds
+                 * information that points back to the raw data.
+                 *
+                 * - `dataGroup.start` is the index of the first raw data
+                 *   point in the group.
+                 *
+                 * - `dataGroup.length` is the amount of points in the
+                 *   group.
+                 *
+                 * @product highstock
+                 *
+                 * @name Highcharts.Point#dataGroup
+                 * @type {Highcharts.DataGroupingInfoObject|undefined}
                  */
-                // if called without an argument, toggle
-                point.sliced = point.options.sliced = sliced =
-                    defined(sliced) ? sliced : !point.sliced;
-                // update userOptions.data
-                series.options.data[series.data.indexOf(point)] =
-                    point.options;
-                if (point.graphic) {
-                    point.graphic.animate(this.getTranslate());
-                }
-                if (point.shadowGroup) {
-                    point.shadowGroup.animate(this.getTranslate());
+                point.dataGroup = series.groupMap[i];
+                if (point.dataGroup.options) {
+                  point.options = point.dataGroup.options;
+                  extend(point, point.dataGroup.options);
+                  // Collision of props and options (#9770)
+                  delete point.dataLabels;
                 }
-            },
+              }
+              if (point) {
+                // #6279
+                /**
+                 * Contains the point's index in the `Series.points` array.
+                 *
+                 * @name Highcharts.Point#index
+                 * @type {number}
+                 * @readonly
+                 */
+                point.index = cursor; // For faster access in Point.update
+                points[i] = point;
+              }
+            }
+            // restore keys options (#6590)
+            series.options.keys = keys;
+            // Hide cropped-away points - this only runs when the number of
+            // points is above cropThreshold, or when swithching view from
+            // non-grouped data to grouped data (#637)
+            if (
+              data &&
+              (processedDataLength !== (dataLength = data.length) ||
+                hasGroupedData)
+            ) {
+              for (i = 0; i < dataLength; i++) {
+                // when has grouped data, clear all points
+                if (i === cropStart && !hasGroupedData) {
+                  i += processedDataLength;
+                }
+                if (data[i]) {
+                  data[i].destroyElements();
+                  data[i].plotX = void 0; // #1003
+                }
+              }
+            }
             /**
-             * @private
-             * @function Highcharts.seriesTypes.pie#pointClass#getTranslate
-             * @return {Highcharts.TranslationAttributes}
-             */
-            getTranslate: function () {
-                return this.sliced ? this.slicedTranslation : {
-                    translateX: 0,
-                    translateY: 0
+             * Read only. An array containing those values converted to points.
+             * In case the series data length exceeds the `cropThreshold`, or if
+             * the data is grouped, `series.data` doesn't contain all the
+             * points. Also, in case a series is hidden, the `data` array may be
+             * empty. To access raw values, `series.options.data` will always be
+             * up to date. `Series.data` only contains the points that have been
+             * created on demand. To modify the data, use
+             * {@link Highcharts.Series#setData} or
+             * {@link Highcharts.Point#update}.
+             *
+             * @see Series.points
+             *
+             * @name Highcharts.Series#data
+             * @type {Array<Highcharts.Point>}
+             */
+            series.data = data;
+            /**
+             * An array containing all currently visible point objects. In case
+             * of cropping, the cropped-away points are not part of this array.
+             * The `series.points` array starts at `series.cropStart` compared
+             * to `series.data` and `series.options.data`. If however the series
+             * data is grouped, these can't be correlated one to one. To modify
+             * the data, use {@link Highcharts.Series#setData} or
+             * {@link Highcharts.Point#update}.
+             *
+             * @name Highcharts.Series#points
+             * @type {Array<Highcharts.Point>}
+             */
+            series.points = points;
+            fireEvent(this, "afterGeneratePoints");
+          },
+          /**
+           * Get current X extremes for the visible data.
+           *
+           * @private
+           * @function Highcharts.Series#getXExtremes
+           *
+           * @param {Array<number>} xData
+           *        The data to inspect. Defaults to the current data within the
+           *        visible range.
+           * @return {Highcharts.RangeObject}
+           */
+          getXExtremes: function (xData) {
+            return {
+              min: arrayMin(xData),
+              max: arrayMax(xData),
+            };
+          },
+          /**
+           * Calculate Y extremes for the visible data. The result is returned
+           * as an object with `dataMin` and `dataMax` properties.
+           *
+           * @private
+           * @function Highcharts.Series#getExtremes
+           * @param {Array<number>} [yData]
+           *        The data to inspect. Defaults to the current data within the
+           *        visible range.
+           * @param {boolean} [forceExtremesFromAll]
+           *        Force getting extremes of a total series data range.
+           * @return {Highcharts.DataExtremesObject}
+           */
+          getExtremes: function (yData, forceExtremesFromAll) {
+            var xAxis = this.xAxis,
+              yAxis = this.yAxis,
+              xData = this.processedXData || this.xData,
+              yDataLength,
+              activeYData = [],
+              activeCounter = 0,
+              // #2117, need to compensate for log X axis
+              xExtremes,
+              xMin = 0,
+              xMax = 0,
+              validValue,
+              withinRange,
+              // Handle X outside the viewed area. This does not work with
+              // non-sorted data like scatter (#7639).
+              shoulder = this.requireSorting ? this.cropShoulder : 0,
+              positiveValuesOnly = yAxis ? yAxis.positiveValuesOnly : false,
+              x,
+              y,
+              i,
+              j;
+            yData = yData || this.stackedYData || this.processedYData || [];
+            yDataLength = yData.length;
+            if (xAxis) {
+              xExtremes = xAxis.getExtremes();
+              xMin = xExtremes.min;
+              xMax = xExtremes.max;
+            }
+            for (i = 0; i < yDataLength; i++) {
+              x = xData[i];
+              y = yData[i];
+              // For points within the visible range, including the first
+              // point outside the visible range (#7061), consider y extremes.
+              validValue =
+                (isNumber(y) || isArray(y)) &&
+                (y.length || y > 0 || !positiveValuesOnly);
+              withinRange =
+                forceExtremesFromAll ||
+                this.getExtremesFromAll ||
+                this.options.getExtremesFromAll ||
+                this.cropped ||
+                !xAxis || // for colorAxis support
+                ((xData[i + shoulder] || x) >= xMin &&
+                  (xData[i - shoulder] || x) <= xMax);
+              if (validValue && withinRange) {
+                j = y.length;
+                if (j) {
+                  // array, like ohlc or range data
+                  while (j--) {
+                    if (isNumber(y[j])) {
+                      // #7380, #11513
+                      activeYData[activeCounter++] = y[j];
+                    }
+                  }
+                } else {
+                  activeYData[activeCounter++] = y;
+                }
+              }
+            }
+            var dataExtremes = {
+              dataMin: arrayMin(activeYData),
+              dataMax: arrayMax(activeYData),
+            };
+            fireEvent(this, "afterGetExtremes", { dataExtremes: dataExtremes });
+            return dataExtremes;
+          },
+          /**
+           * Set the current data extremes as `dataMin` and `dataMax` on the
+           * Series item. Use this only when the series properties should be
+           * updated.
+           *
+           * @private
+           * @function Highcharts.Series#applyExtremes
+           * @return {void}
+           */
+          applyExtremes: function () {
+            var dataExtremes = this.getExtremes();
+            /**
+             * Contains the minimum value of the series' data point. Some series
+             * types like `networkgraph` do not support this property as they
+             * lack a `y`-value.
+             * @name Highcharts.Series#dataMin
+             * @type {number|undefined}
+             * @readonly
+             */
+            this.dataMin = dataExtremes.dataMin;
+            /**
+             * Contains the maximum value of the series' data point. Some series
+             * types like `networkgraph` do not support this property as they
+             * lack a `y`-value.
+             * @name Highcharts.Series#dataMax
+             * @type {number|undefined}
+             * @readonly
+             */
+            this.dataMax = dataExtremes.dataMax;
+            return dataExtremes;
+          },
+          /**
+           * Find and return the first non null point in the data
+           *
+           * @private
+           * @function Highcharts.Series.getFirstValidPoint
+           * @param {Array<Highcharts.PointOptionsType>} data
+           *        Array of options for points
+           *
+           * @return {Highcharts.PointOptionsType}
+           */
+          getFirstValidPoint: function (data) {
+            var firstPoint = null,
+              dataLength = data.length,
+              i = 0;
+            while (firstPoint === null && i < dataLength) {
+              firstPoint = data[i];
+              i++;
+            }
+            return firstPoint;
+          },
+          /**
+           * Translate data points from raw data values to chart specific
+           * positioning data needed later in the `drawPoints` and `drawGraph`
+           * functions. This function can be overridden in plugins and custom
+           * series type implementations.
+           *
+           * @function Highcharts.Series#translate
+           * @return {void}
+           * @fires Highcharts.Series#events:translate
+           */
+          translate: function () {
+            if (!this.processedXData) {
+              // hidden series
+              this.processData();
+            }
+            this.generatePoints();
+            var series = this,
+              options = series.options,
+              stacking = options.stacking,
+              xAxis = series.xAxis,
+              categories = xAxis.categories,
+              enabledDataSorting = series.enabledDataSorting,
+              yAxis = series.yAxis,
+              points = series.points,
+              dataLength = points.length,
+              hasModifyValue = !!series.modifyValue,
+              i,
+              pointPlacement = series.pointPlacementToXValue(), // #7860
+              dynamicallyPlaced = Boolean(pointPlacement),
+              threshold = options.threshold,
+              stackThreshold = options.startFromThreshold ? threshold : 0,
+              plotX,
+              lastPlotX,
+              stackIndicator,
+              zoneAxis = this.zoneAxis || "y",
+              closestPointRangePx = Number.MAX_VALUE;
+            /**
+             * Plotted coordinates need to be within a limited range. Drawing
+             * too far outside the viewport causes various rendering issues
+             * (#3201, #3923, #7555).
+             * @private
+             */
+            function limitedRange(val) {
+              return clamp(val, -1e5, 1e5);
+            }
+            // Translate each point
+            for (i = 0; i < dataLength; i++) {
+              var point = points[i],
+                xValue = point.x,
+                yValue = point.y,
+                yBottom = point.low,
+                stack =
+                  stacking &&
+                  yAxis.stacking &&
+                  yAxis.stacking.stacks[
+                    (series.negStacks &&
+                    yValue < (stackThreshold ? 0 : threshold)
+                      ? "-"
+                      : "") + series.stackKey
+                  ],
+                pointStack,
+                stackValues;
+              if (
+                (yAxis.positiveValuesOnly &&
+                  !yAxis.validatePositiveValue(yValue)) ||
+                (xAxis.positiveValuesOnly &&
+                  !xAxis.validatePositiveValue(xValue))
+              ) {
+                point.isNull = true;
+              }
+              // Get the plotX translation
+              point.plotX = plotX = correctFloat(
+                // #5236
+                limitedRange(
+                  xAxis.translate(
+                    // #3923
+                    xValue,
+                    0,
+                    0,
+                    0,
+                    1,
+                    pointPlacement,
+                    this.type === "flags"
+                  )
+                ) // #3923
+              );
+              // Calculate the bottom y value for stacked series
+              if (stacking && series.visible && stack && stack[xValue]) {
+                stackIndicator = series.getStackIndicator(
+                  stackIndicator,
+                  xValue,
+                  series.index
+                );
+                if (!point.isNull) {
+                  pointStack = stack[xValue];
+                  stackValues = pointStack.points[stackIndicator.key];
+                }
+              }
+              if (isArray(stackValues)) {
+                yBottom = stackValues[0];
+                yValue = stackValues[1];
+                if (
+                  yBottom === stackThreshold &&
+                  stackIndicator.key === stack[xValue].base
+                ) {
+                  yBottom = pick(isNumber(threshold) && threshold, yAxis.min);
+                }
+                // #1200, #1232
+                if (yAxis.positiveValuesOnly && yBottom <= 0) {
+                  yBottom = null;
+                }
+                point.total = point.stackTotal = pointStack.total;
+                point.percentage =
+                  pointStack.total && (point.y / pointStack.total) * 100;
+                point.stackY = yValue;
+                // Place the stack label
+                // in case of variwide series (where widths of points are
+                // different in most cases), stack labels are positioned
+                // wrongly, so the call of the setOffset is omited here and
+                // labels are correctly positioned later, at the end of the
+                // variwide's translate function (#10962)
+                if (!series.irregularWidths) {
+                  pointStack.setOffset(
+                    series.pointXOffset || 0,
+                    series.barW || 0
+                  );
+                }
+              }
+              // Set translated yBottom or remove it
+              point.yBottom = defined(yBottom)
+                ? limitedRange(yAxis.translate(yBottom, 0, 1, 0, 1))
+                : null;
+              // general hook, used for Highstock compare mode
+              if (hasModifyValue) {
+                yValue = series.modifyValue(yValue, point);
+              }
+              // Set the the plotY value, reset it for redraws
+              // #3201
+              point.plotY =
+                typeof yValue === "number" && yValue !== Infinity
+                  ? limitedRange(yAxis.translate(yValue, 0, 1, 0, 1))
+                  : void 0;
+              point.isInside = this.isPointInside(point);
+              // Set client related positions for mouse tracking
+              point.clientX = dynamicallyPlaced
+                ? correctFloat(
+                    xAxis.translate(xValue, 0, 0, 0, 1, pointPlacement)
+                  )
+                : plotX; // #1514, #5383, #5518
+              // Negative points. For bubble charts, this means negative z
+              // values (#9728)
+              point.negative =
+                point[zoneAxis] <
+                (options[zoneAxis + "Threshold"] || threshold || 0);
+              // some API data
+              point.category =
+                categories && typeof categories[point.x] !== "undefined"
+                  ? categories[point.x]
+                  : point.x;
+              // Determine auto enabling of markers (#3635, #5099)
+              if (!point.isNull && point.visible !== false) {
+                if (typeof lastPlotX !== "undefined") {
+                  closestPointRangePx = Math.min(
+                    closestPointRangePx,
+                    Math.abs(plotX - lastPlotX)
+                  );
+                }
+                lastPlotX = plotX;
+              }
+              // Find point zone
+              point.zone = this.zones.length && point.getZone();
+              // Animate new points with data sorting
+              if (!point.graphic && series.group && enabledDataSorting) {
+                point.isNew = true;
+              }
+            }
+            series.closestPointRangePx = closestPointRangePx;
+            fireEvent(this, "afterTranslate");
+          },
+          /**
+           * Return the series points with null points filtered out.
+           *
+           * @function Highcharts.Series#getValidPoints
+           *
+           * @param {Array<Highcharts.Point>} [points]
+           *        The points to inspect, defaults to {@link Series.points}.
+           *
+           * @param {boolean} [insideOnly=false]
+           *        Whether to inspect only the points that are inside the visible
+           *        view.
+           *
+           * @param {boolean} [allowNull=false]
+           *        Whether to allow null points to pass as valid points.
+           *
+           * @return {Array<Highcharts.Point>}
+           *         The valid points.
+           */
+          getValidPoints: function (points, insideOnly, allowNull) {
+            var chart = this.chart;
+            // #3916, #5029, #5085
+            return (points || this.points || []).filter(function isValidPoint(
+              point
+            ) {
+              if (
+                insideOnly &&
+                !chart.isInsidePlot(point.plotX, point.plotY, chart.inverted)
+              ) {
+                return false;
+              }
+              return point.visible !== false && (allowNull || !point.isNull);
+            });
+          },
+          /**
+           * Get the clipping for the series. Could be called for a series to
+           * initiate animating the clip or to set the final clip (only width
+           * and x).
+           *
+           * @private
+           * @function Highcharts.Series#getClip
+           * @param  {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation]
+           *         Initialize the animation.
+           * @param  {boolean} [finalBox]
+           *         Final size for the clip - end state for the animation.
+           * @return {Highcharts.Dictionary<number>}
+           */
+          getClipBox: function (animation, finalBox) {
+            var series = this,
+              options = series.options,
+              chart = series.chart,
+              inverted = chart.inverted,
+              xAxis = series.xAxis,
+              yAxis = xAxis && series.yAxis,
+              clipBox,
+              scrollablePlotAreaOptions =
+                chart.options.chart.scrollablePlotArea || {};
+            if (animation && options.clip === false && yAxis) {
+              // support for not clipped series animation (#10450)
+              clipBox = inverted
+                ? {
+                    y: -chart.chartWidth + yAxis.len + yAxis.pos,
+                    height: chart.chartWidth,
+                    width: chart.chartHeight,
+                    x: -chart.chartHeight + xAxis.len + xAxis.pos,
+                  }
+                : {
+                    y: -yAxis.pos,
+                    height: chart.chartHeight,
+                    width: chart.chartWidth,
+                    x: -xAxis.pos,
+                  };
+              // x and width will be changed later when setting for animation
+              // initial state in Series.setClip
+            } else {
+              clipBox = series.clipBox || chart.clipBox;
+              if (finalBox) {
+                clipBox.width = chart.plotSizeX;
+                clipBox.x =
+                  (chart.scrollablePixelsX || 0) *
+                  (scrollablePlotAreaOptions.scrollPositionX || 0);
+              }
+            }
+            return !finalBox
+              ? clipBox
+              : {
+                  width: clipBox.width,
+                  x: clipBox.x,
                 };
-            },
-            /**
-             * @private
-             * @function Highcharts.seriesTypes.pie#pointClass#haloPath
-             * @param {number} size
-             * @return {Highcharts.SVGPathArray}
-             */
-            haloPath: function (size) {
-                var shapeArgs = this.shapeArgs;
-                return this.sliced || !this.visible ?
-                    [] :
-                    this.series.chart.renderer.symbols.arc(shapeArgs.x, shapeArgs.y, shapeArgs.r + size, shapeArgs.r + size, {
-                        // Substract 1px to ensure the background is not bleeding
-                        // through between the halo and the slice (#7495).
-                        innerR: shapeArgs.r - 1,
-                        start: shapeArgs.start,
-                        end: shapeArgs.end
-                    });
-            },
-            connectorShapes: {
-                // only one available before v7.0.0
-                fixedOffset: function (labelPosition, connectorPosition, options) {
-                    var breakAt = connectorPosition.breakAt,
-                        touchingSliceAt = connectorPosition.touchingSliceAt,
-                        lineSegment = options.softConnector ? [
-                            'C',
-                            // 1st control point (of the curve)
-                            labelPosition.x +
-                                // 5 gives the connector a little horizontal bend
-                                (labelPosition.alignment === 'left' ? -5 : 5),
-                            labelPosition.y,
-                            2 * breakAt.x - touchingSliceAt.x,
-                            2 * breakAt.y - touchingSliceAt.y,
-                            breakAt.x,
-                            breakAt.y //
-                        ] : [
-                            'L',
-                            breakAt.x,
-                            breakAt.y
-                        ];
-                    // assemble the path
-                    return ([
-                        ['M', labelPosition.x, labelPosition.y],
-                        lineSegment,
-                        ['L', touchingSliceAt.x, touchingSliceAt.y]
-                    ]);
-                },
-                straight: function (labelPosition, connectorPosition) {
-                    var touchingSliceAt = connectorPosition.touchingSliceAt;
-                    // direct line to the slice
-                    return [
-                        ['M', labelPosition.x, labelPosition.y],
-                        ['L', touchingSliceAt.x, touchingSliceAt.y]
-                    ];
-                },
-                crookedLine: function (labelPosition, connectorPosition, options) {
-                    var touchingSliceAt = connectorPosition.touchingSliceAt,
-                        series = this.series,
-                        pieCenterX = series.center[0],
-                        plotWidth = series.chart.plotWidth,
-                        plotLeft = series.chart.plotLeft,
-                        alignment = labelPosition.alignment,
-                        radius = this.shapeArgs.r,
-                        crookDistance = relativeLength(// % to fraction
-                        options.crookDistance, 1),
-                        crookX = alignment === 'left' ?
-                            pieCenterX + radius + (plotWidth + plotLeft -
-                                pieCenterX - radius) * (1 - crookDistance) :
-                            plotLeft + (pieCenterX - radius) * crookDistance,
-                        segmentWithCrook = [
-                            'L',
-                            crookX,
-                            labelPosition.y
-                        ],
-                        useCrook = true;
-                    // crookedLine formula doesn't make sense if the path overlaps
-                    // the label - use straight line instead in that case
-                    if (alignment === 'left' ?
-                        (crookX > labelPosition.x || crookX < touchingSliceAt.x) :
-                        (crookX < labelPosition.x || crookX > touchingSliceAt.x)) {
-                        useCrook = false;
-                    }
-                    // assemble the path
-                    var path = [
-                            ['M',
-                        labelPosition.x,
-                        labelPosition.y]
-                        ];
-                    if (useCrook) {
-                        path.push(segmentWithCrook);
-                    }
-                    path.push(['L', touchingSliceAt.x, touchingSliceAt.y]);
-                    return path;
-                }
-            },
-            /**
-             * Extendable method for getting the path of the connector between the
-             * data label and the pie slice.
-             */
-            getConnectorPath: function () {
-                var labelPosition = this.labelPosition,
-                    options = this.series.options.dataLabels,
-                    connectorShape = options.connectorShape,
-                    predefinedShapes = this.connectorShapes;
-                // find out whether to use the predefined shape
-                if (predefinedShapes[connectorShape]) {
-                    connectorShape = predefinedShapes[connectorShape];
+          },
+          /**
+           * Set the clipping for the series. For animated series it is called
+           * twice, first to initiate animating the clip then the second time
+           * without the animation to set the final clip.
+           *
+           * @private
+           * @function Highcharts.Series#setClip
+           * @param {boolean|Highcharts.AnimationOptionsObject} [animation]
+           */
+          setClip: function (animation) {
+            var chart = this.chart,
+              options = this.options,
+              renderer = chart.renderer,
+              inverted = chart.inverted,
+              seriesClipBox = this.clipBox,
+              clipBox = this.getClipBox(animation),
+              sharedClipKey =
+                this.sharedClipKey ||
+                [
+                  "_sharedClip",
+                  animation && animation.duration,
+                  animation && animation.easing,
+                  clipBox.height,
+                  options.xAxis,
+                  options.yAxis,
+                ].join(","), // #4526
+              clipRect = chart[sharedClipKey],
+              markerClipRect = chart[sharedClipKey + "m"];
+            if (animation) {
+              clipBox.width = 0;
+              if (inverted) {
+                clipBox.x =
+                  chart.plotHeight +
+                  (options.clip !== false ? 0 : chart.plotTop);
+              }
+            }
+            // If a clipping rectangle with the same properties is currently
+            // present in the chart, use that.
+            if (!clipRect) {
+              // When animation is set, prepare the initial positions
+              if (animation) {
+                chart[sharedClipKey + "m"] = markerClipRect = renderer.clipRect(
+                  // include the width of the first marker
+                  inverted ? chart.plotSizeX + 99 : -99,
+                  inverted ? -chart.plotLeft : -chart.plotTop,
+                  99,
+                  inverted ? chart.chartWidth : chart.chartHeight
+                );
+              }
+              chart[sharedClipKey] = clipRect = renderer.clipRect(clipBox);
+              // Create hashmap for series indexes
+              clipRect.count = { length: 0 };
+              // When the series is rendered again before starting animating, in
+              // compliance to a responsive rule
+            } else if (!chart.hasLoaded) {
+              clipRect.attr(clipBox);
+            }
+            if (animation) {
+              if (!clipRect.count[this.index]) {
+                clipRect.count[this.index] = true;
+                clipRect.count.length += 1;
+              }
+            }
+            if (options.clip !== false || animation) {
+              this.group.clip(
+                animation || seriesClipBox ? clipRect : chart.clipRect
+              );
+              this.markerGroup.clip(markerClipRect);
+              this.sharedClipKey = sharedClipKey;
+            }
+            // Remove the shared clipping rectangle when all series are shown
+            if (!animation) {
+              if (clipRect.count[this.index]) {
+                delete clipRect.count[this.index];
+                clipRect.count.length -= 1;
+              }
+              if (
+                clipRect.count.length === 0 &&
+                sharedClipKey &&
+                chart[sharedClipKey]
+              ) {
+                if (!seriesClipBox) {
+                  chart[sharedClipKey] = chart[sharedClipKey].destroy();
+                }
+                if (chart[sharedClipKey + "m"]) {
+                  chart[sharedClipKey + "m"] =
+                    chart[sharedClipKey + "m"].destroy();
+                }
+              }
+            }
+          },
+          /**
+           * Animate in the series. Called internally twice. First with the `init`
+           * parameter set to true, which sets up the initial state of the
+           * animation. Then when ready, it is called with the `init` parameter
+           * undefined, in order to perform the actual animation. After the
+           * second run, the function is removed.
+           *
+           * @function Highcharts.Series#animate
+           *
+           * @param {boolean} [init]
+           *        Initialize the animation.
+           */
+          animate: function (init) {
+            var series = this,
+              chart = series.chart,
+              animation = animObject(series.options.animation),
+              clipRect,
+              sharedClipKey,
+              finalBox;
+            // Initialize the animation. Set up the clipping rectangle.
+            if (!chart.hasRendered) {
+              if (init) {
+                series.setClip(animation);
+                // Run the animation
+              } else {
+                sharedClipKey = this.sharedClipKey;
+                clipRect = chart[sharedClipKey];
+                finalBox = series.getClipBox(animation, true);
+                if (clipRect) {
+                  clipRect.animate(finalBox, animation);
+                }
+                if (chart[sharedClipKey + "m"]) {
+                  chart[sharedClipKey + "m"].animate(
+                    {
+                      width: finalBox.width + 99,
+                      x: finalBox.x - (chart.inverted ? 0 : 99),
+                    },
+                    animation
+                  );
                 }
-                return connectorShape.call(this, {
-                    // pass simplified label position object for user's convenience
-                    x: labelPosition.final.x,
-                    y: labelPosition.final.y,
-                    alignment: labelPosition.alignment
-                }, labelPosition.connectorPosition, options);
+              }
             }
-        }
-        /* eslint-enable valid-jsdoc */
-        );
-        /**
-         * A `pie` series. If the [type](#series.pie.type) option is not specified,
-         * it is inherited from [chart.type](#chart.type).
-         *
-         * @extends   series,plotOptions.pie
-         * @excluding cropThreshold, dataParser, dataURL, stack, xAxis, yAxis,
-         *            dataSorting, step, boostThreshold, boostBlending
-         * @product   highcharts
-         * @apioption series.pie
-         */
-        /**
-         * An array of data points for the series. For the `pie` series type,
-         * points can be given in the following ways:
-         *
-         * 1. An array of numerical values. In this case, the numerical values will be
-         *    interpreted as `y` options. Example:
-         *    ```js
-         *    data: [0, 5, 3, 5]
-         *    ```
-         *
-         * 2. An array of objects with named values. The following snippet shows only a
-         *    few settings, see the complete options set below. If the total number of
-         *    data points exceeds the series'
-         *    [turboThreshold](#series.pie.turboThreshold),
-         *    this option is not available.
-         *    ```js
-         *    data: [{
-         *        y: 1,
-         *        name: "Point2",
-         *        color: "#00FF00"
-         *    }, {
-         *        y: 7,
-         *        name: "Point1",
-         *        color: "#FF00FF"
-         *    }]
-         *    ```
-         *
-         * @sample {highcharts} highcharts/chart/reflow-true/
-         *         Numerical values
-         * @sample {highcharts} highcharts/series/data-array-of-arrays/
-         *         Arrays of numeric x and y
-         * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
-         *         Arrays of datetime x and y
-         * @sample {highcharts} highcharts/series/data-array-of-name-value/
-         *         Arrays of point.name and y
-         * @sample {highcharts} highcharts/series/data-array-of-objects/
-         *         Config objects
-         *
-         * @type      {Array<number|Array<string,(number|null)>|null|*>}
-         * @extends   series.line.data
-         * @excluding marker, x
-         * @product   highcharts
-         * @apioption series.pie.data
-         */
-        /**
-         * @type      {Highcharts.SeriesPieDataLabelsOptionsObject}
-         * @product   highcharts
-         * @apioption series.pie.data.dataLabels
-         */
-        /**
-         * The sequential index of the data point in the legend.
-         *
-         * @type      {number}
-         * @product   highcharts
-         * @apioption series.pie.data.legendIndex
-         */
-        /**
-         * Whether to display a slice offset from the center.
-         *
-         * @sample {highcharts} highcharts/point/sliced/
-         *         One sliced point
-         *
-         * @type      {boolean}
-         * @product   highcharts
-         * @apioption series.pie.data.sliced
-         */
-        /**
-         * @excluding legendItemClick
-         * @product   highcharts
-         * @apioption series.pie.events
-         */
-        ''; // placeholder for transpiled doclets above
-
-    });
-    _registerModule(_modules, 'Core/Series/DataLabels.js', [_modules['Core/Animation/AnimationUtilities.js'], _modules['Core/Globals.js'], _modules['Core/Series/CartesianSeries.js'], _modules['Core/Utilities.js']], function (A, H, CartesianSeries, U) {
-        /* *
-         *
-         *  (c) 2010-2020 Torstein Honsi
-         *
-         *  License: www.highcharts.com/license
-         *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
-         *
-         * */
-        var getDeferredAnimation = A.getDeferredAnimation;
-        var noop = H.noop,
-            seriesTypes = H.seriesTypes;
-        var arrayMax = U.arrayMax,
-            clamp = U.clamp,
-            defined = U.defined,
-            extend = U.extend,
-            fireEvent = U.fireEvent,
-            format = U.format,
-            isArray = U.isArray,
-            merge = U.merge,
-            objectEach = U.objectEach,
-            pick = U.pick,
-            relativeLength = U.relativeLength,
-            splat = U.splat,
-            stableSort = U.stableSort;
-        /**
-         * Callback JavaScript function to format the data label as a string. Note that
-         * if a `format` is defined, the format takes precedence and the formatter is
-         * ignored.
-         *
-         * @callback Highcharts.DataLabelsFormatterCallbackFunction
-         *
-         * @param {Highcharts.PointLabelObject} this
-         * Data label context to format
-         *
-         * @param {Highcharts.DataLabelsOptions} options
-         * [API options](/highcharts/plotOptions.series.dataLabels) of the data label
-         *
-         * @return {number|string|null|undefined}
-         * Formatted data label text
-         */
-        /**
-         * Values for handling data labels that flow outside the plot area.
-         *
-         * @typedef {"allow"|"justify"} Highcharts.DataLabelsOverflowValue
-         */
-        ''; // detach doclets above
-        /* eslint-disable valid-jsdoc */
-        /**
-         * General distribution algorithm for distributing labels of differing size
-         * along a confined length in two dimensions. The algorithm takes an array of
-         * objects containing a size, a target and a rank. It will place the labels as
-         * close as possible to their targets, skipping the lowest ranked labels if
-         * necessary.
-         *
-         * @private
-         * @function Highcharts.distribute
-         * @param {Highcharts.DataLabelsBoxArray} boxes
-         * @param {number} len
-         * @param {number} [maxDistance]
-         * @return {void}
-         */
-        H.distribute = function (boxes, len, maxDistance) {
-            var i,
-                overlapping = true,
-                origBoxes = boxes, // Original array will be altered with added .pos
-                restBoxes = [], // The outranked overshoot
-                box,
-                target,
-                total = 0,
-                reducedLen = origBoxes.reducedLen || len;
-            /**
-             * @private
-             */
-            function sortByTarget(a, b) {
-                return a.target - b.target;
+          },
+          /**
+           * This runs after animation to land on the final plot clipping.
+           *
+           * @private
+           * @function Highcharts.Series#afterAnimate
+           * @fires Highcharts.Series#event:afterAnimate
+           */
+          afterAnimate: function () {
+            this.setClip();
+            fireEvent(this, "afterAnimate");
+            this.finishedAnimating = true;
+          },
+          /**
+           * Draw the markers for line-like series types, and columns or other
+           * graphical representation for {@link Point} objects for other series
+           * types. The resulting element is typically stored as
+           * {@link Point.graphic}, and is created on the first call and updated
+           * and moved on subsequent calls.
+           *
+           * @function Highcharts.Series#drawPoints
+           */
+          drawPoints: function () {
+            var series = this,
+              points = series.points,
+              chart = series.chart,
+              i,
+              point,
+              graphic,
+              verb,
+              options = series.options,
+              seriesMarkerOptions = options.marker,
+              pointMarkerOptions,
+              hasPointMarker,
+              markerGroup = series[series.specialGroup] || series.markerGroup,
+              xAxis = series.xAxis,
+              markerAttribs,
+              globallyEnabled = pick(
+                seriesMarkerOptions.enabled,
+                !xAxis || xAxis.isRadial ? true : null,
+                // Use larger or equal as radius is null in bubbles (#6321)
+                series.closestPointRangePx >=
+                  seriesMarkerOptions.enabledThreshold *
+                    seriesMarkerOptions.radius
+              );
+            if (
+              seriesMarkerOptions.enabled !== false ||
+              series._hasPointMarkers
+            ) {
+              for (i = 0; i < points.length; i++) {
+                point = points[i];
+                graphic = point.graphic;
+                verb = graphic ? "animate" : "attr";
+                pointMarkerOptions = point.marker || {};
+                hasPointMarker = !!point.marker;
+                var shouldDrawMarker =
+                  ((globallyEnabled &&
+                    typeof pointMarkerOptions.enabled === "undefined") ||
+                    pointMarkerOptions.enabled) &&
+                  !point.isNull &&
+                  point.visible !== false;
+                // only draw the point if y is defined
+                if (shouldDrawMarker) {
+                  // Shortcuts
+                  var symbol = pick(pointMarkerOptions.symbol, series.symbol);
+                  markerAttribs = series.markerAttribs(
+                    point,
+                    point.selected && "select"
+                  );
+                  // Set starting position for point sliding animation.
+                  if (series.enabledDataSorting) {
+                    point.startXPos = xAxis.reversed
+                      ? -markerAttribs.width
+                      : xAxis.width;
+                  }
+                  var isInside = point.isInside !== false;
+                  if (graphic) {
+                    // update
+                    // Since the marker group isn't clipped, each
+                    // individual marker must be toggled
+                    graphic[isInside ? "show" : "hide"](isInside).animate(
+                      markerAttribs
+                    );
+                  } else if (
+                    isInside &&
+                    (markerAttribs.width > 0 || point.hasImage)
+                  ) {
+                    /**
+                     * The graphic representation of the point.
+                     * Typically this is a simple shape, like a `rect`
+                     * for column charts or `path` for line markers, but
+                     * for some complex series types like boxplot or 3D
+                     * charts, the graphic may be a `g` element
+                     * containing other shapes. The graphic is generated
+                     * the first time {@link Series#drawPoints} runs,
+                     * and updated and moved on subsequent runs.
+                     *
+                     * @name Point#graphic
+                     * @type {SVGElement}
+                     */
+                    point.graphic = graphic = chart.renderer
+                      .symbol(
+                        symbol,
+                        markerAttribs.x,
+                        markerAttribs.y,
+                        markerAttribs.width,
+                        markerAttribs.height,
+                        hasPointMarker
+                          ? pointMarkerOptions
+                          : seriesMarkerOptions
+                      )
+                      .add(markerGroup);
+                    // Sliding animation for new points
+                    if (series.enabledDataSorting && chart.hasRendered) {
+                      graphic.attr({
+                        x: point.startXPos,
+                      });
+                      verb = "animate";
+                    }
+                  }
+                  if (graphic && verb === "animate") {
+                    // update
+                    // Since the marker group isn't clipped, each
+                    // individual marker must be toggled
+                    graphic[isInside ? "show" : "hide"](isInside).animate(
+                      markerAttribs
+                    );
+                  }
+                  // Presentational attributes
+                  if (graphic && !chart.styledMode) {
+                    graphic[verb](
+                      series.pointAttribs(point, point.selected && "select")
+                    );
+                  }
+                  if (graphic) {
+                    graphic.addClass(point.getClassName(), true);
+                  }
+                } else if (graphic) {
+                  point.graphic = graphic.destroy(); // #1269
+                }
+              }
+            }
+          },
+          /**
+           * Get non-presentational attributes for a point. Used internally for
+           * both styled mode and classic. Can be overridden for different series
+           * types.
+           *
+           * @see Series#pointAttribs
+           *
+           * @function Highcharts.Series#markerAttribs
+           *
+           * @param {Highcharts.Point} point
+           *        The Point to inspect.
+           *
+           * @param {string} [state]
+           *        The state, can be either `hover`, `select` or undefined.
+           *
+           * @return {Highcharts.SVGAttributes}
+           *         A hash containing those attributes that are not settable from
+           *         CSS.
+           */
+          markerAttribs: function (point, state) {
+            var seriesOptions = this.options,
+              seriesMarkerOptions = seriesOptions.marker,
+              seriesStateOptions,
+              pointMarkerOptions = point.marker || {},
+              symbol = pointMarkerOptions.symbol || seriesMarkerOptions.symbol,
+              pointStateOptions,
+              radius = pick(
+                pointMarkerOptions.radius,
+                seriesMarkerOptions.radius
+              ),
+              attribs;
+            // Handle hover and select states
+            if (state) {
+              seriesStateOptions = seriesMarkerOptions.states[state];
+              pointStateOptions =
+                pointMarkerOptions.states && pointMarkerOptions.states[state];
+              radius = pick(
+                pointStateOptions && pointStateOptions.radius,
+                seriesStateOptions && seriesStateOptions.radius,
+                radius +
+                  ((seriesStateOptions && seriesStateOptions.radiusPlus) || 0)
+              );
+            }
+            point.hasImage = symbol && symbol.indexOf("url") === 0;
+            if (point.hasImage) {
+              radius = 0; // and subsequently width and height is not set
+            }
+            attribs = {
+              // Math.floor for #1843:
+              x: seriesOptions.crisp
+                ? Math.floor(point.plotX) - radius
+                : point.plotX - radius,
+              y: point.plotY - radius,
+            };
+            if (radius) {
+              attribs.width = attribs.height = 2 * radius;
+            }
+            return attribs;
+          },
+          /**
+           * Internal function to get presentational attributes for each point.
+           * Unlike {@link Series#markerAttribs}, this function should return
+           * those attributes that can also be set in CSS. In styled mode,
+           * `pointAttribs` won't be called.
+           *
+           * @private
+           * @function Highcharts.Series#pointAttribs
+           *
+           * @param {Highcharts.Point} [point]
+           *        The point instance to inspect.
+           *
+           * @param {string} [state]
+           *        The point state, can be either `hover`, `select` or 'normal'.
+           *        If undefined, normal state is assumed.
+           *
+           * @return {Highcharts.SVGAttributes}
+           *         The presentational attributes to be set on the point.
+           */
+          pointAttribs: function (point, state) {
+            var seriesMarkerOptions = this.options.marker,
+              seriesStateOptions,
+              pointOptions = point && point.options,
+              pointMarkerOptions = (pointOptions && pointOptions.marker) || {},
+              pointStateOptions,
+              color = this.color,
+              pointColorOption = pointOptions && pointOptions.color,
+              pointColor = point && point.color,
+              strokeWidth = pick(
+                pointMarkerOptions.lineWidth,
+                seriesMarkerOptions.lineWidth
+              ),
+              zoneColor = point && point.zone && point.zone.color,
+              fill,
+              stroke,
+              opacity = 1;
+            color = pointColorOption || zoneColor || pointColor || color;
+            fill =
+              pointMarkerOptions.fillColor ||
+              seriesMarkerOptions.fillColor ||
+              color;
+            stroke =
+              pointMarkerOptions.lineColor ||
+              seriesMarkerOptions.lineColor ||
+              color;
+            // Handle hover and select states
+            state = state || "normal";
+            if (state) {
+              seriesStateOptions = seriesMarkerOptions.states[state];
+              pointStateOptions =
+                (pointMarkerOptions.states &&
+                  pointMarkerOptions.states[state]) ||
+                {};
+              strokeWidth = pick(
+                pointStateOptions.lineWidth,
+                seriesStateOptions.lineWidth,
+                strokeWidth +
+                  pick(
+                    pointStateOptions.lineWidthPlus,
+                    seriesStateOptions.lineWidthPlus,
+                    0
+                  )
+              );
+              fill =
+                pointStateOptions.fillColor ||
+                seriesStateOptions.fillColor ||
+                fill;
+              stroke =
+                pointStateOptions.lineColor ||
+                seriesStateOptions.lineColor ||
+                stroke;
+              opacity = pick(
+                pointStateOptions.opacity,
+                seriesStateOptions.opacity,
+                opacity
+              );
+            }
+            return {
+              stroke: stroke,
+              "stroke-width": strokeWidth,
+              fill: fill,
+              opacity: opacity,
+            };
+          },
+          /**
+           * Clear DOM objects and free up memory.
+           *
+           * @private
+           * @function Highcharts.Series#destroy
+           * @param {boolean} [keepEventsForUpdate]
+           * @return {void}
+           * @fires Highcharts.Series#event:destroy
+           */
+          destroy: function (keepEventsForUpdate) {
+            var series = this,
+              chart = series.chart,
+              issue134 = /AppleWebKit\/533/.test(win.navigator.userAgent),
+              destroy,
+              i,
+              data = series.data || [],
+              point,
+              axis;
+            // add event hook
+            fireEvent(series, "destroy");
+            // remove events
+            this.removeEvents(keepEventsForUpdate);
+            // erase from axes
+            (series.axisTypes || []).forEach(function (AXIS) {
+              axis = series[AXIS];
+              if (axis && axis.series) {
+                erase(axis.series, series);
+                axis.isDirty = axis.forceRedraw = true;
+              }
+            });
+            // remove legend items
+            if (series.legendItem) {
+              series.chart.legend.destroyItem(series);
             }
-            // If the total size exceeds the len, remove those boxes with the lowest
-            // rank
-            i = boxes.length;
+            // destroy all points with their elements
+            i = data.length;
             while (i--) {
-                total += boxes[i].size;
+              point = data[i];
+              if (point && point.destroy) {
+                point.destroy();
+              }
             }
-            // Sort by rank, then slice away overshoot
-            if (total > reducedLen) {
-                stableSort(boxes, function (a, b) {
-                    return (b.rank || 0) - (a.rank || 0);
-                });
-                i = 0;
-                total = 0;
-                while (total <= reducedLen) {
-                    total += boxes[i].size;
-                    i++;
-                }
-                restBoxes = boxes.splice(i - 1, boxes.length);
+            series.points = null;
+            // Clear the animation timeout if we are destroying the series
+            // during initial animation
+            U.clearTimeout(series.animationTimeout);
+            // Destroy all SVGElements associated to the series
+            objectEach(series, function (val, prop) {
+              // Survive provides a hook for not destroying
+              if (val instanceof SVGElement && !val.survive) {
+                // issue 134 workaround
+                destroy = issue134 && prop === "group" ? "hide" : "destroy";
+                val[destroy]();
+              }
+            });
+            // remove from hoverSeries
+            if (chart.hoverSeries === series) {
+              chart.hoverSeries = null;
             }
-            // Order by target
-            stableSort(boxes, sortByTarget);
-            // So far we have been mutating the original array. Now
-            // create a copy with target arrays
-            boxes = boxes.map(function (box) {
-                return {
-                    size: box.size,
-                    targets: [box.target],
-                    align: pick(box.align, 0.5)
-                };
+            erase(chart.series, series);
+            chart.orderSeries();
+            // clear all members
+            objectEach(series, function (val, prop) {
+              if (!keepEventsForUpdate || prop !== "hcEvents") {
+                delete series[prop];
+              }
             });
-            while (overlapping) {
-                // Initial positions: target centered in box
-                i = boxes.length;
-                while (i--) {
-                    box = boxes[i];
-                    // Composite box, average of targets
-                    target = (Math.min.apply(0, box.targets) +
-                        Math.max.apply(0, box.targets)) / 2;
-                    box.pos = clamp(target - box.size * box.align, 0, len - box.size);
-                }
-                // Detect overlap and join boxes
-                i = boxes.length;
-                overlapping = false;
-                while (i--) {
-                    // Overlap
-                    if (i > 0 &&
-                        boxes[i - 1].pos + boxes[i - 1].size >
-                            boxes[i].pos) {
-                        // Add this size to the previous box
-                        boxes[i - 1].size += boxes[i].size;
-                        boxes[i - 1].targets = boxes[i - 1]
-                            .targets
-                            .concat(boxes[i].targets);
-                        boxes[i - 1].align = 0.5;
-                        // Overlapping right, push left
-                        if (boxes[i - 1].pos + boxes[i - 1].size > len) {
-                            boxes[i - 1].pos = len - boxes[i - 1].size;
-                        }
-                        boxes.splice(i, 1); // Remove this item
-                        overlapping = true;
-                    }
-                }
+          },
+          /**
+           * Get the graph path.
+           *
+           * @private
+           * @function Highcharts.Series#getGraphPath
+           * @param {Array<Highcharts.Point>} points
+           * @param {boolean} [nullsAsZeroes]
+           * @param {boolean} [connectCliffs]
+           * @return {Highcharts.SVGPathArray}
+           */
+          getGraphPath: function (points, nullsAsZeroes, connectCliffs) {
+            var series = this,
+              options = series.options,
+              step = options.step,
+              reversed,
+              graphPath = [],
+              xMap = [],
+              gap;
+            points = points || series.points;
+            // Bottom of a stack is reversed
+            reversed = points.reversed;
+            if (reversed) {
+              points.reverse();
             }
-            // Add the rest (hidden boxes)
-            origBoxes.push.apply(origBoxes, restBoxes);
-            // Now the composite boxes are placed, we need to put the original boxes
-            // within them
-            i = 0;
-            boxes.some(function (box) {
-                var posInCompositeBox = 0;
-                if (box.targets.some(function () {
-                    origBoxes[i].pos = box.pos + posInCompositeBox;
-                    // If the distance between the position and the target exceeds
-                    // maxDistance, abort the loop and decrease the length in increments
-                    // of 10% to recursively reduce the  number of visible boxes by
-                    // rank. Once all boxes are within the maxDistance, we're good.
-                    if (typeof maxDistance !== 'undefined' &&
-                        Math.abs(origBoxes[i].pos - origBoxes[i].target) > maxDistance) {
-                        // Reset the positions that are already set
-                        origBoxes.slice(0, i + 1).forEach(function (box) {
-                            delete box.pos;
-                        });
-                        // Try with a smaller length
-                        origBoxes.reducedLen =
-                            (origBoxes.reducedLen || len) - (len * 0.1);
-                        // Recurse
-                        if (origBoxes.reducedLen > len * 0.1) {
-                            H.distribute(origBoxes, len, maxDistance);
-                        }
-                        // Exceeded maxDistance => abort
-                        return true;
-                    }
-                    posInCompositeBox += origBoxes[i].size;
-                    i++;
-                })) {
-                    // Exceeded maxDistance => abort
-                    return true;
-                }
+            // Reverse the steps (#5004)
+            step =
+              {
+                right: 1,
+                center: 2,
+              }[step] ||
+              (step && 3);
+            if (step && reversed) {
+              step = 4 - step;
+            }
+            // Remove invalid points, especially in spline (#5015)
+            points = this.getValidPoints(
+              points,
+              false,
+              !(options.connectNulls && !nullsAsZeroes && !connectCliffs)
+            );
+            // Build the line
+            points.forEach(function (point, i) {
+              var plotX = point.plotX,
+                plotY = point.plotY,
+                lastPoint = points[i - 1],
+                // the path to this point from the previous
+                pathToPoint;
+              if (
+                (point.leftCliff || (lastPoint && lastPoint.rightCliff)) &&
+                !connectCliffs
+              ) {
+                gap = true; // ... and continue
+              }
+              // Line series, nullsAsZeroes is not handled
+              if (point.isNull && !defined(nullsAsZeroes) && i > 0) {
+                gap = !options.connectNulls;
+                // Area series, nullsAsZeroes is set
+              } else if (point.isNull && !nullsAsZeroes) {
+                gap = true;
+              } else {
+                if (i === 0 || gap) {
+                  pathToPoint = [["M", point.plotX, point.plotY]];
+                  // Generate the spline as defined in the SplineSeries object
+                } else if (series.getPointSpline) {
+                  pathToPoint = [series.getPointSpline(points, point, i)];
+                } else if (step) {
+                  if (step === 1) {
+                    // right
+                    pathToPoint = [["L", lastPoint.plotX, plotY]];
+                  } else if (step === 2) {
+                    // center
+                    pathToPoint = [
+                      ["L", (lastPoint.plotX + plotX) / 2, lastPoint.plotY],
+                      ["L", (lastPoint.plotX + plotX) / 2, plotY],
+                    ];
+                  } else {
+                    pathToPoint = [["L", plotX, lastPoint.plotY]];
+                  }
+                  pathToPoint.push(["L", plotX, plotY]);
+                } else {
+                  // normal line to next point
+                  pathToPoint = [["L", plotX, plotY]];
+                }
+                // Prepare for animation. When step is enabled, there are
+                // two path nodes for each x value.
+                xMap.push(point.x);
+                if (step) {
+                  xMap.push(point.x);
+                  if (step === 2) {
+                    // step = center (#8073)
+                    xMap.push(point.x);
+                  }
+                }
+                graphPath.push.apply(graphPath, pathToPoint);
+                gap = false;
+              }
             });
-            // Add the rest (hidden) boxes and sort by target
-            stableSort(origBoxes, sortByTarget);
-        };
-        /**
-         * Draw the data labels
-         *
-         * @private
-         * @function Highcharts.Series#drawDataLabels
-         * @return {void}
-         * @fires Highcharts.Series#event:afterDrawDataLabels
-         */
-        CartesianSeries.prototype.drawDataLabels = function () {
+            graphPath.xMap = xMap;
+            series.graphPath = graphPath;
+            return graphPath;
+          },
+          /**
+           * Draw the graph. Called internally when rendering line-like series
+           * types. The first time it generates the `series.graph` item and
+           * optionally other series-wide items like `series.area` for area
+           * charts. On subsequent calls these items are updated with new
+           * positions and attributes.
+           *
+           * @function Highcharts.Series#drawGraph
+           */
+          drawGraph: function () {
+            var series = this,
+              options = this.options,
+              graphPath = (this.gappedPath || this.getGraphPath).call(this),
+              styledMode = this.chart.styledMode,
+              props = [["graph", "highcharts-graph"]];
+            // Presentational properties
+            if (!styledMode) {
+              props[0].push(
+                options.lineColor || this.color || "#cccccc", // when colorByPoint = true
+                options.dashStyle
+              );
+            }
+            props = series.getZonesGraphs(props);
+            // Draw the graph
+            props.forEach(function (prop, i) {
+              var graphKey = prop[0],
+                graph = series[graphKey],
+                verb = graph ? "animate" : "attr",
+                attribs;
+              if (graph) {
+                graph.endX = series.preventGraphAnimation
+                  ? null
+                  : graphPath.xMap;
+                graph.animate({ d: graphPath });
+              } else if (graphPath.length) {
+                // #1487
+                /**
+                 * SVG element of area-based charts. Can be used for styling
+                 * purposes. If zones are configured, this element will be
+                 * hidden and replaced by multiple zone areas, accessible
+                 * via `series['zone-area-x']` (where x is a number,
+                 * starting with 0).
+                 *
+                 * @name Highcharts.Series#area
+                 * @type {Highcharts.SVGElement|undefined}
+                 */
+                /**
+                 * SVG element of line-based charts. Can be used for styling
+                 * purposes. If zones are configured, this element will be
+                 * hidden and replaced by multiple zone lines, accessible
+                 * via `series['zone-graph-x']` (where x is a number,
+                 * starting with 0).
+                 *
+                 * @name Highcharts.Series#graph
+                 * @type {Highcharts.SVGElement|undefined}
+                 */
+                series[graphKey] = graph = series.chart.renderer
+                  .path(graphPath)
+                  .addClass(prop[1])
+                  .attr({ zIndex: 1 }) // #1069
+                  .add(series.group);
+              }
+              if (graph && !styledMode) {
+                attribs = {
+                  stroke: prop[2],
+                  "stroke-width": options.lineWidth,
+                  // Polygon series use filled graph
+                  fill: (series.fillGraph && series.color) || "none",
+                };
+                if (prop[3]) {
+                  attribs.dashstyle = prop[3];
+                } else if (options.linecap !== "square") {
+                  attribs["stroke-linecap"] = attribs["stroke-linejoin"] =
+                    "round";
+                }
+                graph[verb](attribs)
+                  // Add shadow to normal series (0) or to first
+                  // zone (1) #3932
+                  .shadow(i < 2 && options.shadow);
+              }
+              // Helpers for animation
+              if (graph) {
+                graph.startX = graphPath.xMap;
+                graph.isArea = graphPath.isArea; // For arearange animation
+              }
+            });
+          },
+          /**
+           * Get zones properties for building graphs. Extendable by series with
+           * multiple lines within one series.
+           *
+           * @private
+           * @function Highcharts.Series#getZonesGraphs
+           *
+           * @param {Array<Array<string>>} props
+           *
+           * @return {Array<Array<string>>}
+           */
+          getZonesGraphs: function (props) {
+            // Add the zone properties if any
+            this.zones.forEach(function (zone, i) {
+              var propset = [
+                "zone-graph-" + i,
+                "highcharts-graph highcharts-zone-graph-" +
+                  i +
+                  " " +
+                  (zone.className || ""),
+              ];
+              if (!this.chart.styledMode) {
+                propset.push(
+                  zone.color || this.color,
+                  zone.dashStyle || this.options.dashStyle
+                );
+              }
+              props.push(propset);
+            }, this);
+            return props;
+          },
+          /**
+           * Clip the graphs into zones for colors and styling.
+           *
+           * @private
+           * @function Highcharts.Series#applyZones
+           * @return {void}
+           */
+          applyZones: function () {
+            var series = this,
+              chart = this.chart,
+              renderer = chart.renderer,
+              zones = this.zones,
+              translatedFrom,
+              translatedTo,
+              clips = this.clips || [],
+              clipAttr,
+              graph = this.graph,
+              area = this.area,
+              chartSizeMax = Math.max(chart.chartWidth, chart.chartHeight),
+              axis = this[(this.zoneAxis || "y") + "Axis"],
+              extremes,
+              reversed,
+              inverted = chart.inverted,
+              horiz,
+              pxRange,
+              pxPosMin,
+              pxPosMax,
+              ignoreZones = false,
+              zoneArea,
+              zoneGraph;
+            if (
+              zones.length &&
+              (graph || area) &&
+              axis &&
+              typeof axis.min !== "undefined"
+            ) {
+              reversed = axis.reversed;
+              horiz = axis.horiz;
+              // The use of the Color Threshold assumes there are no gaps
+              // so it is safe to hide the original graph and area
+              // unless it is not waterfall series, then use showLine property
+              // to set lines between columns to be visible (#7862)
+              if (graph && !this.showLine) {
+                graph.hide();
+              }
+              if (area) {
+                area.hide();
+              }
+              // Create the clips
+              extremes = axis.getExtremes();
+              zones.forEach(function (threshold, i) {
+                translatedFrom = reversed
+                  ? horiz
+                    ? chart.plotWidth
+                    : 0
+                  : horiz
+                  ? 0
+                  : axis.toPixels(extremes.min) || 0;
+                translatedFrom = clamp(
+                  pick(translatedTo, translatedFrom),
+                  0,
+                  chartSizeMax
+                );
+                translatedTo = clamp(
+                  Math.round(
+                    axis.toPixels(pick(threshold.value, extremes.max), true) ||
+                      0
+                  ),
+                  0,
+                  chartSizeMax
+                );
+                if (ignoreZones) {
+                  translatedFrom = translatedTo = axis.toPixels(extremes.max);
+                }
+                pxRange = Math.abs(translatedFrom - translatedTo);
+                pxPosMin = Math.min(translatedFrom, translatedTo);
+                pxPosMax = Math.max(translatedFrom, translatedTo);
+                if (axis.isXAxis) {
+                  clipAttr = {
+                    x: inverted ? pxPosMax : pxPosMin,
+                    y: 0,
+                    width: pxRange,
+                    height: chartSizeMax,
+                  };
+                  if (!horiz) {
+                    clipAttr.x = chart.plotHeight - clipAttr.x;
+                  }
+                } else {
+                  clipAttr = {
+                    x: 0,
+                    y: inverted ? pxPosMax : pxPosMin,
+                    width: chartSizeMax,
+                    height: pxRange,
+                  };
+                  if (horiz) {
+                    clipAttr.y = chart.plotWidth - clipAttr.y;
+                  }
+                }
+                // VML SUPPPORT
+                if (inverted && renderer.isVML) {
+                  if (axis.isXAxis) {
+                    clipAttr = {
+                      x: 0,
+                      y: reversed ? pxPosMin : pxPosMax,
+                      height: clipAttr.width,
+                      width: chart.chartWidth,
+                    };
+                  } else {
+                    clipAttr = {
+                      x: clipAttr.y - chart.plotLeft - chart.spacingBox.x,
+                      y: 0,
+                      width: clipAttr.height,
+                      height: chart.chartHeight,
+                    };
+                  }
+                }
+                // END OF VML SUPPORT
+                if (clips[i]) {
+                  clips[i].animate(clipAttr);
+                } else {
+                  clips[i] = renderer.clipRect(clipAttr);
+                }
+                // when no data, graph zone is not applied and after setData
+                // clip was ignored. As a result, it should be applied each
+                // time.
+                zoneArea = series["zone-area-" + i];
+                zoneGraph = series["zone-graph-" + i];
+                if (graph && zoneGraph) {
+                  zoneGraph.clip(clips[i]);
+                }
+                if (area && zoneArea) {
+                  zoneArea.clip(clips[i]);
+                }
+                // if this zone extends out of the axis, ignore the others
+                ignoreZones = threshold.value > extremes.max;
+                // Clear translatedTo for indicators
+                if (series.resetZones && translatedTo === 0) {
+                  translatedTo = void 0;
+                }
+              });
+              this.clips = clips;
+            } else if (series.visible) {
+              // If zones were removed, restore graph and area
+              if (graph) {
+                graph.show(true);
+              }
+              if (area) {
+                area.show(true);
+              }
+            }
+          },
+          /**
+           * Initialize and perform group inversion on series.group and
+           * series.markerGroup.
+           *
+           * @private
+           * @function Highcharts.Series#invertGroups
+           * @param {boolean} [inverted]
+           * @return {void}
+           */
+          invertGroups: function (inverted) {
             var series = this,
-                chart = series.chart,
-                seriesOptions = series.options,
-                seriesDlOptions = seriesOptions.dataLabels,
-                points = series.points,
-                pointOptions,
-                hasRendered = series.hasRendered || 0,
-                dataLabelsGroup,
-                dataLabelAnim = seriesDlOptions.animation,
-                animationConfig = seriesDlOptions.defer ?
-                    getDeferredAnimation(chart,
-                dataLabelAnim,
-                series) :
-                    { defer: 0,
-                duration: 0 },
-                renderer = chart.renderer;
+              chart = series.chart;
             /**
-             * Handle the dataLabels.filter option.
              * @private
              */
-            function applyFilter(point, options) {
-                var filter = options.filter,
-                    op,
-                    prop,
-                    val;
-                if (filter) {
-                    op = filter.operator;
-                    prop = point[filter.property];
-                    val = filter.value;
-                    if ((op === '>' && prop > val) ||
-                        (op === '<' && prop < val) ||
-                        (op === '>=' && prop >= val) ||
-                        (op === '<=' && prop <= val) ||
-                        (op === '==' && prop == val) || // eslint-disable-line eqeqeq
-                        (op === '===' && prop === val)) {
-                        return true;
+            function setInvert() {
+              ["group", "markerGroup"].forEach(function (groupName) {
+                if (series[groupName]) {
+                  // VML/HTML needs explicit attributes for flipping
+                  if (chart.renderer.isVML) {
+                    series[groupName].attr({
+                      width: series.yAxis.len,
+                      height: series.xAxis.len,
+                    });
+                  }
+                  series[groupName].width = series.yAxis.len;
+                  series[groupName].height = series.xAxis.len;
+                  // If inverted polar, don't invert series group
+                  series[groupName].invert(
+                    series.isRadialSeries ? false : inverted
+                  );
+                }
+              });
+            }
+            // Pie, go away (#1736)
+            if (!series.xAxis) {
+              return;
+            }
+            // A fixed size is needed for inversion to work
+            series.eventsToUnbind.push(addEvent(chart, "resize", setInvert));
+            // Do it now
+            setInvert();
+            // On subsequent render and redraw, just do setInvert without
+            // setting up events again
+            series.invertGroups = setInvert;
+          },
+          /**
+           * General abstraction for creating plot groups like series.group,
+           * series.dataLabelsGroup and series.markerGroup. On subsequent calls,
+           * the group will only be adjusted to the updated plot size.
+           *
+           * @private
+           * @function Highcharts.Series#plotGroup
+           * @param {string} prop
+           * @param {string} name
+           * @param {string} visibility
+           * @param {number} [zIndex]
+           * @param {Highcharts.SVGElement} [parent]
+           * @return {Highcharts.SVGElement}
+           */
+          plotGroup: function (prop, name, visibility, zIndex, parent) {
+            var group = this[prop],
+              isNew = !group,
+              attrs = {
+                visibility: visibility,
+                zIndex: zIndex || 0.1, // IE8 and pointer logic use this
+              };
+            // Avoid setting undefined opacity, or in styled mode
+            if (
+              typeof this.opacity !== "undefined" &&
+              !this.chart.styledMode &&
+              this.state !== "inactive" // #13719
+            ) {
+              attrs.opacity = this.opacity;
+            }
+            // Generate it on first call
+            if (isNew) {
+              this[prop] = group = this.chart.renderer.g().add(parent);
+            }
+            // Add the class names, and replace existing ones as response to
+            // Series.update (#6660)
+            group.addClass(
+              "highcharts-" +
+                name +
+                " highcharts-series-" +
+                this.index +
+                " highcharts-" +
+                this.type +
+                "-series " +
+                (defined(this.colorIndex)
+                  ? "highcharts-color-" + this.colorIndex + " "
+                  : "") +
+                (this.options.className || "") +
+                (group.hasClass("highcharts-tracker")
+                  ? " highcharts-tracker"
+                  : ""),
+              true
+            );
+            // Place it on first and subsequent (redraw) calls
+            group.attr(attrs)[isNew ? "attr" : "animate"](this.getPlotBox());
+            return group;
+          },
+          /**
+           * Get the translation and scale for the plot area of this series.
+           *
+           * @function Highcharts.Series#getPlotBox
+           *
+           * @return {Highcharts.SeriesPlotBoxObject}
+           */
+          getPlotBox: function () {
+            var chart = this.chart,
+              xAxis = this.xAxis,
+              yAxis = this.yAxis;
+            // Swap axes for inverted (#2339)
+            if (chart.inverted) {
+              xAxis = yAxis;
+              yAxis = this.xAxis;
+            }
+            return {
+              translateX: xAxis ? xAxis.left : chart.plotLeft,
+              translateY: yAxis ? yAxis.top : chart.plotTop,
+              scaleX: 1,
+              scaleY: 1,
+            };
+          },
+          /**
+           * Removes the event handlers attached previously with addEvents.
+           *
+           * @private
+           * @function Highcharts.Series#removeEvents
+           * @param {boolean} [keepEventsForUpdate]
+           * @return {void}
+           */
+          removeEvents: function (keepEventsForUpdate) {
+            var series = this;
+            if (!keepEventsForUpdate) {
+              // remove all events
+              removeEvent(series);
+            } else if (series.eventsToUnbind.length) {
+              // remove only internal events for proper update
+              // #12355 - solves problem with multiple destroy events
+              series.eventsToUnbind.forEach(function (unbind) {
+                unbind();
+              });
+              series.eventsToUnbind.length = 0;
+            }
+          },
+          /**
+           * Render the graph and markers. Called internally when first rendering
+           * and later when redrawing the chart. This function can be extended in
+           * plugins, but normally shouldn't be called directly.
+           *
+           * @function Highcharts.Series#render
+           *
+           * @return {void}
+           *
+           * @fires Highcharts.Series#event:afterRender
+           */
+          render: function () {
+            var series = this,
+              chart = series.chart,
+              group,
+              options = series.options,
+              animOptions = animObject(options.animation),
+              // Animation doesn't work in IE8 quirks when the group div is
+              // hidden, and looks bad in other oldIE
+              animDuration =
+                !series.finishedAnimating &&
+                chart.renderer.isSVG &&
+                animOptions.duration,
+              visibility = series.visible ? "inherit" : "hidden", // #2597
+              zIndex = options.zIndex,
+              hasRendered = series.hasRendered,
+              chartSeriesGroup = chart.seriesGroup,
+              inverted = chart.inverted;
+            fireEvent(this, "render");
+            // the group
+            group = series.plotGroup(
+              "group",
+              "series",
+              visibility,
+              zIndex,
+              chartSeriesGroup
+            );
+            series.markerGroup = series.plotGroup(
+              "markerGroup",
+              "markers",
+              visibility,
+              zIndex,
+              chartSeriesGroup
+            );
+            // initiate the animation
+            if (animDuration && series.animate) {
+              series.animate(true);
+            }
+            // SVGRenderer needs to know this before drawing elements (#1089,
+            // #1795)
+            group.inverted =
+              series.isCartesian || series.invertable ? inverted : false;
+            // Draw the graph if any
+            if (series.drawGraph) {
+              series.drawGraph();
+              series.applyZones();
+            }
+            // Draw the points
+            if (series.visible) {
+              series.drawPoints();
+            }
+            /* series.points.forEach(function (point) {
+                    if (point.redraw) {
+                        point.redraw();
                     }
-                    return false;
-                }
-                return true;
+                }); */
+            // Draw the data labels
+            if (series.drawDataLabels) {
+              series.drawDataLabels();
+            }
+            // In pie charts, slices are added to the DOM, but actual rendering
+            // is postponed until labels reserved their space
+            if (series.redrawPoints) {
+              series.redrawPoints();
             }
+            // draw the mouse tracking area
+            if (
+              series.drawTracker &&
+              series.options.enableMouseTracking !== false
+            ) {
+              series.drawTracker();
+            }
+            // Handle inverted series and tracker groups
+            series.invertGroups(inverted);
+            // Initial clipping, must be defined after inverting groups for VML.
+            // Applies to columns etc. (#3839).
+            if (
+              options.clip !== false &&
+              !series.sharedClipKey &&
+              !hasRendered
+            ) {
+              group.clip(chart.clipRect);
+            }
+            // Run the animation
+            if (animDuration && series.animate) {
+              series.animate();
+            }
+            // Call the afterAnimate function on animation complete (but don't
+            // overwrite the animation.complete option which should be available
+            // to the user).
+            if (!hasRendered) {
+              // Additional time if defer is defined before afterAnimate
+              // will be triggered
+              if (animDuration && animOptions.defer) {
+                animDuration += animOptions.defer;
+              }
+              series.animationTimeout = syncTimeout(function () {
+                series.afterAnimate();
+              }, animDuration || 0);
+            }
+            // Means data is in accordance with what you see
+            series.isDirty = false;
+            // (See #322) series.isDirty = series.isDirtyData = false; // means
+            // data is in accordance with what you see
+            series.hasRendered = true;
+            fireEvent(series, "afterRender");
+          },
+          /**
+           * Redraw the series. This function is called internally from
+           * `chart.redraw` and normally shouldn't be called directly.
+           *
+           * @private
+           * @function Highcharts.Series#redraw
+           * @return {void}
+           */
+          redraw: function () {
+            var series = this,
+              chart = series.chart,
+              // cache it here as it is set to false in render, but used after
+              wasDirty = series.isDirty || series.isDirtyData,
+              group = series.group,
+              xAxis = series.xAxis,
+              yAxis = series.yAxis;
+            // reposition on resize
+            if (group) {
+              if (chart.inverted) {
+                group.attr({
+                  width: chart.plotWidth,
+                  height: chart.plotHeight,
+                });
+              }
+              group.animate({
+                translateX: pick(xAxis && xAxis.left, chart.plotLeft),
+                translateY: pick(yAxis && yAxis.top, chart.plotTop),
+              });
+            }
+            series.translate();
+            series.render();
+            if (wasDirty) {
+              // #3868, #3945
+              delete this.kdTree;
+            }
+          },
+          kdAxisArray: ["clientX", "plotY"],
+          /**
+           * @private
+           * @function Highcharts.Series#searchPoint
+           * @param {Highcharts.PointerEventObject} e
+           * @param {boolean} [compareX]
+           * @return {Highcharts.Point}
+           */
+          searchPoint: function (e, compareX) {
+            var series = this,
+              xAxis = series.xAxis,
+              yAxis = series.yAxis,
+              inverted = series.chart.inverted;
+            return this.searchKDTree(
+              {
+                clientX: inverted
+                  ? xAxis.len - e.chartY + xAxis.pos
+                  : e.chartX - xAxis.pos,
+                plotY: inverted
+                  ? yAxis.len - e.chartX + yAxis.pos
+                  : e.chartY - yAxis.pos,
+              },
+              compareX,
+              e
+            );
+          },
+          /**
+           * Build the k-d-tree that is used by mouse and touch interaction to get
+           * the closest point. Line-like series typically have a one-dimensional
+           * tree where points are searched along the X axis, while scatter-like
+           * series typically search in two dimensions, X and Y.
+           *
+           * @private
+           * @function Highcharts.Series#buildKDTree
+           * @param {Highcharts.PointerEventObject} [e]
+           * @return {void}
+           */
+          buildKDTree: function (e) {
+            // Prevent multiple k-d-trees from being built simultaneously
+            // (#6235)
+            this.buildingKdTree = true;
+            var series = this,
+              dimensions =
+                series.options.findNearestPointBy.indexOf("y") > -1 ? 2 : 1;
             /**
-             * Merge two objects that can be arrays. If one of them is an array, the
-             * other is merged into each element. If both are arrays, each element is
-             * merged by index. If neither are arrays, we use normal merge.
+             * Internal function
              * @private
              */
-            function mergeArrays(one, two) {
-                var res = [],
-                    i;
-                if (isArray(one) && !isArray(two)) {
-                    res = one.map(function (el) {
-                        return merge(el, two);
-                    });
-                }
-                else if (isArray(two) && !isArray(one)) {
-                    res = two.map(function (el) {
-                        return merge(one, el);
-                    });
-                }
-                else if (!isArray(one) && !isArray(two)) {
-                    res = merge(one, two);
-                }
-                else {
-                    i = Math.max(one.length, two.length);
-                    while (i--) {
-                        res[i] = merge(one[i], two[i]);
-                    }
-                }
-                return res;
-            }
-            // Merge in plotOptions.dataLabels for series
-            seriesDlOptions = mergeArrays(mergeArrays(chart.options.plotOptions &&
-                chart.options.plotOptions.series &&
-                chart.options.plotOptions.series.dataLabels, chart.options.plotOptions &&
-                chart.options.plotOptions[series.type] &&
-                chart.options.plotOptions[series.type].dataLabels), seriesDlOptions);
-            fireEvent(this, 'drawDataLabels');
-            if (isArray(seriesDlOptions) ||
-                seriesDlOptions.enabled ||
-                series._hasPointLabels) {
-                // Create a separate group for the data labels to avoid rotation
-                dataLabelsGroup = series.plotGroup('dataLabelsGroup', 'data-labels', !hasRendered ? 'hidden' : 'inherit', // #5133, #10220
-                seriesDlOptions.zIndex || 6);
-                dataLabelsGroup.attr({ opacity: +hasRendered }); // #3300
-                if (!hasRendered) {
-                    var group = series.dataLabelsGroup;
-                    if (group) {
-                        if (series.visible) { // #2597, #3023, #3024
-                            dataLabelsGroup.show(true);
-                        }
-                        group[seriesOptions.animation ? 'animate' : 'attr']({ opacity: 1 }, animationConfig);
-                    }
-                }
-                // Make the labels for each point
-                points.forEach(function (point) {
-                    // Merge in series options for the point.
-                    // @note dataLabelAttribs (like pointAttribs) would eradicate
-                    // the need for dlOptions, and simplify the section below.
-                    pointOptions = splat(mergeArrays(seriesDlOptions, point.dlOptions || // dlOptions is used in treemaps
-                        (point.options && point.options.dataLabels)));
-                    // Handle each individual data label for this point
-                    pointOptions.forEach(function (labelOptions, i) {
-                        // Options for one datalabel
-                        var labelEnabled = (labelOptions.enabled &&
-                                // #2282, #4641, #7112, #10049
-                                (!point.isNull || point.dataLabelOnNull) &&
-                                applyFilter(point,
-                            labelOptions)),
-                            labelConfig,
-                            formatString,
-                            labelText,
-                            style,
-                            rotation,
-                            attr,
-                            dataLabel = point.dataLabels ? point.dataLabels[i] :
-                                point.dataLabel,
-                            connector = point.connectors ? point.connectors[i] :
-                                point.connector,
-                            labelDistance = pick(labelOptions.distance,
-                            point.labelDistance),
-                            isNew = !dataLabel;
-                        if (labelEnabled) {
-                            // Create individual options structure that can be extended
-                            // without affecting others
-                            labelConfig = point.getLabelConfig();
-                            formatString = pick(labelOptions[point.formatPrefix + 'Format'], labelOptions.format);
-                            labelText = defined(formatString) ?
-                                format(formatString, labelConfig, chart) :
-                                (labelOptions[point.formatPrefix + 'Formatter'] ||
-                                    labelOptions.formatter).call(labelConfig, labelOptions);
-                            style = labelOptions.style;
-                            rotation = labelOptions.rotation;
-                            if (!chart.styledMode) {
-                                // Determine the color
-                                style.color = pick(labelOptions.color, style.color, series.color, '#000000');
-                                // Get automated contrast color
-                                if (style.color === 'contrast') {
-                                    point.contrastColor = renderer.getContrast((point.color || series.color));
-                                    style.color = (!defined(labelDistance) &&
-                                        labelOptions.inside) ||
-                                        labelDistance < 0 ||
-                                        !!seriesOptions.stacking ?
-                                        point.contrastColor :
-                                        '#000000';
-                                }
-                                else {
-                                    delete point.contrastColor;
-                                }
-                                if (seriesOptions.cursor) {
-                                    style.cursor = seriesOptions.cursor;
-                                }
-                            }
-                            attr = {
-                                r: labelOptions.borderRadius || 0,
-                                rotation: rotation,
-                                padding: labelOptions.padding,
-                                zIndex: 1
-                            };
-                            if (!chart.styledMode) {
-                                attr.fill = labelOptions.backgroundColor;
-                                attr.stroke = labelOptions.borderColor;
-                                attr['stroke-width'] = labelOptions.borderWidth;
-                            }
-                            // Remove unused attributes (#947)
-                            objectEach(attr, function (val, name) {
-                                if (typeof val === 'undefined') {
-                                    delete attr[name];
-                                }
-                            });
-                        }
-                        // If the point is outside the plot area, destroy it. #678, #820
-                        if (dataLabel && (!labelEnabled || !defined(labelText))) {
-                            point.dataLabel =
-                                point.dataLabel && point.dataLabel.destroy();
-                            if (point.dataLabels) {
-                                // Remove point.dataLabels if this was the last one
-                                if (point.dataLabels.length === 1) {
-                                    delete point.dataLabels;
-                                }
-                                else {
-                                    delete point.dataLabels[i];
-                                }
-                            }
-                            if (!i) {
-                                delete point.dataLabel;
-                            }
-                            if (connector) {
-                                point.connector = point.connector.destroy();
-                                if (point.connectors) {
-                                    // Remove point.connectors if this was the last one
-                                    if (point.connectors.length === 1) {
-                                        delete point.connectors;
-                                    }
-                                    else {
-                                        delete point.connectors[i];
-                                    }
-                                }
-                            }
-                            // Individual labels are disabled if the are explicitly disabled
-                            // in the point options, or if they fall outside the plot area.
-                        }
-                        else if (labelEnabled && defined(labelText)) {
-                            if (!dataLabel) {
-                                // Create new label element
-                                point.dataLabels = point.dataLabels || [];
-                                dataLabel = point.dataLabels[i] = rotation ?
-                                    // Labels don't rotate, use text element
-                                    renderer.text(labelText, 0, -9999, labelOptions.useHTML)
-                                        .addClass('highcharts-data-label') :
-                                    // We can use label
-                                    renderer.label(labelText, 0, -9999, labelOptions.shape, null, null, labelOptions.useHTML, null, 'data-label');
-                                // Store for backwards compatibility
-                                if (!i) {
-                                    point.dataLabel = dataLabel;
-                                }
-                                dataLabel.addClass(' highcharts-data-label-color-' + point.colorIndex +
-                                    ' ' + (labelOptions.className || '') +
-                                    ( // #3398
-                                    labelOptions.useHTML ?
-                                        ' highcharts-tracker' :
-                                        ''));
-                            }
-                            else {
-                                // Use old element and just update text
-                                attr.text = labelText;
-                            }
-                            // Store data label options for later access
-                            dataLabel.options = labelOptions;
-                            dataLabel.attr(attr);
-                            if (!chart.styledMode) {
-                                // Styles must be applied before add in order to read
-                                // text bounding box
-                                dataLabel.css(style).shadow(labelOptions.shadow);
-                            }
-                            if (!dataLabel.added) {
-                                dataLabel.add(dataLabelsGroup);
-                            }
-                            if (labelOptions.textPath && !labelOptions.useHTML) {
-                                dataLabel.setTextPath((point.getDataLabelPath &&
-                                    point.getDataLabelPath(dataLabel)) || point.graphic, labelOptions.textPath);
-                                if (point.dataLabelPath &&
-                                    !labelOptions.textPath.enabled) {
-                                    // clean the DOM
-                                    point.dataLabelPath = point.dataLabelPath.destroy();
-                                }
-                            }
-                            // Now the data label is created and placed at 0,0, so we
-                            // need to align it
-                            series.alignDataLabel(point, dataLabel, labelOptions, null, isNew);
-                        }
-                    });
+            function _kdtree(points, depth, dimensions) {
+              var axis,
+                median,
+                length = points && points.length;
+              if (length) {
+                // alternate between the axis
+                axis = series.kdAxisArray[depth % dimensions];
+                // sort point array
+                points.sort(function (a, b) {
+                  return a[axis] - b[axis];
                 });
+                median = Math.floor(length / 2);
+                // build and return nod
+                return {
+                  point: points[median],
+                  left: _kdtree(points.slice(0, median), depth + 1, dimensions),
+                  right: _kdtree(
+                    points.slice(median + 1),
+                    depth + 1,
+                    dimensions
+                  ),
+                };
+              }
             }
-            fireEvent(this, 'afterDrawDataLabels');
-        };
-        /**
-         * Align each individual data label.
-         *
-         * @private
-         * @function Highcharts.Series#alignDataLabel
-         * @param {Highcharts.Point} point
-         * @param {Highcharts.SVGElement} dataLabel
-         * @param {Highcharts.DataLabelsOptions} options
-         * @param {Highcharts.BBoxObject} alignTo
-         * @param {boolean} [isNew]
-         * @return {void}
-         */
-        CartesianSeries.prototype.alignDataLabel = function (point, dataLabel, options, alignTo, isNew) {
+            /**
+             * Start the recursive build process with a clone of the points
+             * array and null points filtered out. (#3873)
+             * @private
+             */
+            function startRecursive() {
+              series.kdTree = _kdtree(
+                series.getValidPoints(
+                  null,
+                  // For line-type series restrict to plot area, but
+                  // column-type series not (#3916, #4511)
+                  !series.directTouch
+                ),
+                dimensions,
+                dimensions
+              );
+              series.buildingKdTree = false;
+            }
+            delete series.kdTree;
+            // For testing tooltips, don't build async. Also if touchstart, we
+            // may be dealing with click events on mobile, so don't delay
+            // (#6817).
+            syncTimeout(
+              startRecursive,
+              series.options.kdNow || (e && e.type === "touchstart") ? 0 : 1
+            );
+          },
+          /**
+           * @private
+           * @function Highcharts.Series#searchKDTree
+           * @param {Highcharts.KDPointSearchObject} point
+           * @param {boolean} [compareX]
+           * @param {Highcharts.PointerEventObject} [e]
+           * @return {Highcharts.Point|undefined}
+           */
+          searchKDTree: function (point, compareX, e) {
             var series = this,
-                chart = this.chart,
-                inverted = this.isCartesian && chart.inverted,
-                enabledDataSorting = this.enabledDataSorting,
-                plotX = pick(point.dlBox && point.dlBox.centerX,
-                point.plotX, -9999),
-                plotY = pick(point.plotY, -9999),
-                bBox = dataLabel.getBBox(),
-                baseline,
-                rotation = options.rotation,
-                normRotation,
-                negRotation,
-                align = options.align,
-                rotCorr, // rotation correction
-                isInsidePlot = chart.isInsidePlot(plotX,
-                Math.round(plotY),
-                inverted), 
-                // Math.round for rounding errors (#2683), alignTo to allow column
-                // labels (#2700)
-                alignAttr, // the final position;
-            justify = pick(options.overflow, (enabledDataSorting ? 'none' : 'justify')) === 'justify', visible = this.visible &&
-                point.visible !== false &&
-                (point.series.forceDL ||
-                    (enabledDataSorting && !justify) ||
-                    isInsidePlot ||
-                    (
-                    // If the data label is inside the align box, it is enough
-                    // that parts of the align box is inside the plot area
-                    // (#12370)
-                    options.inside && alignTo && chart.isInsidePlot(plotX, inverted ?
-                        alignTo.x + 1 :
-                        alignTo.y + alignTo.height - 1, inverted))), setStartPos = function (alignOptions) {
-                if (enabledDataSorting && series.xAxis && !justify) {
-                    series.setDataLabelStartPos(point, dataLabel, isNew, isInsidePlot, alignOptions);
-                }
-            };
-            if (visible) {
-                baseline = chart.renderer.fontMetrics(chart.styledMode ? void 0 : options.style.fontSize, dataLabel).b;
-                // The alignment box is a singular point
-                alignTo = extend({
-                    x: inverted ? this.yAxis.len - plotY : plotX,
-                    y: Math.round(inverted ? this.xAxis.len - plotX : plotY),
-                    width: 0,
-                    height: 0
-                }, alignTo);
-                // Add the text size for alignment calculation
-                extend(options, {
-                    width: bBox.width,
-                    height: bBox.height
-                });
-                // Allow a hook for changing alignment in the last moment, then do the
-                // alignment
-                if (rotation) {
-                    justify = false; // Not supported for rotated text
-                    rotCorr = chart.renderer.rotCorr(baseline, rotation); // #3723
-                    alignAttr = {
-                        x: (alignTo.x +
-                            (options.x || 0) +
-                            alignTo.width / 2 +
-                            rotCorr.x),
-                        y: (alignTo.y +
-                            (options.y || 0) +
-                            { top: 0, middle: 0.5, bottom: 1 }[options.verticalAlign] *
-                                alignTo.height)
-                    };
-                    setStartPos(alignAttr); // data sorting
-                    dataLabel[isNew ? 'attr' : 'animate'](alignAttr)
-                        .attr({
-                        align: align
-                    });
-                    // Compensate for the rotated label sticking out on the sides
-                    normRotation = (rotation + 720) % 360;
-                    negRotation = normRotation > 180 && normRotation < 360;
-                    if (align === 'left') {
-                        alignAttr.y -= negRotation ? bBox.height : 0;
-                    }
-                    else if (align === 'center') {
-                        alignAttr.x -= bBox.width / 2;
-                        alignAttr.y -= bBox.height / 2;
-                    }
-                    else if (align === 'right') {
-                        alignAttr.x -= bBox.width;
-                        alignAttr.y -= negRotation ? 0 : bBox.height;
-                    }
-                    dataLabel.placed = true;
-                    dataLabel.alignAttr = alignAttr;
-                }
-                else {
-                    setStartPos(alignTo); // data sorting
-                    dataLabel.align(options, null, alignTo);
-                    alignAttr = dataLabel.alignAttr;
-                }
-                // Handle justify or crop
-                if (justify && alignTo.height >= 0) { // #8830
-                    this.justifyDataLabel(dataLabel, options, alignAttr, bBox, alignTo, isNew);
-                    // Now check that the data label is within the plot area
-                }
-                else if (pick(options.crop, true)) {
-                    visible =
-                        chart.isInsidePlot(alignAttr.x, alignAttr.y) &&
-                            chart.isInsidePlot(alignAttr.x + bBox.width, alignAttr.y + bBox.height);
-                }
-                // When we're using a shape, make it possible with a connector or an
-                // arrow pointing to thie point
-                if (options.shape && !rotation) {
-                    dataLabel[isNew ? 'attr' : 'animate']({
-                        anchorX: inverted ?
-                            chart.plotWidth - point.plotY :
-                            point.plotX,
-                        anchorY: inverted ?
-                            chart.plotHeight - point.plotX :
-                            point.plotY
-                    });
-                }
+              kdX = this.kdAxisArray[0],
+              kdY = this.kdAxisArray[1],
+              kdComparer = compareX ? "distX" : "dist",
+              kdDimensions =
+                series.options.findNearestPointBy.indexOf("y") > -1 ? 2 : 1;
+            /**
+             * Set the one and two dimensional distance on the point object.
+             * @private
+             */
+            function setDistance(p1, p2) {
+              var x =
+                  defined(p1[kdX]) && defined(p2[kdX])
+                    ? Math.pow(p1[kdX] - p2[kdX], 2)
+                    : null,
+                y =
+                  defined(p1[kdY]) && defined(p2[kdY])
+                    ? Math.pow(p1[kdY] - p2[kdY], 2)
+                    : null,
+                r = (x || 0) + (y || 0);
+              p2.dist = defined(r) ? Math.sqrt(r) : Number.MAX_VALUE;
+              p2.distX = defined(x) ? Math.sqrt(x) : Number.MAX_VALUE;
             }
-            // To use alignAttr property in hideOverlappingLabels
-            if (isNew && enabledDataSorting) {
-                dataLabel.placed = false;
+            /**
+             * @private
+             */
+            function _search(search, tree, depth, dimensions) {
+              var point = tree.point,
+                axis = series.kdAxisArray[depth % dimensions],
+                tdist,
+                sideA,
+                sideB,
+                ret = point,
+                nPoint1,
+                nPoint2;
+              setDistance(search, point);
+              // Pick side based on distance to splitting point
+              tdist = search[axis] - point[axis];
+              sideA = tdist < 0 ? "left" : "right";
+              sideB = tdist < 0 ? "right" : "left";
+              // End of tree
+              if (tree[sideA]) {
+                nPoint1 = _search(search, tree[sideA], depth + 1, dimensions);
+                ret = nPoint1[kdComparer] < ret[kdComparer] ? nPoint1 : point;
+              }
+              if (tree[sideB]) {
+                // compare distance to current best to splitting point to
+                // decide wether to check side B or not
+                if (Math.sqrt(tdist * tdist) < ret[kdComparer]) {
+                  nPoint2 = _search(search, tree[sideB], depth + 1, dimensions);
+                  ret = nPoint2[kdComparer] < ret[kdComparer] ? nPoint2 : ret;
+                }
+              }
+              return ret;
+            }
+            if (!this.kdTree && !this.buildingKdTree) {
+              this.buildKDTree(e);
             }
-            // Show or hide based on the final aligned position
-            if (!visible && (!enabledDataSorting || justify)) {
-                dataLabel.hide(true);
-                dataLabel.placed = false; // don't animate back in
+            if (this.kdTree) {
+              return _search(point, this.kdTree, kdDimensions, kdDimensions);
             }
+          },
+          /**
+           * @private
+           * @function Highcharts.Series#pointPlacementToXValue
+           * @return {number}
+           */
+          pointPlacementToXValue: function () {
+            var _a = this,
+              _b = _a.options,
+              pointPlacement = _b.pointPlacement,
+              pointRange = _b.pointRange,
+              axis = _a.xAxis;
+            var factor = pointPlacement;
+            // Point placement is relative to each series pointRange (#5889)
+            if (factor === "between") {
+              factor = axis.reversed ? -0.5 : 0.5; // #11955
+            }
+            return isNumber(factor)
+              ? factor * pick(pointRange, axis.pointRange)
+              : 0;
+          },
+          /**
+           * @private
+           * @function Highcharts.Series#isPointInside
+           * @param {Highcharts.Point} point
+           * @return {boolean}
+           */
+          isPointInside: function (point) {
+            var isInside =
+              typeof point.plotY !== "undefined" &&
+              typeof point.plotX !== "undefined" &&
+              point.plotY >= 0 &&
+              point.plotY <= this.yAxis.len && // #3519
+              point.plotX >= 0 &&
+              point.plotX <= this.xAxis.len;
+            return isInside;
+          },
+        }
+      ); // end Series prototype
+      /**
+       * A line series displays information as a series of data points connected by
+       * straight line segments.
+       *
+       * @sample {highcharts} highcharts/demo/line-basic/
+       *         Line chart
+       * @sample {highstock} stock/demo/basic-line/
+       *         Line chart
+       *
+       * @extends   plotOptions.series
+       * @product   highcharts highstock
+       * @apioption plotOptions.line
+       */
+      /**
+       * The SVG value used for the `stroke-linecap` and `stroke-linejoin`
+       * of a line graph. Round means that lines are rounded in the ends and
+       * bends.
+       *
+       * @type       {Highcharts.SeriesLinecapValue}
+       * @default    round
+       * @since      3.0.7
+       * @apioption  plotOptions.line.linecap
+       */
+      /**
+       * A `line` series. If the [type](#series.line.type) option is not
+       * specified, it is inherited from [chart.type](#chart.type).
+       *
+       * @extends   series,plotOptions.line
+       * @excluding dataParser,dataURL
+       * @product   highcharts highstock
+       * @apioption series.line
+       */
+      /**
+       * An array of data points for the series. For the `line` series type,
+       * points can be given in the following ways:
+       *
+       * 1. An array of numerical values. In this case, the numerical values will be
+       *    interpreted as `y` options. The `x` values will be automatically
+       *    calculated, either starting at 0 and incremented by 1, or from
+       *    `pointStart` and `pointInterval` given in the series options. If the axis
+       *    has categories, these will be used. Example:
+       *    ```js
+       *    data: [0, 5, 3, 5]
+       *    ```
+       *
+       * 2. An array of arrays with 2 values. In this case, the values correspond to
+       *    `x,y`. If the first value is a string, it is applied as the name of the
+       *    point, and the `x` value is inferred.
+       *    ```js
+       *    data: [
+       *        [0, 1],
+       *        [1, 2],
+       *        [2, 8]
+       *    ]
+       *    ```
+       *
+       * 3. An array of objects with named values. The following snippet shows only a
+       *    few settings, see the complete options set below. If the total number of
+       *    data points exceeds the series'
+       *    [turboThreshold](#series.line.turboThreshold),
+       *    this option is not available.
+       *    ```js
+       *    data: [{
+       *        x: 1,
+       *        y: 9,
+       *        name: "Point2",
+       *        color: "#00FF00"
+       *    }, {
+       *        x: 1,
+       *        y: 6,
+       *        name: "Point1",
+       *        color: "#FF00FF"
+       *    }]
+       *    ```
+       *
+       * **Note:** In TypeScript you have to extend `PointOptionsObject` with an
+       * additional declaration to allow custom data types:
+       * ```ts
+       * declare module `highcharts` {
+       *   interface PointOptionsObject {
+       *     custom: Record<string, (boolean|number|string)>;
+       *   }
+       * }
+       * ```
+       *
+       * @sample {highcharts} highcharts/chart/reflow-true/
+       *         Numerical values
+       * @sample {highcharts} highcharts/series/data-array-of-arrays/
+       *         Arrays of numeric x and y
+       * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
+       *         Arrays of datetime x and y
+       * @sample {highcharts} highcharts/series/data-array-of-name-value/
+       *         Arrays of point.name and y
+       * @sample {highcharts} highcharts/series/data-array-of-objects/
+       *         Config objects
+       *
+       * @declare   Highcharts.PointOptionsObject
+       * @type      {Array<number|Array<(number|string),(number|null)>|null|*>}
+       * @apioption series.line.data
+       */
+      /**
+       * An additional, individual class name for the data point's graphic
+       * representation.
+       *
+       * @type      {string}
+       * @since     5.0.0
+       * @product   highcharts gantt
+       * @apioption series.line.data.className
+       */
+      /**
+       * Individual color for the point. By default the color is pulled from
+       * the global `colors` array.
+       *
+       * In styled mode, the `color` option doesn't take effect. Instead, use
+       * `colorIndex`.
+       *
+       * @sample {highcharts} highcharts/point/color/
+       *         Mark the highest point
+       *
+       * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+       * @product   highcharts highstock gantt
+       * @apioption series.line.data.color
+       */
+      /**
+       * A specific color index to use for the point, so its graphic representations
+       * are given the class name `highcharts-color-{n}`. In styled mode this will
+       * change the color of the graphic. In non-styled mode, the color by is set by
+       * the `fill` attribute, so the change in class name won't have a visual effect
+       * by default.
+       *
+       * @type      {number}
+       * @since     5.0.0
+       * @product   highcharts gantt
+       * @apioption series.line.data.colorIndex
+       */
+      /**
+       * A reserved subspace to store options and values for customized functionality.
+       * Here you can add additional data for your own event callbacks and formatter
+       * callbacks.
+       *
+       * @sample {highcharts} highcharts/point/custom/
+       *         Point and series with custom data
+       *
+       * @type      {Highcharts.Dictionary<*>}
+       * @apioption series.line.data.custom
+       */
+      /**
+       * Individual data label for each point. The options are the same as
+       * the ones for [plotOptions.series.dataLabels](
+       * #plotOptions.series.dataLabels).
+       *
+       * @sample highcharts/point/datalabels/
+       *         Show a label for the last value
+       *
+       * @declare   Highcharts.DataLabelsOptions
+       * @extends   plotOptions.line.dataLabels
+       * @product   highcharts highstock gantt
+       * @apioption series.line.data.dataLabels
+       */
+      /**
+       * A description of the point to add to the screen reader information
+       * about the point.
+       *
+       * @type      {string}
+       * @since     5.0.0
+       * @requires  modules/accessibility
+       * @apioption series.line.data.description
+       */
+      /**
+       * An id for the point. This can be used after render time to get a
+       * pointer to the point object through `chart.get()`.
+       *
+       * @sample {highcharts} highcharts/point/id/
+       *         Remove an id'd point
+       *
+       * @type      {string}
+       * @since     1.2.0
+       * @product   highcharts highstock gantt
+       * @apioption series.line.data.id
+       */
+      /**
+       * The rank for this point's data label in case of collision. If two
+       * data labels are about to overlap, only the one with the highest `labelrank`
+       * will be drawn.
+       *
+       * @type      {number}
+       * @apioption series.line.data.labelrank
+       */
+      /**
+       * The name of the point as shown in the legend, tooltip, dataLabels, etc.
+       *
+       * @see [xAxis.uniqueNames](#xAxis.uniqueNames)
+       *
+       * @sample {highcharts} highcharts/series/data-array-of-objects/
+       *         Point names
+       *
+       * @type      {string}
+       * @apioption series.line.data.name
+       */
+      /**
+       * Whether the data point is selected initially.
+       *
+       * @type      {boolean}
+       * @default   false
+       * @product   highcharts highstock gantt
+       * @apioption series.line.data.selected
+       */
+      /**
+       * The x value of the point. For datetime axes, the X value is the timestamp
+       * in milliseconds since 1970.
+       *
+       * @type      {number}
+       * @product   highcharts highstock
+       * @apioption series.line.data.x
+       */
+      /**
+       * The y value of the point.
+       *
+       * @type      {number|null}
+       * @product   highcharts highstock
+       * @apioption series.line.data.y
+       */
+      /**
+       * The individual point events.
+       *
+       * @extends   plotOptions.series.point.events
+       * @product   highcharts highstock gantt
+       * @apioption series.line.data.events
+       */
+      /**
+       * Options for the point markers of line-like series.
+       *
+       * @declare   Highcharts.PointMarkerOptionsObject
+       * @extends   plotOptions.series.marker
+       * @product   highcharts highstock
+       * @apioption series.line.data.marker
+       */
+      (""); // include precedent doclets in transpilat
+
+      return CartesianSeries;
+    }
+  );
+  _registerModule(
+    _modules,
+    "Series/LineSeries.js",
+    [_modules["Core/Series/CartesianSeries.js"], _modules["Core/Globals.js"]],
+    function (CartesianSeries, H) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      H.Series = CartesianSeries; // backwards compatibility
+
+      return H.Series;
+    }
+  );
+  _registerModule(
+    _modules,
+    "Extensions/Stacking.js",
+    [
+      _modules["Core/Axis/Axis.js"],
+      _modules["Core/Chart/Chart.js"],
+      _modules["Core/Globals.js"],
+      _modules["Core/Axis/StackingAxis.js"],
+      _modules["Core/Utilities.js"],
+    ],
+    function (Axis, Chart, H, StackingAxis, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      var correctFloat = U.correctFloat,
+        defined = U.defined,
+        destroyObjectProperties = U.destroyObjectProperties,
+        format = U.format,
+        isNumber = U.isNumber,
+        pick = U.pick;
+      /**
+       * Stack of data points
+       *
+       * @product highcharts
+       *
+       * @interface Highcharts.StackItemObject
+       */ /**
+       * Alignment settings
+       * @name Highcharts.StackItemObject#alignOptions
+       * @type {Highcharts.AlignObject}
+       */ /**
+       * Related axis
+       * @name Highcharts.StackItemObject#axis
+       * @type {Highcharts.Axis}
+       */ /**
+       * Cumulative value of the stacked data points
+       * @name Highcharts.StackItemObject#cumulative
+       * @type {number}
+       */ /**
+       * True if on the negative side
+       * @name Highcharts.StackItemObject#isNegative
+       * @type {boolean}
+       */ /**
+       * Related SVG element
+       * @name Highcharts.StackItemObject#label
+       * @type {Highcharts.SVGElement}
+       */ /**
+       * Related stack options
+       * @name Highcharts.StackItemObject#options
+       * @type {Highcharts.YAxisStackLabelsOptions}
+       */ /**
+       * Total value of the stacked data points
+       * @name Highcharts.StackItemObject#total
+       * @type {number}
+       */ /**
+       * Shared x value of the stack
+       * @name Highcharts.StackItemObject#x
+       * @type {number}
+       */
+      (""); // detached doclets above
+      var Series = H.Series;
+      /* eslint-disable no-invalid-this, valid-jsdoc */
+      /**
+       * The class for stacks. Each stack, on a specific X value and either negative
+       * or positive, has its own stack item.
+       *
+       * @private
+       * @class
+       * @name Highcharts.StackItem
+       * @param {Highcharts.Axis} axis
+       * @param {Highcharts.YAxisStackLabelsOptions} options
+       * @param {boolean} isNegative
+       * @param {number} x
+       * @param {Highcharts.OptionsStackingValue} [stackOption]
+       */
+      var StackItem = /** @class */ (function () {
+        function StackItem(axis, options, isNegative, x, stackOption) {
+          var inverted = axis.chart.inverted;
+          this.axis = axis;
+          // Tells if the stack is negative
+          this.isNegative = isNegative;
+          // Save the options to be able to style the label
+          this.options = options = options || {};
+          // Save the x value to be able to position the label later
+          this.x = x;
+          // Initialize total value
+          this.total = null;
+          // This will keep each points' extremes stored by series.index and point
+          // index
+          this.points = {};
+          this.hasValidPoints = false;
+          // Save the stack option on the series configuration object,
+          // and whether to treat it as percent
+          this.stack = stackOption;
+          this.leftCliff = 0;
+          this.rightCliff = 0;
+          // The align options and text align varies on whether the stack is
+          // negative and if the chart is inverted or not.
+          // First test the user supplied value, then use the dynamic.
+          this.alignOptions = {
+            align:
+              options.align ||
+              (inverted ? (isNegative ? "left" : "right") : "center"),
+            verticalAlign:
+              options.verticalAlign ||
+              (inverted ? "middle" : isNegative ? "bottom" : "top"),
+            y: options.y,
+            x: options.x,
+          };
+          this.textAlign =
+            options.textAlign ||
+            (inverted ? (isNegative ? "right" : "left") : "center");
+        }
+        /**
+         * @private
+         * @function Highcharts.StackItem#destroy
+         */
+        StackItem.prototype.destroy = function () {
+          destroyObjectProperties(this, this.axis);
         };
         /**
-         * Set starting position for data label sorting animation.
+         * Renders the stack total label and adds it to the stack label group.
          *
          * @private
-         * @function Highcharts.Series#setDataLabelStartPos
-         * @param {Highcharts.SVGElement} dataLabel
-         * @param {Highcharts.ColumnPoint} point
-         * @param {boolean | undefined} [isNew]
-         * @param {boolean} [isInside]
-         * @param {Highcharts.AlignObject} [alignOptions]
-         *
-         * @return {void}
-         */
-        CartesianSeries.prototype.setDataLabelStartPos = function (point, dataLabel, isNew, isInside, alignOptions) {
-            var chart = this.chart,
-                inverted = chart.inverted,
-                xAxis = this.xAxis,
-                reversed = xAxis.reversed,
-                labelCenter = inverted ? dataLabel.height / 2 : dataLabel.width / 2,
-                pointWidth = point.pointWidth,
-                halfWidth = pointWidth ? pointWidth / 2 : 0,
-                startXPos,
-                startYPos;
-            startXPos = inverted ?
-                alignOptions.x :
-                (reversed ?
-                    -labelCenter - halfWidth :
-                    xAxis.width - labelCenter + halfWidth);
-            startYPos = inverted ?
-                (reversed ?
-                    this.yAxis.height - labelCenter + halfWidth :
-                    -labelCenter - halfWidth) : alignOptions.y;
-            dataLabel.startXPos = startXPos;
-            dataLabel.startYPos = startYPos;
-            // We need to handle visibility in case of sorting point outside plot area
-            if (!isInside) {
-                dataLabel
-                    .attr({ opacity: 1 })
-                    .animate({ opacity: 0 }, void 0, dataLabel.hide);
-            }
-            else if (dataLabel.visibility === 'hidden') {
-                dataLabel.show();
-                dataLabel
-                    .attr({ opacity: 0 })
-                    .animate({ opacity: 1 });
-            }
-            // Save start position on first render, but do not change position
-            if (!chart.hasRendered) {
-                return;
+         * @function Highcharts.StackItem#render
+         * @param {Highcharts.SVGElement} group
+         */
+        StackItem.prototype.render = function (group) {
+          var chart = this.axis.chart,
+            options = this.options,
+            formatOption = options.format,
+            attr = {},
+            str = formatOption // format the text in the label
+              ? format(formatOption, this, chart)
+              : options.formatter.call(this);
+          // Change the text to reflect the new total and set visibility to hidden
+          // in case the serie is hidden
+          if (this.label) {
+            this.label.attr({ text: str, visibility: "hidden" });
+          } else {
+            // Create new label
+            this.label = chart.renderer.label(
+              str,
+              null,
+              null,
+              options.shape,
+              null,
+              null,
+              options.useHTML,
+              false,
+              "stack-labels"
+            );
+            attr = {
+              r: options.borderRadius || 0,
+              text: str,
+              rotation: options.rotation,
+              padding: pick(options.padding, 5),
+              visibility: "hidden", // hidden until setOffset is called
+            };
+            if (!chart.styledMode) {
+              attr.fill = options.backgroundColor;
+              attr.stroke = options.borderColor;
+              attr["stroke-width"] = options.borderWidth;
+              this.label.css(options.style);
             }
-            // Set start position
-            if (isNew) {
-                dataLabel.attr({ x: dataLabel.startXPos, y: dataLabel.startYPos });
+            this.label.attr(attr);
+            if (!this.label.added) {
+              this.label.add(group); // add to the labels-group
             }
-            dataLabel.placed = true;
+          }
+          // Rank it higher than data labels (#8742)
+          this.label.labelrank = chart.plotHeight;
         };
         /**
-         * If data labels fall partly outside the plot area, align them back in, in a
-         * way that doesn't hide the point.
+         * Sets the offset that the stack has from the x value and repositions the
+         * label.
          *
          * @private
-         * @function Highcharts.Series#justifyDataLabel
-         * @param {Highcharts.SVGElement} dataLabel
-         * @param {Highcharts.DataLabelsOptions} options
-         * @param {Highcharts.SVGAttributes} alignAttr
-         * @param {Highcharts.BBoxObject} bBox
-         * @param {Highcharts.BBoxObject} [alignTo]
-         * @param {boolean} [isNew]
-         * @return {boolean|undefined}
-         */
-        CartesianSeries.prototype.justifyDataLabel = function (dataLabel, options, alignAttr, bBox, alignTo, isNew) {
-            var chart = this.chart,
-                align = options.align,
-                verticalAlign = options.verticalAlign,
-                off,
-                justified,
-                padding = dataLabel.box ? 0 : (dataLabel.padding || 0);
-            var _a = options.x,
-                x = _a === void 0 ? 0 : _a,
-                _b = options.y,
-                y = _b === void 0 ? 0 : _b;
-            // Off left
-            off = alignAttr.x + padding;
-            if (off < 0) {
-                if (align === 'right' && x >= 0) {
-                    options.align = 'left';
-                    options.inside = true;
-                }
-                else {
-                    x -= off;
-                }
-                justified = true;
-            }
-            // Off right
-            off = alignAttr.x + bBox.width - padding;
-            if (off > chart.plotWidth) {
-                if (align === 'left' && x <= 0) {
-                    options.align = 'right';
-                    options.inside = true;
-                }
-                else {
-                    x += chart.plotWidth - off;
-                }
-                justified = true;
-            }
-            // Off top
-            off = alignAttr.y + padding;
-            if (off < 0) {
-                if (verticalAlign === 'bottom' && y >= 0) {
-                    options.verticalAlign = 'top';
-                    options.inside = true;
-                }
-                else {
-                    y -= off;
-                }
-                justified = true;
-            }
-            // Off bottom
-            off = alignAttr.y + bBox.height - padding;
-            if (off > chart.plotHeight) {
-                if (verticalAlign === 'top' && y <= 0) {
-                    options.verticalAlign = 'bottom';
-                    options.inside = true;
-                }
-                else {
-                    y += chart.plotHeight - off;
-                }
-                justified = true;
+         * @function Highcarts.StackItem#setOffset
+         * @param {number} xOffset
+         * @param {number} xWidth
+         * @param {number} [boxBottom]
+         * @param {number} [boxTop]
+         * @param {number} [defaultX]
+         */
+        StackItem.prototype.setOffset = function (
+          xOffset,
+          xWidth,
+          boxBottom,
+          boxTop,
+          defaultX
+        ) {
+          var stackItem = this,
+            axis = stackItem.axis,
+            chart = axis.chart,
+            // stack value translated mapped to chart coordinates
+            y = axis.translate(
+              axis.stacking.usePercentage
+                ? 100
+                : boxTop
+                ? boxTop
+                : stackItem.total,
+              0,
+              0,
+              0,
+              1
+            ),
+            yZero = axis.translate(boxBottom ? boxBottom : 0), // stack origin
+            // stack height:
+            h = defined(y) && Math.abs(y - yZero),
+            // x position:
+            x = pick(defaultX, chart.xAxis[0].translate(stackItem.x)) + xOffset,
+            stackBox =
+              defined(y) &&
+              stackItem.getStackBox(chart, stackItem, x, y, xWidth, h, axis),
+            label = stackItem.label,
+            isNegative = stackItem.isNegative,
+            isJustify =
+              pick(stackItem.options.overflow, "justify") === "justify",
+            textAlign = stackItem.textAlign,
+            visible;
+          if (label && stackBox) {
+            var bBox = label.getBBox(),
+              padding = label.padding,
+              boxOffsetX,
+              boxOffsetY;
+            if (textAlign === "left") {
+              boxOffsetX = chart.inverted ? -padding : padding;
+            } else if (textAlign === "right") {
+              boxOffsetX = bBox.width;
+            } else {
+              if (chart.inverted && textAlign === "center") {
+                boxOffsetX = bBox.width / 2;
+              } else {
+                boxOffsetX = chart.inverted
+                  ? isNegative
+                    ? bBox.width + padding
+                    : -padding
+                  : bBox.width / 2;
+              }
+            }
+            boxOffsetY = chart.inverted
+              ? bBox.height / 2
+              : isNegative
+              ? -padding
+              : bBox.height;
+            // Reset alignOptions property after justify #12337
+            stackItem.alignOptions.x = pick(stackItem.options.x, 0);
+            stackItem.alignOptions.y = pick(stackItem.options.y, 0);
+            // Set the stackBox position
+            stackBox.x -= boxOffsetX;
+            stackBox.y -= boxOffsetY;
+            // Align the label to the box
+            label.align(stackItem.alignOptions, null, stackBox);
+            // Check if label is inside the plotArea #12294
+            if (
+              chart.isInsidePlot(
+                label.alignAttr.x + boxOffsetX - stackItem.alignOptions.x,
+                label.alignAttr.y + boxOffsetY - stackItem.alignOptions.y
+              )
+            ) {
+              label.show();
+            } else {
+              // Move label away to avoid the overlapping issues
+              label.alignAttr.y = -9999;
+              isJustify = false;
             }
-            if (justified) {
-                options.x = x;
-                options.y = y;
-                dataLabel.placed = !isNew;
-                dataLabel.align(options, void 0, alignTo);
+            if (isJustify) {
+              // Justify stackLabel into the stackBox
+              Series.prototype.justifyDataLabel.call(
+                this.axis,
+                label,
+                stackItem.alignOptions,
+                label.alignAttr,
+                bBox,
+                stackBox
+              );
+            }
+            label.attr({
+              x: label.alignAttr.x,
+              y: label.alignAttr.y,
+            });
+            if (pick(!isJustify && stackItem.options.crop, true)) {
+              visible =
+                isNumber(label.x) &&
+                isNumber(label.y) &&
+                chart.isInsidePlot(label.x - padding + label.width, label.y) &&
+                chart.isInsidePlot(label.x + padding, label.y);
+              if (!visible) {
+                label.hide();
+              }
             }
-            return justified;
+          }
         };
-        if (seriesTypes.pie) {
-            seriesTypes.pie.prototype.dataLabelPositioners = {
-                // Based on the value computed in Highcharts' distribute algorithm.
-                radialDistributionY: function (point) {
-                    return point.top + point.distributeBox.pos;
-                },
-                // get the x - use the natural x position for labels near the
-                // top and bottom, to prevent the top and botton slice
-                // connectors from touching each other on either side
-                // Based on the value computed in Highcharts' distribute algorithm.
-                radialDistributionX: function (series, point, y, naturalY) {
-                    return series.getX(y < point.top + 2 || y > point.bottom - 2 ?
-                        naturalY :
-                        y, point.half, point);
-                },
-                // dataLabels.distance determines the x position of the label
-                justify: function (point, radius, seriesCenter) {
-                    return seriesCenter[0] + (point.half ? -1 : 1) *
-                        (radius + point.labelDistance);
-                },
-                // Left edges of the left-half labels touch the left edge of the plot
-                // area. Right edges of the right-half labels touch the right edge of
-                // the plot area.
-                alignToPlotEdges: function (dataLabel, half, plotWidth, plotLeft) {
-                    var dataLabelWidth = dataLabel.getBBox().width;
-                    return half ? dataLabelWidth + plotLeft :
-                        plotWidth - dataLabelWidth - plotLeft;
-                },
-                // Connectors of each side end in the same x position. Labels are
-                // aligned to them. Left edge of the widest left-half label touches the
-                // left edge of the plot area. Right edge of the widest right-half label
-                // touches the right edge of the plot area.
-                alignToConnectors: function (points, half, plotWidth, plotLeft) {
-                    var maxDataLabelWidth = 0,
-                        dataLabelWidth;
-                    // find widest data label
-                    points.forEach(function (point) {
-                        dataLabelWidth = point.dataLabel.getBBox().width;
-                        if (dataLabelWidth > maxDataLabelWidth) {
-                            maxDataLabelWidth = dataLabelWidth;
-                        }
-                    });
-                    return half ? maxDataLabelWidth + plotLeft :
-                        plotWidth - maxDataLabelWidth - plotLeft;
-                }
-            };
-            /**
-             * Override the base drawDataLabels method by pie specific functionality
-             *
-             * @private
-             * @function Highcharts.seriesTypes.pie#drawDataLabels
-             * @return {void}
-             */
-            seriesTypes.pie.prototype.drawDataLabels = function () {
-                var series = this,
-                    data = series.data,
-                    point,
-                    chart = series.chart,
-                    options = series.options.dataLabels || {},
-                    connectorPadding = options.connectorPadding,
-                    connectorWidth,
-                    plotWidth = chart.plotWidth,
-                    plotHeight = chart.plotHeight,
-                    plotLeft = chart.plotLeft,
-                    maxWidth = Math.round(chart.chartWidth / 3),
-                    connector,
-                    seriesCenter = series.center,
-                    radius = seriesCenter[2] / 2,
-                    centerY = seriesCenter[1],
-                    dataLabel,
-                    dataLabelWidth, 
-                    // labelPos,
-                    labelPosition,
-                    labelHeight, 
-                    // divide the points into right and left halves for anti collision
-                    halves = [
-                        [],
-                        [] // left
-                    ],
-                    x,
-                    y,
-                    visibility,
-                    j,
-                    overflow = [0, 0, 0, 0], // top, right, bottom, left
-                    dataLabelPositioners = series.dataLabelPositioners,
-                    pointDataLabelsOptions;
-                // get out if not enabled
-                if (!series.visible ||
-                    (!options.enabled &&
-                        !series._hasPointLabels)) {
-                    return;
-                }
-                // Reset all labels that have been shortened
-                data.forEach(function (point) {
-                    if (point.dataLabel && point.visible && point.dataLabel.shortened) {
-                        point.dataLabel
-                            .attr({
-                            width: 'auto'
-                        }).css({
-                            width: 'auto',
-                            textOverflow: 'clip'
-                        });
-                        point.dataLabel.shortened = false;
-                    }
-                });
-                // run parent method
-                CartesianSeries.prototype.drawDataLabels.apply(series);
-                data.forEach(function (point) {
-                    if (point.dataLabel) {
-                        if (point.visible) { // #407, #2510
-                            // Arrange points for detection collision
-                            halves[point.half].push(point);
-                            // Reset positions (#4905)
-                            point.dataLabel._pos = null;
-                            // Avoid long labels squeezing the pie size too far down
-                            if (!defined(options.style.width) &&
-                                !defined(point.options.dataLabels &&
-                                    point.options.dataLabels.style &&
-                                    point.options.dataLabels.style.width)) {
-                                if (point.dataLabel.getBBox().width > maxWidth) {
-                                    point.dataLabel.css({
-                                        // Use a fraction of the maxWidth to avoid
-                                        // wrapping close to the end of the string.
-                                        width: Math.round(maxWidth * 0.7) + 'px'
-                                    });
-                                    point.dataLabel.shortened = true;
-                                }
-                            }
-                        }
-                        else {
-                            point.dataLabel = point.dataLabel.destroy();
-                            // Workaround to make pies destroy multiple datalabels
-                            // correctly. This logic needs rewriting to support multiple
-                            // datalabels fully.
-                            if (point.dataLabels && point.dataLabels.length === 1) {
-                                delete point.dataLabels;
-                            }
-                        }
-                    }
-                });
-                /* Loop over the points in each half, starting from the top and bottom
-                 * of the pie to detect overlapping labels.
-                 */
-                halves.forEach(function (points, i) {
-                    var top,
-                        bottom,
-                        length = points.length,
-                        positions = [],
-                        naturalY,
-                        sideOverflow,
-                        size,
-                        distributionLength;
-                    if (!length) {
-                        return;
-                    }
-                    // Sort by angle
-                    series.sortByAngle(points, i - 0.5);
-                    // Only do anti-collision when we have dataLabels outside the pie
-                    // and have connectors. (#856)
-                    if (series.maxLabelDistance > 0) {
-                        top = Math.max(0, centerY - radius - series.maxLabelDistance);
-                        bottom = Math.min(centerY + radius + series.maxLabelDistance, chart.plotHeight);
-                        points.forEach(function (point) {
-                            // check if specific points' label is outside the pie
-                            if (point.labelDistance > 0 && point.dataLabel) {
-                                // point.top depends on point.labelDistance value
-                                // Used for calculation of y value in getX method
-                                point.top = Math.max(0, centerY - radius - point.labelDistance);
-                                point.bottom = Math.min(centerY + radius + point.labelDistance, chart.plotHeight);
-                                size = point.dataLabel.getBBox().height || 21;
-                                // point.positionsIndex is needed for getting index of
-                                // parameter related to specific point inside positions
-                                // array - not every point is in positions array.
-                                point.distributeBox = {
-                                    target: point.labelPosition.natural.y -
-                                        point.top + size / 2,
-                                    size: size,
-                                    rank: point.y
-                                };
-                                positions.push(point.distributeBox);
-                            }
-                        });
-                        distributionLength = bottom + size - top;
-                        H.distribute(positions, distributionLength, distributionLength / 5);
-                    }
-                    // Now the used slots are sorted, fill them up sequentially
-                    for (j = 0; j < length; j++) {
-                        point = points[j];
-                        // labelPos = point.labelPos;
-                        labelPosition = point.labelPosition;
-                        dataLabel = point.dataLabel;
-                        visibility = point.visible === false ? 'hidden' : 'inherit';
-                        naturalY = labelPosition.natural.y;
-                        y = naturalY;
-                        if (positions && defined(point.distributeBox)) {
-                            if (typeof point.distributeBox.pos === 'undefined') {
-                                visibility = 'hidden';
-                            }
-                            else {
-                                labelHeight = point.distributeBox.size;
-                                // Find label's y position
-                                y = dataLabelPositioners
-                                    .radialDistributionY(point);
-                            }
-                        }
-                        // It is needed to delete point.positionIndex for
-                        // dynamically added points etc.
-                        delete point.positionIndex; // @todo unused
-                        // Find label's x position
-                        // justify is undocumented in the API - preserve support for it
-                        if (options.justify) {
-                            x = dataLabelPositioners.justify(point, radius, seriesCenter);
-                        }
-                        else {
-                            switch (options.alignTo) {
-                                case 'connectors':
-                                    x = dataLabelPositioners.alignToConnectors(points, i, plotWidth, plotLeft);
-                                    break;
-                                case 'plotEdges':
-                                    x = dataLabelPositioners.alignToPlotEdges(dataLabel, i, plotWidth, plotLeft);
-                                    break;
-                                default:
-                                    x = dataLabelPositioners.radialDistributionX(series, point, y, naturalY);
-                            }
-                        }
-                        // Record the placement and visibility
-                        dataLabel._attr = {
-                            visibility: visibility,
-                            align: labelPosition.alignment
-                        };
-                        pointDataLabelsOptions = point.options.dataLabels || {};
-                        dataLabel._pos = {
-                            x: (x +
-                                pick(pointDataLabelsOptions.x, options.x) + // (#12985)
-                                ({
-                                    left: connectorPadding,
-                                    right: -connectorPadding
-                                }[labelPosition.alignment] || 0)),
-                            // 10 is for the baseline (label vs text)
-                            y: (y +
-                                pick(pointDataLabelsOptions.y, options.y) - // (#12985)
-                                10)
-                        };
-                        // labelPos.x = x;
-                        // labelPos.y = y;
-                        labelPosition.final.x = x;
-                        labelPosition.final.y = y;
-                        // Detect overflowing data labels
-                        if (pick(options.crop, true)) {
-                            dataLabelWidth = dataLabel.getBBox().width;
-                            sideOverflow = null;
-                            // Overflow left
-                            if (x - dataLabelWidth < connectorPadding &&
-                                i === 1 // left half
-                            ) {
-                                sideOverflow = Math.round(dataLabelWidth - x + connectorPadding);
-                                overflow[3] = Math.max(sideOverflow, overflow[3]);
-                                // Overflow right
-                            }
-                            else if (x + dataLabelWidth > plotWidth - connectorPadding &&
-                                i === 0 // right half
-                            ) {
-                                sideOverflow = Math.round(x + dataLabelWidth - plotWidth + connectorPadding);
-                                overflow[1] = Math.max(sideOverflow, overflow[1]);
-                            }
-                            // Overflow top
-                            if (y - labelHeight / 2 < 0) {
-                                overflow[0] = Math.max(Math.round(-y + labelHeight / 2), overflow[0]);
-                                // Overflow left
-                            }
-                            else if (y + labelHeight / 2 > plotHeight) {
-                                overflow[2] = Math.max(Math.round(y + labelHeight / 2 - plotHeight), overflow[2]);
-                            }
-                            dataLabel.sideOverflow = sideOverflow;
-                        }
-                    } // for each point
-                }); // for each half
-                // Do not apply the final placement and draw the connectors until we
-                // have verified that labels are not spilling over.
-                if (arrayMax(overflow) === 0 ||
-                    this.verifyDataLabelOverflow(overflow)) {
-                    // Place the labels in the final position
-                    this.placeDataLabels();
-                    this.points.forEach(function (point) {
-                        // #8864: every connector can have individual options
-                        pointDataLabelsOptions =
-                            merge(options, point.options.dataLabels);
-                        connectorWidth =
-                            pick(pointDataLabelsOptions.connectorWidth, 1);
-                        // Draw the connector
-                        if (connectorWidth) {
-                            var isNew;
-                            connector = point.connector;
-                            dataLabel = point.dataLabel;
-                            if (dataLabel &&
-                                dataLabel._pos &&
-                                point.visible &&
-                                point.labelDistance > 0) {
-                                visibility = dataLabel._attr.visibility;
-                                isNew = !connector;
-                                if (isNew) {
-                                    point.connector = connector = chart.renderer
-                                        .path()
-                                        .addClass('highcharts-data-label-connector ' +
-                                        ' highcharts-color-' + point.colorIndex +
-                                        (point.className ?
-                                            ' ' + point.className :
-                                            ''))
-                                        .add(series.dataLabelsGroup);
-                                    if (!chart.styledMode) {
-                                        connector.attr({
-                                            'stroke-width': connectorWidth,
-                                            'stroke': (pointDataLabelsOptions.connectorColor ||
-                                                point.color ||
-                                                '#666666')
-                                        });
-                                    }
-                                }
-                                connector[isNew ? 'attr' : 'animate']({
-                                    d: point.getConnectorPath()
-                                });
-                                connector.attr('visibility', visibility);
-                            }
-                            else if (connector) {
-                                point.connector = connector.destroy();
-                            }
-                        }
-                    });
-                }
-            };
-            /**
-             * Extendable method for getting the path of the connector between the data
-             * label and the pie slice.
-             *
-             * @private
-             * @function Highcharts.seriesTypes.pie#connectorPath
-             *
-             * @param {*} labelPos
-             *
-             * @return {Highcharts.SVGPathArray}
-             */
-            // TODO: depracated - remove it
-            /*
-            seriesTypes.pie.prototype.connectorPath = function (labelPos) {
-                var x = labelPos.x,
-                        y = labelPos.y;
-                return pick(this.options.dataLabels.softConnector, true) ? [
-                    'M',
-                    // end of the string at the label
-                    x + (labelPos[6] === 'left' ? 5 : -5), y,
-                    'C',
-                    x, y, // first break, next to the label
-                    2 * labelPos[2] - labelPos[4], 2 * labelPos[3] - labelPos[5],
-                    labelPos[2], labelPos[3], // second break
-                    'L',
-                    labelPos[4], labelPos[5] // base
-                ] : [
-                    'M',
-                    // end of the string at the label
-                    x + (labelPos[6] === 'left' ? 5 : -5), y,
-                    'L',
-                    labelPos[2], labelPos[3], // second break
-                    'L',
-                    labelPos[4], labelPos[5] // base
-                ];
-            };
-            */
-            /**
-             * Perform the final placement of the data labels after we have verified
-             * that they fall within the plot area.
-             *
-             * @private
-             * @function Highcharts.seriesTypes.pie#placeDataLabels
-             * @return {void}
-             */
-            seriesTypes.pie.prototype.placeDataLabels = function () {
-                this.points.forEach(function (point) {
-                    var dataLabel = point.dataLabel,
-                        _pos;
-                    if (dataLabel && point.visible) {
-                        _pos = dataLabel._pos;
-                        if (_pos) {
-                            // Shorten data labels with ellipsis if they still overflow
-                            // after the pie has reached minSize (#223).
-                            if (dataLabel.sideOverflow) {
-                                dataLabel._attr.width =
-                                    Math.max(dataLabel.getBBox().width -
-                                        dataLabel.sideOverflow, 0);
-                                dataLabel.css({
-                                    width: dataLabel._attr.width + 'px',
-                                    textOverflow: ((this.options.dataLabels.style || {})
-                                        .textOverflow ||
-                                        'ellipsis')
-                                });
-                                dataLabel.shortened = true;
-                            }
-                            dataLabel.attr(dataLabel._attr);
-                            dataLabel[dataLabel.moved ? 'animate' : 'attr'](_pos);
-                            dataLabel.moved = true;
-                        }
-                        else if (dataLabel) {
-                            dataLabel.attr({ y: -9999 });
-                        }
-                    }
-                    // Clear for update
-                    delete point.distributeBox;
-                }, this);
-            };
-            seriesTypes.pie.prototype.alignDataLabel = noop;
-            /**
-             * Verify whether the data labels are allowed to draw, or we should run more
-             * translation and data label positioning to keep them inside the plot area.
-             * Returns true when data labels are ready to draw.
-             *
-             * @private
-             * @function Highcharts.seriesTypes.pie#verifyDataLabelOverflow
-             * @param {Array<number>} overflow
-             * @return {boolean}
-             */
-            seriesTypes.pie.prototype.verifyDataLabelOverflow = function (overflow) {
-                var center = this.center,
-                    options = this.options,
-                    centerOption = options.center,
-                    minSize = options.minSize || 80,
-                    newSize = minSize, 
-                    // If a size is set, return true and don't try to shrink the pie
-                    // to fit the labels.
-                    ret = options.size !== null;
-                if (!ret) {
-                    // Handle horizontal size and center
-                    if (centerOption[0] !== null) { // Fixed center
-                        newSize = Math.max(center[2] -
-                            Math.max(overflow[1], overflow[3]), minSize);
-                    }
-                    else { // Auto center
-                        newSize = Math.max(
-                        // horizontal overflow
-                        center[2] - overflow[1] - overflow[3], minSize);
-                        // horizontal center
-                        center[0] += (overflow[3] - overflow[1]) / 2;
-                    }
-                    // Handle vertical size and center
-                    if (centerOption[1] !== null) { // Fixed center
-                        newSize = clamp(newSize, minSize, center[2] - Math.max(overflow[0], overflow[2]));
-                    }
-                    else { // Auto center
-                        newSize = clamp(newSize, minSize, 
-                        // vertical overflow
-                        center[2] - overflow[0] - overflow[2]);
-                        // vertical center
-                        center[1] += (overflow[0] - overflow[2]) / 2;
-                    }
-                    // If the size must be decreased, we need to run translate and
-                    // drawDataLabels again
-                    if (newSize < center[2]) {
-                        center[2] = newSize;
-                        center[3] = Math.min(// #3632
-                        relativeLength(options.innerSize || 0, newSize), newSize);
-                        this.translate(center);
-                        if (this.drawDataLabels) {
-                            this.drawDataLabels();
-                        }
-                        // Else, return true to indicate that the pie and its labels is
-                        // within the plot area
-                    }
-                    else {
-                        ret = true;
-                    }
-                }
-                return ret;
-            };
-        }
-        if (seriesTypes.column) {
-            /**
-             * Override the basic data label alignment by adjusting for the position of
-             * the column.
-             *
-             * @private
-             * @function Highcharts.seriesTypes.column#alignDataLabel
-             * @param {Highcharts.Point} point
-             * @param {Highcharts.SVGElement} dataLabel
-             * @param {Highcharts.DataLabelsOptions} options
-             * @param {Highcharts.BBoxObject} alignTo
-             * @param {boolean} [isNew]
-             * @return {void}
-             */
-            seriesTypes.column.prototype.alignDataLabel = function (point, dataLabel, options, alignTo, isNew) {
-                var inverted = this.chart.inverted,
-                    series = point.series, 
-                    // data label box for alignment
-                    dlBox = point.dlBox || point.shapeArgs,
-                    below = pick(point.below, // range series
-                    point.plotY >
-                        pick(this.translatedThreshold,
-                    series.yAxis.len)), 
-                    // draw it inside the box?
-                    inside = pick(options.inside, !!this.options.stacking),
-                    overshoot;
-                // Align to the column itself, or the top of it
-                if (dlBox) { // Area range uses this method but not alignTo
-                    alignTo = merge(dlBox);
-                    if (alignTo.y < 0) {
-                        alignTo.height += alignTo.y;
-                        alignTo.y = 0;
-                    }
-                    // If parts of the box overshoots outside the plot area, modify the
-                    // box to center the label inside
-                    overshoot = alignTo.y + alignTo.height - series.yAxis.len;
-                    if (overshoot > 0 && overshoot < alignTo.height) {
-                        alignTo.height -= overshoot;
-                    }
-                    if (inverted) {
-                        alignTo = {
-                            x: series.yAxis.len - alignTo.y - alignTo.height,
-                            y: series.xAxis.len - alignTo.x - alignTo.width,
-                            width: alignTo.height,
-                            height: alignTo.width
-                        };
-                    }
-                    // Compute the alignment box
-                    if (!inside) {
-                        if (inverted) {
-                            alignTo.x += below ? 0 : alignTo.width;
-                            alignTo.width = 0;
-                        }
-                        else {
-                            alignTo.y += below ? alignTo.height : 0;
-                            alignTo.height = 0;
-                        }
-                    }
-                }
-                // When alignment is undefined (typically columns and bars), display the
-                // individual point below or above the point depending on the threshold
-                options.align = pick(options.align, !inverted || inside ? 'center' : below ? 'right' : 'left');
-                options.verticalAlign = pick(options.verticalAlign, inverted || inside ? 'middle' : below ? 'top' : 'bottom');
-                // Call the parent method
-                CartesianSeries.prototype.alignDataLabel.call(this, point, dataLabel, options, alignTo, isNew);
-                // If label was justified and we have contrast, set it:
-                if (options.inside && point.contrastColor) {
-                    dataLabel.css({
-                        color: point.contrastColor
-                    });
-                }
-            };
-        }
-
-    });
-    _registerModule(_modules, 'Extensions/OverlappingDataLabels.js', [_modules['Core/Chart/Chart.js'], _modules['Core/Utilities.js']], function (Chart, U) {
-        /* *
+        /**
+         * @private
+         * @function Highcharts.StackItem#getStackBox
+         *
+         * @param {Highcharts.Chart} chart
          *
-         *  Highcharts module to hide overlapping data labels.
-         *  This module is included in Highcharts.
+         * @param {Highcharts.StackItem} stackItem
          *
-         *  (c) 2009-2020 Torstein Honsi
+         * @param {number} x
          *
-         *  License: www.highcharts.com/license
+         * @param {number} y
          *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+         * @param {number} xWidth
          *
-         * */
-        var addEvent = U.addEvent,
-            fireEvent = U.fireEvent,
-            isArray = U.isArray,
-            isNumber = U.isNumber,
-            objectEach = U.objectEach,
-            pick = U.pick;
-        /**
-         * Internal type
-         * @private
-         */
-        /* eslint-disable no-invalid-this */
-        // Collect potensial overlapping data labels. Stack labels probably don't need
-        // to be considered because they are usually accompanied by data labels that lie
-        // inside the columns.
-        addEvent(Chart, 'render', function collectAndHide() {
-            var labels = [];
-            // Consider external label collectors
-            (this.labelCollectors || []).forEach(function (collector) {
-                labels = labels.concat(collector());
-            });
-            (this.yAxis || []).forEach(function (yAxis) {
-                if (yAxis.stacking &&
-                    yAxis.options.stackLabels &&
-                    !yAxis.options.stackLabels.allowOverlap) {
-                    objectEach(yAxis.stacking.stacks, function (stack) {
-                        objectEach(stack, function (stackItem) {
-                            labels.push(stackItem.label);
-                        });
-                    });
+         * @param {number} h
+         *
+         * @param {Highcharts.Axis} axis
+         *
+         * @return {Highcharts.BBoxObject}
+         */
+        StackItem.prototype.getStackBox = function (
+          chart,
+          stackItem,
+          x,
+          y,
+          xWidth,
+          h,
+          axis
+        ) {
+          var reversed = stackItem.axis.reversed,
+            inverted = chart.inverted,
+            axisPos =
+              axis.height +
+              axis.pos -
+              (inverted ? chart.plotLeft : chart.plotTop),
+            neg =
+              (stackItem.isNegative && !reversed) ||
+              (!stackItem.isNegative && reversed); // #4056
+          return {
+            x: inverted
+              ? neg
+                ? y - axis.right
+                : y - h + axis.pos - chart.plotLeft
+              : x + chart.xAxis[0].transB - chart.plotLeft,
+            y: inverted
+              ? axis.height - x - xWidth
+              : neg
+              ? axisPos - y - h
+              : axisPos - y,
+            width: inverted ? h : xWidth,
+            height: inverted ? xWidth : h,
+          };
+        };
+        return StackItem;
+      })();
+      /**
+       * Generate stacks for each series and calculate stacks total values
+       *
+       * @private
+       * @function Highcharts.Chart#getStacks
+       */
+      Chart.prototype.getStacks = function () {
+        var chart = this,
+          inverted = chart.inverted;
+        // reset stacks for each yAxis
+        chart.yAxis.forEach(function (axis) {
+          if (axis.stacking && axis.stacking.stacks && axis.hasVisibleSeries) {
+            axis.stacking.oldStacks = axis.stacking.stacks;
+          }
+        });
+        chart.series.forEach(function (series) {
+          var xAxisOptions = (series.xAxis && series.xAxis.options) || {};
+          if (
+            series.options.stacking &&
+            (series.visible === true ||
+              chart.options.chart.ignoreHiddenSeries === false)
+          ) {
+            series.stackKey = [
+              series.type,
+              pick(series.options.stack, ""),
+              inverted ? xAxisOptions.top : xAxisOptions.left,
+              inverted ? xAxisOptions.height : xAxisOptions.width,
+            ].join(",");
+          }
+        });
+      };
+      // Stacking methods defined on the Axis prototype
+      StackingAxis.compose(Axis);
+      // Stacking methods defined for Series prototype
+      /**
+       * Set grouped points in a stack-like object. When `centerInCategory` is true,
+       * and `stacking` is not enabled, we need a pseudo (horizontal) stack in order
+       * to handle grouping of points within the same category.
+       *
+       * @private
+       * @function Highcharts.Series#setStackedPoints
+       * @return {void}
+       */
+      Series.prototype.setGroupedPoints = function () {
+        if (
+          this.options.centerInCategory &&
+          (this.is("column") || this.is("columnrange")) &&
+          // With stacking enabled, we already have stacks that we can compute
+          // from
+          !this.options.stacking &&
+          // With only one series, we don't need to consider centerInCategory
+          this.chart.series.length > 1
+        ) {
+          Series.prototype.setStackedPoints.call(this, "group");
+        }
+      };
+      /**
+       * Adds series' points value to corresponding stack
+       *
+       * @private
+       * @function Highcharts.Series#setStackedPoints
+       */
+      Series.prototype.setStackedPoints = function (stackingParam) {
+        var stacking = stackingParam || this.options.stacking;
+        if (
+          !stacking ||
+          (this.visible !== true &&
+            this.chart.options.chart.ignoreHiddenSeries !== false)
+        ) {
+          return;
+        }
+        var series = this,
+          xData = series.processedXData,
+          yData = series.processedYData,
+          stackedYData = [],
+          yDataLength = yData.length,
+          seriesOptions = series.options,
+          threshold = seriesOptions.threshold,
+          stackThreshold = pick(
+            seriesOptions.startFromThreshold && threshold,
+            0
+          ),
+          stackOption = seriesOptions.stack,
+          stackKey = stackingParam
+            ? series.type + "," + stacking
+            : series.stackKey,
+          negKey = "-" + stackKey,
+          negStacks = series.negStacks,
+          yAxis = series.yAxis,
+          stacks = yAxis.stacking.stacks,
+          oldStacks = yAxis.stacking.oldStacks,
+          stackIndicator,
+          isNegative,
+          stack,
+          other,
+          key,
+          pointKey,
+          i,
+          x,
+          y;
+        yAxis.stacking.stacksTouched += 1;
+        // loop over the non-null y values and read them into a local array
+        for (i = 0; i < yDataLength; i++) {
+          x = xData[i];
+          y = yData[i];
+          stackIndicator = series.getStackIndicator(
+            stackIndicator,
+            x,
+            series.index
+          );
+          pointKey = stackIndicator.key;
+          // Read stacked values into a stack based on the x value,
+          // the sign of y and the stack key. Stacking is also handled for null
+          // values (#739)
+          isNegative = negStacks && y < (stackThreshold ? 0 : threshold);
+          key = isNegative ? negKey : stackKey;
+          // Create empty object for this stack if it doesn't exist yet
+          if (!stacks[key]) {
+            stacks[key] = {};
+          }
+          // Initialize StackItem for this x
+          if (!stacks[key][x]) {
+            if (oldStacks[key] && oldStacks[key][x]) {
+              stacks[key][x] = oldStacks[key][x];
+              stacks[key][x].total = null;
+            } else {
+              stacks[key][x] = new StackItem(
+                yAxis,
+                yAxis.options.stackLabels,
+                isNegative,
+                x,
+                stackOption
+              );
+            }
+          }
+          // If the StackItem doesn't exist, create it first
+          stack = stacks[key][x];
+          if (y !== null) {
+            stack.points[pointKey] = stack.points[series.index] = [
+              pick(stack.cumulative, stackThreshold),
+            ];
+            // Record the base of the stack
+            if (!defined(stack.cumulative)) {
+              stack.base = pointKey;
+            }
+            stack.touched = yAxis.stacking.stacksTouched;
+            // In area charts, if there are multiple points on the same X value,
+            // let the area fill the full span of those points
+            if (stackIndicator.index > 0 && series.singleStacks === false) {
+              stack.points[pointKey][0] =
+                stack.points[series.index + "," + x + ",0"][0];
+            }
+            // When updating to null, reset the point stack (#7493)
+          } else {
+            stack.points[pointKey] = stack.points[series.index] = null;
+          }
+          // Add value to the stack total
+          if (stacking === "percent") {
+            // Percent stacked column, totals are the same for the positive and
+            // negative stacks
+            other = isNegative ? stackKey : negKey;
+            if (negStacks && stacks[other] && stacks[other][x]) {
+              other = stacks[other][x];
+              stack.total = other.total =
+                Math.max(other.total, stack.total) + Math.abs(y) || 0;
+              // Percent stacked areas
+            } else {
+              stack.total = correctFloat(stack.total + (Math.abs(y) || 0));
+            }
+          } else if (stacking === "group") {
+            // In this stack, the total is the number of valid points
+            if (y !== null) {
+              stack.total = (stack.total || 0) + 1;
+            }
+          } else {
+            stack.total = correctFloat(stack.total + (y || 0));
+          }
+          if (stacking === "group") {
+            // This point's index within the stack, pushed to stack.points[1]
+            stack.cumulative = (stack.total || 1) - 1;
+          } else {
+            stack.cumulative =
+              pick(stack.cumulative, stackThreshold) + (y || 0);
+          }
+          if (y !== null) {
+            stack.points[pointKey].push(stack.cumulative);
+            stackedYData[i] = stack.cumulative;
+            stack.hasValidPoints = true;
+          }
+        }
+        if (stacking === "percent") {
+          yAxis.stacking.usePercentage = true;
+        }
+        if (stacking !== "group") {
+          this.stackedYData = stackedYData; // To be used in getExtremes
+        }
+        // Reset old stacks
+        yAxis.stacking.oldStacks = {};
+      };
+      /**
+       * Iterate over all stacks and compute the absolute values to percent
+       *
+       * @private
+       * @function Highcharts.Series#modifyStacks
+       */
+      Series.prototype.modifyStacks = function () {
+        var series = this,
+          yAxis = series.yAxis,
+          stackKey = series.stackKey,
+          stacks = yAxis.stacking.stacks,
+          processedXData = series.processedXData,
+          stackIndicator,
+          stacking = series.options.stacking;
+        if (series[stacking + "Stacker"]) {
+          // Modifier function exists
+          [stackKey, "-" + stackKey].forEach(function (key) {
+            var i = processedXData.length,
+              x,
+              stack,
+              pointExtremes;
+            while (i--) {
+              x = processedXData[i];
+              stackIndicator = series.getStackIndicator(
+                stackIndicator,
+                x,
+                series.index,
+                key
+              );
+              stack = stacks[key] && stacks[key][x];
+              pointExtremes = stack && stack.points[stackIndicator.key];
+              if (pointExtremes) {
+                series[stacking + "Stacker"](pointExtremes, stack, i);
+              }
+            }
+          });
+        }
+      };
+      /**
+       * Modifier function for percent stacks. Blows up the stack to 100%.
+       *
+       * @private
+       * @function Highcharts.Series#percentStacker
+       * @param {Array<number>} pointExtremes
+       * @param {Highcharts.StackItem} stack
+       * @param {number} i
+       */
+      Series.prototype.percentStacker = function (pointExtremes, stack, i) {
+        var totalFactor = stack.total ? 100 / stack.total : 0;
+        // Y bottom value
+        pointExtremes[0] = correctFloat(pointExtremes[0] * totalFactor);
+        // Y value
+        pointExtremes[1] = correctFloat(pointExtremes[1] * totalFactor);
+        this.stackedYData[i] = pointExtremes[1];
+      };
+      /**
+       * Get stack indicator, according to it's x-value, to determine points with the
+       * same x-value
+       *
+       * @private
+       * @function Highcharts.Series#getStackIndicator
+       * @param {Highcharts.StackItemIndicatorObject|undefined} stackIndicator
+       * @param {number} x
+       * @param {number} index
+       * @param {string} [key]
+       * @return {Highcharts.StackItemIndicatorObject}
+       */
+      Series.prototype.getStackIndicator = function (
+        stackIndicator,
+        x,
+        index,
+        key
+      ) {
+        // Update stack indicator, when:
+        // first point in a stack || x changed || stack type (negative vs positive)
+        // changed:
+        if (
+          !defined(stackIndicator) ||
+          stackIndicator.x !== x ||
+          (key && stackIndicator.key !== key)
+        ) {
+          stackIndicator = {
+            x: x,
+            index: 0,
+            key: key,
+          };
+        } else {
+          stackIndicator.index++;
+        }
+        stackIndicator.key = [index, x, stackIndicator.index].join(",");
+        return stackIndicator;
+      };
+      H.StackItem = StackItem;
+
+      return H.StackItem;
+    }
+  );
+  _registerModule(
+    _modules,
+    "Core/Dynamics.js",
+    [
+      _modules["Core/Animation/AnimationUtilities.js"],
+      _modules["Core/Axis/Axis.js"],
+      _modules["Core/Series/Series.js"],
+      _modules["Core/Chart/Chart.js"],
+      _modules["Core/Globals.js"],
+      _modules["Series/LineSeries.js"],
+      _modules["Core/Options.js"],
+      _modules["Core/Series/Point.js"],
+      _modules["Core/Time.js"],
+      _modules["Core/Utilities.js"],
+    ],
+    function (A, Axis, BaseSeries, Chart, H, LineSeries, O, Point, Time, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      var animate = A.animate,
+        setAnimation = A.setAnimation;
+      var seriesTypes = BaseSeries.seriesTypes;
+      var time = O.time;
+      var addEvent = U.addEvent,
+        createElement = U.createElement,
+        css = U.css,
+        defined = U.defined,
+        erase = U.erase,
+        error = U.error,
+        extend = U.extend,
+        fireEvent = U.fireEvent,
+        isArray = U.isArray,
+        isNumber = U.isNumber,
+        isObject = U.isObject,
+        isString = U.isString,
+        merge = U.merge,
+        objectEach = U.objectEach,
+        pick = U.pick,
+        relativeLength = U.relativeLength,
+        splat = U.splat;
+      /* eslint-disable valid-jsdoc */
+      /**
+       * Remove settings that have not changed, to avoid unnecessary rendering or
+       * computing (#9197).
+       * @private
+       */
+      H.cleanRecursively = function (newer, older) {
+        var result = {};
+        objectEach(newer, function (val, key) {
+          var ob;
+          // Dive into objects (except DOM nodes)
+          if (
+            isObject(newer[key], true) &&
+            !newer.nodeType && // #10044
+            older[key]
+          ) {
+            ob = H.cleanRecursively(newer[key], older[key]);
+            if (Object.keys(ob).length) {
+              result[key] = ob;
+            }
+            // Arrays, primitives and DOM nodes are copied directly
+          } else if (isObject(newer[key]) || newer[key] !== older[key]) {
+            result[key] = newer[key];
+          }
+        });
+        return result;
+      };
+      // Extend the Chart prototype for dynamic methods
+      extend(
+        Chart.prototype,
+        /** @lends Highcharts.Chart.prototype */ {
+          /**
+           * Add a series to the chart after render time. Note that this method should
+           * never be used when adding data synchronously at chart render time, as it
+           * adds expense to the calculations and rendering. When adding data at the
+           * same time as the chart is initialized, add the series as a configuration
+           * option instead. With multiple axes, the `offset` is dynamically adjusted.
+           *
+           * @sample highcharts/members/chart-addseries/
+           *         Add a series from a button
+           * @sample stock/members/chart-addseries/
+           *         Add a series in Highstock
+           *
+           * @function Highcharts.Chart#addSeries
+           *
+           * @param {Highcharts.SeriesOptionsType} options
+           *        The config options for the series.
+           *
+           * @param {boolean} [redraw=true]
+           *        Whether to redraw the chart after adding.
+           *
+           * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation]
+           *        Whether to apply animation, and optionally animation
+           *        configuration.
+           *
+           * @return {Highcharts.Series}
+           *         The newly created series object.
+           *
+           * @fires Highcharts.Chart#event:addSeries
+           * @fires Highcharts.Chart#event:afterAddSeries
+           */
+          addSeries: function (options, redraw, animation) {
+            var series,
+              chart = this;
+            if (options) {
+              // <- not necessary
+              redraw = pick(redraw, true); // defaults to true
+              fireEvent(chart, "addSeries", { options: options }, function () {
+                series = chart.initSeries(options);
+                chart.isDirtyLegend = true;
+                chart.linkSeries();
+                if (series.enabledDataSorting) {
+                  // We need to call `setData` after `linkSeries`
+                  series.setData(options.data, false);
                 }
-            });
-            (this.series || []).forEach(function (series) {
-                var dlOptions = series.options.dataLabels;
-                if (series.visible &&
-                    !(dlOptions.enabled === false && !series._hasPointLabels)) { // #3866
-                    (series.nodes || series.points).forEach(function (point) {
-                        if (point.visible) {
-                            var dataLabels = (isArray(point.dataLabels) ?
-                                    point.dataLabels :
-                                    (point.dataLabel ? [point.dataLabel] : []));
-                            dataLabels.forEach(function (label) {
-                                var options = label.options;
-                                label.labelrank = pick(options.labelrank, point.labelrank, point.shapeArgs && point.shapeArgs.height); // #4118
-                                if (!options.allowOverlap) {
-                                    labels.push(label);
-                                }
-                            });
-                        }
-                    });
+                fireEvent(chart, "afterAddSeries", { series: series });
+                if (redraw) {
+                  chart.redraw(animation);
                 }
+              });
+            }
+            return series;
+          },
+          /**
+           * Add an axis to the chart after render time. Note that this method should
+           * never be used when adding data synchronously at chart render time, as it
+           * adds expense to the calculations and rendering. When adding data at the
+           * same time as the chart is initialized, add the axis as a configuration
+           * option instead.
+           *
+           * @sample highcharts/members/chart-addaxis/
+           *         Add and remove axes
+           *
+           * @function Highcharts.Chart#addAxis
+           *
+           * @param {Highcharts.AxisOptions} options
+           *        The axis options.
+           *
+           * @param {boolean} [isX=false]
+           *        Whether it is an X axis or a value axis.
+           *
+           * @param {boolean} [redraw=true]
+           *        Whether to redraw the chart after adding.
+           *
+           * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation=true]
+           *        Whether and how to apply animation in the redraw.
+           *
+           * @return {Highcharts.Axis}
+           *         The newly generated Axis object.
+           */
+          addAxis: function (options, isX, redraw, animation) {
+            return this.createAxis(isX ? "xAxis" : "yAxis", {
+              axis: options,
+              redraw: redraw,
+              animation: animation,
             });
-            this.hideOverlappingLabels(labels);
-        });
-        /**
-         * Hide overlapping labels. Labels are moved and faded in and out on zoom to
-         * provide a smooth visual imression.
-         *
-         * @private
-         * @function Highcharts.Chart#hideOverlappingLabels
-         * @param {Array<Highcharts.SVGElement>} labels
-         * Rendered data labels
-         * @requires modules/overlapping-datalabels
-         */
-        Chart.prototype.hideOverlappingLabels = function (labels) {
+          },
+          /**
+           * Add a color axis to the chart after render time. Note that this method
+           * should never be used when adding data synchronously at chart render time,
+           * as it adds expense to the calculations and rendering. When adding data at
+           * the same time as the chart is initialized, add the axis as a
+           * configuration option instead.
+           *
+           * @sample highcharts/members/chart-addaxis/
+           *         Add and remove axes
+           *
+           * @function Highcharts.Chart#addColorAxis
+           *
+           * @param {Highcharts.ColorAxisOptions} options
+           *        The axis options.
+           *
+           * @param {boolean} [redraw=true]
+           *        Whether to redraw the chart after adding.
+           *
+           * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation=true]
+           *        Whether and how to apply animation in the redraw.
+           *
+           * @return {Highcharts.ColorAxis}
+           *         The newly generated Axis object.
+           */
+          addColorAxis: function (options, redraw, animation) {
+            return this.createAxis("colorAxis", {
+              axis: options,
+              redraw: redraw,
+              animation: animation,
+            });
+          },
+          /**
+           * Factory for creating different axis types.
+           *
+           * @private
+           * @function Highcharts.Chart#createAxis
+           *
+           * @param {string} type
+           *        An axis type.
+           *
+           * @param {...Array<*>} arguments
+           *        All arguments for the constructor.
+           *
+           * @return {Highcharts.Axis | Highcharts.ColorAxis}
+           *         The newly generated Axis object.
+           */
+          createAxis: function (type, options) {
+            var chartOptions = this.options,
+              isColorAxis = type === "colorAxis",
+              axisOptions = options.axis,
+              redraw = options.redraw,
+              animation = options.animation,
+              userOptions = merge(axisOptions, {
+                index: this[type].length,
+                isX: type === "xAxis",
+              }),
+              axis;
+            if (isColorAxis) {
+              axis = new H.ColorAxis(this, userOptions);
+            } else {
+              axis = new Axis(this, userOptions);
+            }
+            // Push the new axis options to the chart options
+            chartOptions[type] = splat(chartOptions[type] || {});
+            chartOptions[type].push(userOptions);
+            if (isColorAxis) {
+              this.isDirtyLegend = true;
+              // Clear before 'bindAxes' (#11924)
+              this.axes.forEach(function (axis) {
+                axis.series = [];
+              });
+              this.series.forEach(function (series) {
+                series.bindAxes();
+                series.isDirtyData = true;
+              });
+            }
+            if (pick(redraw, true)) {
+              this.redraw(animation);
+            }
+            return axis;
+          },
+          /**
+           * Dim the chart and show a loading text or symbol. Options for the loading
+           * screen are defined in {@link
+           * https://api.highcharts.com/highcharts/loading|the loading options}.
+           *
+           * @sample highcharts/members/chart-hideloading/
+           *         Show and hide loading from a button
+           * @sample highcharts/members/chart-showloading/
+           *         Apply different text labels
+           * @sample stock/members/chart-show-hide-loading/
+           *         Toggle loading in Highstock
+           *
+           * @function Highcharts.Chart#showLoading
+           *
+           * @param {string} [str]
+           *        An optional text to show in the loading label instead of the
+           *        default one. The default text is set in
+           *        [lang.loading](https://api.highcharts.com/highcharts/lang.loading).
+           */
+          showLoading: function (str) {
             var chart = this,
-                len = labels.length,
-                ren = chart.renderer,
-                label,
-                i,
-                j,
-                label1,
-                label2,
-                box1,
-                box2,
-                isLabelAffected = false,
-                isIntersectRect = function (box1,
-                box2) {
-                    return !(box2.x >= box1.x + box1.width ||
-                        box2.x + box2.width <= box1.x ||
-                        box2.y >= box1.y + box1.height ||
-                        box2.y + box2.height <= box1.y);
-            }, 
-            // Get the box with its position inside the chart, as opposed to getBBox
-            // that only reports the position relative to the parent.
-            getAbsoluteBox = function (label) {
-                var pos,
-                    parent,
-                    bBox, 
-                    // Substract the padding if no background or border (#4333)
-                    padding = label.box ? 0 : (label.padding || 0),
-                    lineHeightCorrection = 0,
-                    xOffset = 0,
-                    boxWidth,
-                    alignValue;
-                if (label &&
-                    (!label.alignAttr || label.placed)) {
-                    pos = label.alignAttr || {
-                        x: label.attr('x'),
-                        y: label.attr('y')
-                    };
-                    parent = label.parentGroup;
-                    // Get width and height if pure text nodes (stack labels)
-                    if (!label.width) {
-                        bBox = label.getBBox();
-                        label.width = bBox.width;
-                        label.height = bBox.height;
-                        // Labels positions are computed from top left corner, so
-                        // we need to substract the text height from text nodes too.
-                        lineHeightCorrection = ren
-                            .fontMetrics(null, label.element).h;
-                    }
-                    boxWidth = label.width - 2 * padding;
-                    alignValue = {
-                        left: '0',
-                        center: '0.5',
-                        right: '1'
-                    }[label.alignValue];
-                    if (alignValue) {
-                        xOffset = +alignValue * boxWidth;
-                    }
-                    else if (isNumber(label.x) && Math.round(label.x) !== label.translateX) {
-                        xOffset = label.x - label.translateX;
-                    }
-                    return {
-                        x: pos.x + (parent.translateX || 0) + padding -
-                            (xOffset || 0),
-                        y: pos.y + (parent.translateY || 0) + padding -
-                            lineHeightCorrection,
-                        width: label.width - 2 * padding,
-                        height: label.height - 2 * padding
-                    };
+              options = chart.options,
+              loadingDiv = chart.loadingDiv,
+              loadingOptions = options.loading,
+              setLoadingSize = function () {
+                if (loadingDiv) {
+                  css(loadingDiv, {
+                    left: chart.plotLeft + "px",
+                    top: chart.plotTop + "px",
+                    width: chart.plotWidth + "px",
+                    height: chart.plotHeight + "px",
+                  });
+                }
+              };
+            // create the layer at the first call
+            if (!loadingDiv) {
+              chart.loadingDiv = loadingDiv = createElement(
+                "div",
+                {
+                  className: "highcharts-loading highcharts-loading-hidden",
+                },
+                null,
+                chart.container
+              );
+              chart.loadingSpan = createElement(
+                "span",
+                { className: "highcharts-loading-inner" },
+                null,
+                loadingDiv
+              );
+              addEvent(chart, "redraw", setLoadingSize); // #1080
+            }
+            loadingDiv.className = "highcharts-loading";
+            // Update text
+            chart.loadingSpan.innerHTML = pick(str, options.lang.loading, "");
+            if (!chart.styledMode) {
+              // Update visuals
+              css(
+                loadingDiv,
+                extend(loadingOptions.style, {
+                  zIndex: 10,
+                })
+              );
+              css(chart.loadingSpan, loadingOptions.labelStyle);
+              // Show it
+              if (!chart.loadingShown) {
+                css(loadingDiv, {
+                  opacity: 0,
+                  display: "",
+                });
+                animate(
+                  loadingDiv,
+                  {
+                    opacity: loadingOptions.style.opacity || 0.5,
+                  },
+                  {
+                    duration: loadingOptions.showDuration || 0,
+                  }
+                );
+              }
+            }
+            chart.loadingShown = true;
+            setLoadingSize();
+          },
+          /**
+           * Hide the loading layer.
+           *
+           * @see Highcharts.Chart#showLoading
+           *
+           * @sample highcharts/members/chart-hideloading/
+           *         Show and hide loading from a button
+           * @sample stock/members/chart-show-hide-loading/
+           *         Toggle loading in Highstock
+           *
+           * @function Highcharts.Chart#hideLoading
+           */
+          hideLoading: function () {
+            var options = this.options,
+              loadingDiv = this.loadingDiv;
+            if (loadingDiv) {
+              loadingDiv.className =
+                "highcharts-loading highcharts-loading-hidden";
+              if (!this.styledMode) {
+                animate(
+                  loadingDiv,
+                  {
+                    opacity: 0,
+                  },
+                  {
+                    duration: options.loading.hideDuration || 100,
+                    complete: function () {
+                      css(loadingDiv, { display: "none" });
+                    },
+                  }
+                );
+              }
+            }
+            this.loadingShown = false;
+          },
+          /**
+           * These properties cause isDirtyBox to be set to true when updating. Can be
+           * extended from plugins.
+           */
+          propsRequireDirtyBox: [
+            "backgroundColor",
+            "borderColor",
+            "borderWidth",
+            "borderRadius",
+            "plotBackgroundColor",
+            "plotBackgroundImage",
+            "plotBorderColor",
+            "plotBorderWidth",
+            "plotShadow",
+            "shadow",
+          ],
+          /**
+           * These properties require a full reflow of chart elements, best
+           * implemented through running `Chart.setSize` internally (#8190).
+           * @type {Array}
+           */
+          propsRequireReflow: [
+            "margin",
+            "marginTop",
+            "marginRight",
+            "marginBottom",
+            "marginLeft",
+            "spacing",
+            "spacingTop",
+            "spacingRight",
+            "spacingBottom",
+            "spacingLeft",
+          ],
+          /**
+           * These properties cause all series to be updated when updating. Can be
+           * extended from plugins.
+           */
+          propsRequireUpdateSeries: [
+            "chart.inverted",
+            "chart.polar",
+            "chart.ignoreHiddenSeries",
+            "chart.type",
+            "colors",
+            "plotOptions",
+            "time",
+            "tooltip",
+          ],
+          /**
+           * These collections (arrays) implement update() methods with support for
+           * one-to-one option.
+           */
+          collectionsWithUpdate: ["xAxis", "yAxis", "zAxis", "series"],
+          /**
+           * A generic function to update any element of the chart. Elements can be
+           * enabled and disabled, moved, re-styled, re-formatted etc.
+           *
+           * A special case is configuration objects that take arrays, for example
+           * [xAxis](https://api.highcharts.com/highcharts/xAxis),
+           * [yAxis](https://api.highcharts.com/highcharts/yAxis) or
+           * [series](https://api.highcharts.com/highcharts/series). For these
+           * collections, an `id` option is used to map the new option set to an
+           * existing object. If an existing object of the same id is not found, the
+           * corresponding item is updated. So for example, running `chart.update`
+           * with a series item without an id, will cause the existing chart's series
+           * with the same index in the series array to be updated. When the
+           * `oneToOne` parameter is true, `chart.update` will also take care of
+           * adding and removing items from the collection. Read more under the
+           * parameter description below.
+           *
+           * Note that when changing series data, `chart.update` may mutate the passed
+           * data options.
+           *
+           * See also the
+           * [responsive option set](https://api.highcharts.com/highcharts/responsive).
+           * Switching between `responsive.rules` basically runs `chart.update` under
+           * the hood.
+           *
+           * @sample highcharts/members/chart-update/
+           *         Update chart geometry
+           *
+           * @function Highcharts.Chart#update
+           *
+           * @param {Highcharts.Options} options
+           *        A configuration object for the new chart options.
+           *
+           * @param {boolean} [redraw=true]
+           *        Whether to redraw the chart.
+           *
+           * @param {boolean} [oneToOne=false]
+           *        When `true`, the `series`, `xAxis`, `yAxis` and `annotations`
+           *        collections will be updated one to one, and items will be either
+           *        added or removed to match the new updated options. For example,
+           *        if the chart has two series and we call `chart.update` with a
+           *        configuration containing three series, one will be added. If we
+           *        call `chart.update` with one series, one will be removed. Setting
+           *        an empty `series` array will remove all series, but leaving out
+           *        the`series` property will leave all series untouched. If the
+           *        series have id's, the new series options will be matched by id,
+           *        and the remaining ones removed.
+           *
+           * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation=true]
+           *        Whether to apply animation, and optionally animation
+           *        configuration.
+           *
+           * @fires Highcharts.Chart#event:update
+           * @fires Highcharts.Chart#event:afterUpdate
+           */
+          update: function (options, redraw, oneToOne, animation) {
+            var chart = this,
+              adders = {
+                credits: "addCredits",
+                title: "setTitle",
+                subtitle: "setSubtitle",
+                caption: "setCaption",
+              },
+              optionsChart,
+              updateAllAxes,
+              updateAllSeries,
+              newWidth,
+              newHeight,
+              runSetSize,
+              isResponsiveOptions = options.isResponsiveOptions,
+              itemsForRemoval = [];
+            fireEvent(chart, "update", { options: options });
+            // If there are responsive rules in action, undo the responsive rules
+            // before we apply the updated options and replay the responsive rules
+            // on top from the chart.redraw function (#9617).
+            if (!isResponsiveOptions) {
+              chart.setResponsive(false, true);
+            }
+            options = H.cleanRecursively(options, chart.options);
+            merge(true, chart.userOptions, options);
+            // If the top-level chart option is present, some special updates are
+            // required
+            optionsChart = options.chart;
+            if (optionsChart) {
+              merge(true, chart.options.chart, optionsChart);
+              // Setter function
+              if ("className" in optionsChart) {
+                chart.setClassName(optionsChart.className);
+              }
+              if ("reflow" in optionsChart) {
+                chart.setReflow(optionsChart.reflow);
+              }
+              if (
+                "inverted" in optionsChart ||
+                "polar" in optionsChart ||
+                "type" in optionsChart
+              ) {
+                // Parse options.chart.inverted and options.chart.polar together
+                // with the available series.
+                chart.propFromSeries();
+                updateAllAxes = true;
+              }
+              if ("alignTicks" in optionsChart) {
+                // #6452
+                updateAllAxes = true;
+              }
+              objectEach(optionsChart, function (val, key) {
+                if (
+                  chart.propsRequireUpdateSeries.indexOf("chart." + key) !== -1
+                ) {
+                  updateAllSeries = true;
                 }
-            };
-            for (i = 0; i < len; i++) {
-                label = labels[i];
-                if (label) {
-                    // Mark with initial opacity
-                    label.oldOpacity = label.opacity;
-                    label.newOpacity = 1;
-                    label.absoluteBox = getAbsoluteBox(label);
+                // Only dirty box
+                if (chart.propsRequireDirtyBox.indexOf(key) !== -1) {
+                  chart.isDirtyBox = true;
                 }
+                // Chart setSize
+                if (chart.propsRequireReflow.indexOf(key) !== -1) {
+                  if (isResponsiveOptions) {
+                    chart.isDirtyBox = true;
+                  } else {
+                    runSetSize = true;
+                  }
+                }
+              });
+              if (!chart.styledMode && "style" in optionsChart) {
+                chart.renderer.setStyle(optionsChart.style);
+              }
+            }
+            // Moved up, because tooltip needs updated plotOptions (#6218)
+            if (!chart.styledMode && options.colors) {
+              this.options.colors = options.colors;
             }
-            // Prevent a situation in a gradually rising slope, that each label will
-            // hide the previous one because the previous one always has lower rank.
-            labels.sort(function (a, b) {
-                return (b.labelrank || 0) - (a.labelrank || 0);
+            if (options.time) {
+              // Maintaining legacy global time. If the chart is instanciated
+              // first with global time, then updated with time options, we need
+              // to create a new Time instance to avoid mutating the global time
+              // (#10536).
+              if (this.time === time) {
+                this.time = new Time(options.time);
+              }
+              // If we're updating, the time class is different from other chart
+              // classes (chart.legend, chart.tooltip etc) in that it doesn't know
+              // about the chart. The other chart[something].update functions also
+              // set the chart.options[something]. For the time class however we
+              // need to update the chart options separately. #14230.
+              merge(true, chart.options.time, options.time);
+            }
+            // Some option stuctures correspond one-to-one to chart objects that
+            // have update methods, for example
+            // options.credits => chart.credits
+            // options.legend => chart.legend
+            // options.title => chart.title
+            // options.tooltip => chart.tooltip
+            // options.subtitle => chart.subtitle
+            // options.mapNavigation => chart.mapNavigation
+            // options.navigator => chart.navigator
+            // options.scrollbar => chart.scrollbar
+            objectEach(options, function (val, key) {
+              if (chart[key] && typeof chart[key].update === "function") {
+                chart[key].update(val, false);
+                // If a one-to-one object does not exist, look for an adder function
+              } else if (typeof chart[adders[key]] === "function") {
+                chart[adders[key]](val);
+                // Else, just merge the options. For nodes like loading, noData,
+                // plotOptions
+              } else if (
+                key !== "color" &&
+                chart.collectionsWithUpdate.indexOf(key) === -1
+              ) {
+                merge(true, chart.options[key], options[key]);
+              }
+              if (
+                key !== "chart" &&
+                chart.propsRequireUpdateSeries.indexOf(key) !== -1
+              ) {
+                updateAllSeries = true;
+              }
             });
-            // Detect overlapping labels
-            for (i = 0; i < len; i++) {
-                label1 = labels[i];
-                box1 = label1 && label1.absoluteBox;
-                for (j = i + 1; j < len; ++j) {
-                    label2 = labels[j];
-                    box2 = label2 && label2.absoluteBox;
-                    if (box1 &&
-                        box2 &&
-                        label1 !== label2 && // #6465, polar chart with connectEnds
-                        label1.newOpacity !== 0 &&
-                        label2.newOpacity !== 0) {
-                        if (isIntersectRect(box1, box2)) {
-                            (label1.labelrank < label2.labelrank ? label1 : label2)
-                                .newOpacity = 0;
-                        }
+            // Setters for collections. For axes and series, each item is referred
+            // by an id. If the id is not found, it defaults to the corresponding
+            // item in the collection, so setting one series without an id, will
+            // update the first series in the chart. Setting two series without
+            // an id will update the first and the second respectively (#6019)
+            // chart.update and responsive.
+            this.collectionsWithUpdate.forEach(function (coll) {
+              var indexMap;
+              if (options[coll]) {
+                // In stock charts, the navigator series are also part of the
+                // chart.series array, but those series should not be handled
+                // here (#8196).
+                if (coll === "series") {
+                  indexMap = [];
+                  chart[coll].forEach(function (s, i) {
+                    if (!s.options.isInternal) {
+                      indexMap.push(pick(s.options.index, i));
+                    }
+                  });
+                }
+                splat(options[coll]).forEach(function (newOptions, i) {
+                  var hasId = defined(newOptions.id);
+                  var item;
+                  // Match by id
+                  if (hasId) {
+                    item = chart.get(newOptions.id);
+                  }
+                  // No match by id found, match by index instead
+                  if (!item) {
+                    item = chart[coll][indexMap ? indexMap[i] : i];
+                    // Check if we grabbed an item with an exising but
+                    // different id (#13541)
+                    if (item && hasId && defined(item.options.id)) {
+                      item = void 0;
+                    }
+                  }
+                  if (item && item.coll === coll) {
+                    item.update(newOptions, false);
+                    if (oneToOne) {
+                      item.touched = true;
+                    }
+                  }
+                  // If oneToOne and no matching item is found, add one
+                  if (!item && oneToOne && chart.collectionsWithInit[coll]) {
+                    chart.collectionsWithInit[coll][0].apply(
+                      chart,
+                      // [newOptions, ...extraArguments, redraw=false]
+                      [newOptions]
+                        .concat(
+                          // Not all initializers require extra args
+                          chart.collectionsWithInit[coll][1] || []
+                        )
+                        .concat([false])
+                    ).touched = true;
+                  }
+                });
+                // Add items for removal
+                if (oneToOne) {
+                  chart[coll].forEach(function (item) {
+                    if (!item.touched && !item.options.isInternal) {
+                      itemsForRemoval.push(item);
+                    } else {
+                      delete item.touched;
                     }
+                  });
                 }
+              }
+            });
+            itemsForRemoval.forEach(function (item) {
+              if (item.remove) {
+                item.remove(false);
+              }
+            });
+            if (updateAllAxes) {
+              chart.axes.forEach(function (axis) {
+                axis.update({}, false);
+              });
             }
-            // Hide or show
-            labels.forEach(function (label) {
-                var complete,
-                    newOpacity;
-                if (label) {
-                    newOpacity = label.newOpacity;
-                    if (label.oldOpacity !== newOpacity) {
-                        // Make sure the label is completely hidden to avoid catching
-                        // clicks (#4362)
-                        if (label.alignAttr && label.placed) { // data labels
-                            label[newOpacity ? 'removeClass' : 'addClass']('highcharts-data-label-hidden');
-                            complete = function () {
-                                if (!chart.styledMode) {
-                                    label.css({ pointerEvents: newOpacity ? 'auto' : 'none' });
-                                }
-                                label.visibility = newOpacity ? 'inherit' : 'hidden';
-                            };
-                            isLabelAffected = true;
-                            // Animate or set the opacity
-                            label.alignAttr.opacity = newOpacity;
-                            label[label.isOld ? 'animate' : 'attr'](label.alignAttr, null, complete);
-                            fireEvent(chart, 'afterHideOverlappingLabel');
-                        }
-                        else { // other labels, tick labels
-                            label.attr({
-                                opacity: newOpacity
-                            });
-                        }
-                    }
-                    label.isOld = true;
+            // Certain options require the whole series structure to be thrown away
+            // and rebuilt
+            if (updateAllSeries) {
+              chart.getSeriesOrderByLinks().forEach(function (series) {
+                // Avoid removed navigator series
+                if (series.chart) {
+                  series.update({}, false);
+                }
+              }, this);
+            }
+            // Update size. Redraw is forced.
+            newWidth = optionsChart && optionsChart.width;
+            newHeight = optionsChart && optionsChart.height;
+            if (isString(newHeight)) {
+              newHeight = relativeLength(
+                newHeight,
+                newWidth || chart.chartWidth
+              );
+            }
+            if (
+              // In this case, run chart.setSize with newWidth and newHeight which
+              // are undefined, only for reflowing chart elements because margin
+              // or spacing has been set (#8190)
+              runSetSize ||
+              // In this case, the size is actually set
+              (isNumber(newWidth) && newWidth !== chart.chartWidth) ||
+              (isNumber(newHeight) && newHeight !== chart.chartHeight)
+            ) {
+              chart.setSize(newWidth, newHeight, animation);
+            } else if (pick(redraw, true)) {
+              chart.redraw(animation);
+            }
+            fireEvent(chart, "afterUpdate", {
+              options: options,
+              redraw: redraw,
+              animation: animation,
+            });
+          },
+          /**
+           * Shortcut to set the subtitle options. This can also be done from {@link
+           * Chart#update} or {@link Chart#setTitle}.
+           *
+           * @function Highcharts.Chart#setSubtitle
+           *
+           * @param {Highcharts.SubtitleOptions} options
+           *        New subtitle options. The subtitle text itself is set by the
+           *        `options.text` property.
+           */
+          setSubtitle: function (options, redraw) {
+            this.applyDescription("subtitle", options);
+            this.layOutTitles(redraw);
+          },
+          /**
+           * Set the caption options. This can also be done from {@link
+           * Chart#update}.
+           *
+           * @function Highcharts.Chart#setCaption
+           *
+           * @param {Highcharts.CaptionOptions} options
+           *        New caption options. The caption text itself is set by the
+           *        `options.text` property.
+           */
+          setCaption: function (options, redraw) {
+            this.applyDescription("caption", options);
+            this.layOutTitles(redraw);
+          },
+        }
+      );
+      /**
+       * These collections (arrays) implement `Chart.addSomethig` method used in
+       * chart.update() to create new object in the collection. Equivalent for
+       * deleting is resolved by simple `Somethig.remove()`.
+       *
+       * Note: We need to define these references after initializers are bound to
+       * chart's prototype.
+       */
+      Chart.prototype.collectionsWithInit = {
+        // collectionName: [ initializingMethod, [extraArguments] ]
+        xAxis: [Chart.prototype.addAxis, [true]],
+        yAxis: [Chart.prototype.addAxis, [false]],
+        series: [Chart.prototype.addSeries],
+      };
+      // extend the Point prototype for dynamic methods
+      extend(
+        Point.prototype,
+        /** @lends Highcharts.Point.prototype */ {
+          /**
+           * Update point with new options (typically x/y data) and optionally redraw
+           * the series.
+           *
+           * @sample highcharts/members/point-update-column/
+           *         Update column value
+           * @sample highcharts/members/point-update-pie/
+           *         Update pie slice
+           * @sample maps/members/point-update/
+           *         Update map area value in Highmaps
+           *
+           * @function Highcharts.Point#update
+           *
+           * @param {Highcharts.PointOptionsType} options
+           *        The point options. Point options are handled as described under
+           *        the `series.type.data` item for each series type. For example
+           *        for a line series, if options is a single number, the point will
+           *        be given that number as the marin y value. If it is an array, it
+           *        will be interpreted as x and y values respectively. If it is an
+           *        object, advanced options are applied.
+           *
+           * @param {boolean} [redraw=true]
+           *        Whether to redraw the chart after the point is updated. If doing
+           *        more operations on the chart, it is best practice to set
+           *        `redraw` to false and call `chart.redraw()` after.
+           *
+           * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation=true]
+           *        Whether to apply animation, and optionally animation
+           *        configuration.
+           *
+           * @return {void}
+           *
+           * @fires Highcharts.Point#event:update
+           */
+          update: function (options, redraw, animation, runEvent) {
+            var point = this,
+              series = point.series,
+              graphic = point.graphic,
+              i,
+              chart = series.chart,
+              seriesOptions = series.options;
+            redraw = pick(redraw, true);
+            /**
+             * @private
+             */
+            function update() {
+              point.applyOptions(options);
+              // Update visuals, #4146
+              // Handle dummy graphic elements for a11y, #12718
+              var hasDummyGraphic = graphic && point.hasDummyGraphic;
+              var shouldDestroyGraphic =
+                point.y === null ? !hasDummyGraphic : hasDummyGraphic;
+              if (graphic && shouldDestroyGraphic) {
+                point.graphic = graphic.destroy();
+                delete point.hasDummyGraphic;
+              }
+              if (isObject(options, true)) {
+                // Destroy so we can get new elements
+                if (graphic && graphic.element) {
+                  // "null" is also a valid symbol
+                  if (
+                    options &&
+                    options.marker &&
+                    typeof options.marker.symbol !== "undefined"
+                  ) {
+                    point.graphic = graphic.destroy();
+                  }
+                }
+                if (options && options.dataLabels && point.dataLabel) {
+                  point.dataLabel = point.dataLabel.destroy(); // #2468
+                }
+                if (point.connector) {
+                  point.connector = point.connector.destroy(); // #7243
+                }
+              }
+              // record changes in the parallel arrays
+              i = point.index;
+              series.updateParallelArrays(point, i);
+              // Record the options to options.data. If the old or the new config
+              // is an object, use point options, otherwise use raw options
+              // (#4701, #4916).
+              seriesOptions.data[i] =
+                isObject(seriesOptions.data[i], true) || isObject(options, true)
+                  ? point.options
+                  : pick(options, seriesOptions.data[i]);
+              // redraw
+              series.isDirty = series.isDirtyData = true;
+              if (!series.fixedBox && series.hasCartesianSeries) {
+                // #1906, #2320
+                chart.isDirtyBox = true;
+              }
+              if (seriesOptions.legendType === "point") {
+                // #1831, #1885
+                chart.isDirtyLegend = true;
+              }
+              if (redraw) {
+                chart.redraw(animation);
+              }
+            }
+            // Fire the event with a default handler of doing the update
+            if (runEvent === false) {
+              // When called from setData
+              update();
+            } else {
+              point.firePointEvent("update", { options: options }, update);
+            }
+          },
+          /**
+           * Remove a point and optionally redraw the series and if necessary the axes
+           *
+           * @sample highcharts/plotoptions/series-point-events-remove/
+           *         Remove point and confirm
+           * @sample highcharts/members/point-remove/
+           *         Remove pie slice
+           * @sample maps/members/point-remove/
+           *         Remove selected points in Highmaps
+           *
+           * @function Highcharts.Point#remove
+           *
+           * @param {boolean} [redraw=true]
+           *        Whether to redraw the chart or wait for an explicit call. When
+           *        doing more operations on the chart, for example running
+           *        `point.remove()` in a loop, it is best practice to set `redraw`
+           *        to false and call `chart.redraw()` after.
+           *
+           * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation=false]
+           *        Whether to apply animation, and optionally animation
+           *        configuration.
+           *
+           * @return {void}
+           */
+          remove: function (redraw, animation) {
+            this.series.removePoint(
+              this.series.data.indexOf(this),
+              redraw,
+              animation
+            );
+          },
+        }
+      );
+      // Extend the series prototype for dynamic methods
+      extend(
+        LineSeries.prototype,
+        /** @lends Series.prototype */ {
+          /**
+           * Add a point to the series after render time. The point can be added at
+           * the end, or by giving it an X value, to the start or in the middle of the
+           * series.
+           *
+           * @sample highcharts/members/series-addpoint-append/
+           *         Append point
+           * @sample highcharts/members/series-addpoint-append-and-shift/
+           *         Append and shift
+           * @sample highcharts/members/series-addpoint-x-and-y/
+           *         Both X and Y values given
+           * @sample highcharts/members/series-addpoint-pie/
+           *         Append pie slice
+           * @sample stock/members/series-addpoint/
+           *         Append 100 points in Highstock
+           * @sample stock/members/series-addpoint-shift/
+           *         Append and shift in Highstock
+           * @sample maps/members/series-addpoint/
+           *         Add a point in Highmaps
+           *
+           * @function Highcharts.Series#addPoint
+           *
+           * @param {Highcharts.PointOptionsType} options
+           *        The point options. If options is a single number, a point with
+           *        that y value is appended to the series. If it is an array, it will
+           *        be interpreted as x and y values respectively. If it is an
+           *        object, advanced options as outlined under `series.data` are
+           *        applied.
+           *
+           * @param {boolean} [redraw=true]
+           *        Whether to redraw the chart after the point is added. When adding
+           *        more than one point, it is highly recommended that the redraw
+           *        option be set to false, and instead {@link Chart#redraw} is
+           *        explicitly called after the adding of points is finished.
+           *        Otherwise, the chart will redraw after adding each point.
+           *
+           * @param {boolean} [shift=false]
+           *        If true, a point is shifted off the start of the series as one is
+           *        appended to the end.
+           *
+           * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation]
+           *        Whether to apply animation, and optionally animation
+           *        configuration.
+           *
+           * @param {boolean} [withEvent=true]
+           *        Used internally, whether to fire the series `addPoint` event.
+           *
+           * @return {void}
+           *
+           * @fires Highcharts.Series#event:addPoint
+           */
+          addPoint: function (options, redraw, shift, animation, withEvent) {
+            var series = this,
+              seriesOptions = series.options,
+              data = series.data,
+              chart = series.chart,
+              xAxis = series.xAxis,
+              names = xAxis && xAxis.hasNames && xAxis.names,
+              dataOptions = seriesOptions.data,
+              point,
+              xData = series.xData,
+              isInTheMiddle,
+              i,
+              x;
+            // Optional redraw, defaults to true
+            redraw = pick(redraw, true);
+            // Get options and push the point to xData, yData and series.options. In
+            // series.generatePoints the Point instance will be created on demand
+            // and pushed to the series.data array.
+            point = { series: series };
+            series.pointClass.prototype.applyOptions.apply(point, [options]);
+            x = point.x;
+            // Get the insertion point
+            i = xData.length;
+            if (series.requireSorting && x < xData[i - 1]) {
+              isInTheMiddle = true;
+              while (i && xData[i - 1] > x) {
+                i--;
+              }
+            }
+            // Insert undefined item
+            series.updateParallelArrays(point, "splice", i, 0, 0);
+            // Update it
+            series.updateParallelArrays(point, i);
+            if (names && point.name) {
+              names[x] = point.name;
+            }
+            dataOptions.splice(i, 0, options);
+            if (isInTheMiddle) {
+              series.data.splice(i, 0, null);
+              series.processData();
+            }
+            // Generate points to be added to the legend (#1329)
+            if (seriesOptions.legendType === "point") {
+              series.generatePoints();
+            }
+            // Shift the first point off the parallel arrays
+            if (shift) {
+              if (data[0] && data[0].remove) {
+                data[0].remove(false);
+              } else {
+                data.shift();
+                series.updateParallelArrays(point, "shift");
+                dataOptions.shift();
+              }
+            }
+            // Fire event
+            if (withEvent !== false) {
+              fireEvent(series, "addPoint", { point: point });
+            }
+            // redraw
+            series.isDirty = true;
+            series.isDirtyData = true;
+            if (redraw) {
+              chart.redraw(animation); // Animation is set anyway on redraw, #5665
+            }
+          },
+          /**
+           * Remove a point from the series. Unlike the
+           * {@link Highcharts.Point#remove} method, this can also be done on a point
+           * that is not instanciated because it is outside the view or subject to
+           * Highstock data grouping.
+           *
+           * @sample highcharts/members/series-removepoint/
+           *         Remove cropped point
+           *
+           * @function Highcharts.Series#removePoint
+           *
+           * @param {number} i
+           *        The index of the point in the {@link Highcharts.Series.data|data}
+           *        array.
+           *
+           * @param {boolean} [redraw=true]
+           *        Whether to redraw the chart after the point is added. When
+           *        removing more than one point, it is highly recommended that the
+           *        `redraw` option be set to `false`, and instead {@link
+           *        Highcharts.Chart#redraw} is explicitly called after the adding of
+           *        points is finished.
+           *
+           * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation]
+           *        Whether and optionally how the series should be animated.
+           *
+           * @return {void}
+           *
+           * @fires Highcharts.Point#event:remove
+           */
+          removePoint: function (i, redraw, animation) {
+            var series = this,
+              data = series.data,
+              point = data[i],
+              points = series.points,
+              chart = series.chart,
+              remove = function () {
+                if (points && points.length === data.length) {
+                  // #4935
+                  points.splice(i, 1);
+                }
+                data.splice(i, 1);
+                series.options.data.splice(i, 1);
+                series.updateParallelArrays(
+                  point || { series: series },
+                  "splice",
+                  i,
+                  1
+                );
+                if (point) {
+                  point.destroy();
                 }
+                // redraw
+                series.isDirty = true;
+                series.isDirtyData = true;
+                if (redraw) {
+                  chart.redraw();
+                }
+              };
+            setAnimation(animation, chart);
+            redraw = pick(redraw, true);
+            // Fire the event with a default handler of removing the point
+            if (point) {
+              point.firePointEvent("remove", null, remove);
+            } else {
+              remove();
+            }
+          },
+          /**
+           * Remove a series and optionally redraw the chart.
+           *
+           * @sample highcharts/members/series-remove/
+           *         Remove first series from a button
+           *
+           * @function Highcharts.Series#remove
+           *
+           * @param {boolean} [redraw=true]
+           *        Whether to redraw the chart or wait for an explicit call to
+           *        {@link Highcharts.Chart#redraw}.
+           *
+           * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation]
+           *        Whether to apply animation, and optionally animation
+           *        configuration.
+           *
+           * @param {boolean} [withEvent=true]
+           *        Used internally, whether to fire the series `remove` event.
+           *
+           * @return {void}
+           *
+           * @fires Highcharts.Series#event:remove
+           */
+          remove: function (redraw, animation, withEvent, keepEvents) {
+            var series = this,
+              chart = series.chart;
+            /**
+             * @private
+             */
+            function remove() {
+              // Destroy elements
+              series.destroy(keepEvents);
+              series.remove = null; // Prevent from doing again (#9097)
+              // Redraw
+              chart.isDirtyLegend = chart.isDirtyBox = true;
+              chart.linkSeries();
+              if (pick(redraw, true)) {
+                chart.redraw(animation);
+              }
+            }
+            // Fire the event with a default handler of removing the point
+            if (withEvent !== false) {
+              fireEvent(series, "remove", null, remove);
+            } else {
+              remove();
+            }
+          },
+          /**
+           * Update the series with a new set of options. For a clean and precise
+           * handling of new options, all methods and elements from the series are
+           * removed, and it is initialized from scratch. Therefore, this method is
+           * more performance expensive than some other utility methods like {@link
+           * Series#setData} or {@link Series#setVisible}.
+           *
+           * Note that `Series.update` may mutate the passed `data` options.
+           *
+           * @sample highcharts/members/series-update/
+           *         Updating series options
+           * @sample maps/members/series-update/
+           *         Update series options in Highmaps
+           *
+           * @function Highcharts.Series#update
+           *
+           * @param {Highcharts.SeriesOptionsType} options
+           *        New options that will be merged with the series' existing options.
+           *
+           * @param {boolean} [redraw=true]
+           *        Whether to redraw the chart after the series is altered. If doing
+           *        more operations on the chart, it is a good idea to set redraw to
+           *        false and call {@link Chart#redraw} after.
+           *
+           * @return {void}
+           *
+           * @fires Highcharts.Series#event:update
+           * @fires Highcharts.Series#event:afterUpdate
+           */
+          update: function (options, redraw) {
+            options = H.cleanRecursively(options, this.userOptions);
+            fireEvent(this, "update", { options: options });
+            var series = this,
+              chart = series.chart,
+              // must use user options when changing type because series.options
+              // is merged in with type specific plotOptions
+              oldOptions = series.userOptions,
+              seriesOptions,
+              initialType = series.initialType || series.type,
+              plotOptions = chart.options.plotOptions,
+              newType =
+                options.type || oldOptions.type || chart.options.chart.type,
+              keepPoints = !(
+                // Indicators, histograms etc recalculate the data. It should be
+                // possible to omit this.
+                (
+                  this.hasDerivedData ||
+                  // New type requires new point classes
+                  (newType && newType !== this.type) ||
+                  // New options affecting how the data points are built
+                  typeof options.pointStart !== "undefined" ||
+                  typeof options.pointInterval !== "undefined" ||
+                  // Changes to data grouping requires new points in new group
+                  series.hasOptionChanged("dataGrouping") ||
+                  series.hasOptionChanged("pointStart") ||
+                  series.hasOptionChanged("pointInterval") ||
+                  series.hasOptionChanged("pointIntervalUnit") ||
+                  series.hasOptionChanged("keys")
+                )
+              ),
+              initialSeriesProto = seriesTypes[initialType].prototype,
+              n,
+              groups = [
+                "group",
+                "markerGroup",
+                "dataLabelsGroup",
+                "transformGroup",
+              ],
+              preserve = ["eventOptions", "navigatorSeries", "baseSeries"],
+              // Animation must be enabled when calling update before the initial
+              // animation has first run. This happens when calling update
+              // directly after chart initialization, or when applying responsive
+              // rules (#6912).
+              animation = series.finishedAnimating && { animation: false },
+              kinds = {};
+            if (keepPoints) {
+              preserve.push(
+                "data",
+                "isDirtyData",
+                "points",
+                "processedXData",
+                "processedYData",
+                "xIncrement",
+                "cropped",
+                "_hasPointMarkers",
+                "_hasPointLabels",
+                // Map specific, consider moving it to series-specific preserve-
+                // properties (#10617)
+                "mapMap",
+                "mapData",
+                "minY",
+                "maxY",
+                "minX",
+                "maxX"
+              );
+              if (options.visible !== false) {
+                preserve.push("area", "graph");
+              }
+              series.parallelArrays.forEach(function (key) {
+                preserve.push(key + "Data");
+              });
+              if (options.data) {
+                // setData uses dataSorting options so we need to update them
+                // earlier
+                if (options.dataSorting) {
+                  extend(series.options.dataSorting, options.dataSorting);
+                }
+                this.setData(options.data, false);
+              }
+            }
+            // Do the merge, with some forced options
+            options = merge(
+              oldOptions,
+              animation,
+              {
+                // When oldOptions.index is null it should't be cleared.
+                // Otherwise navigator series will have wrong indexes (#10193).
+                index:
+                  typeof oldOptions.index === "undefined"
+                    ? series.index
+                    : oldOptions.index,
+                pointStart: pick(
+                  // when updating from blank (#7933)
+                  plotOptions &&
+                    plotOptions.series &&
+                    plotOptions.series.pointStart,
+                  oldOptions.pointStart,
+                  // when updating after addPoint
+                  series.xData[0]
+                ),
+              },
+              !keepPoints && { data: series.options.data },
+              options
+            );
+            // Merge does not merge arrays, but replaces them. Since points were
+            // updated, `series.options.data` has correct merged options, use it:
+            if (keepPoints && options.data) {
+              options.data = series.options.data;
+            }
+            // Make sure preserved properties are not destroyed (#3094)
+            preserve = groups.concat(preserve);
+            preserve.forEach(function (prop) {
+              preserve[prop] = series[prop];
+              delete series[prop];
             });
-            if (isLabelAffected) {
-                fireEvent(chart, 'afterHideAllOverlappingLabels');
+            // Destroy the series and delete all properties. Reinsert all
+            // methods and properties from the new type prototype (#2270,
+            // #3719).
+            series.remove(false, null, false, true);
+            for (n in initialSeriesProto) {
+              // eslint-disable-line guard-for-in
+              series[n] = void 0;
             }
-        };
-
-    });
-    _registerModule(_modules, 'Core/Interaction.js', [_modules['Core/Series/Series.js'], _modules['Core/Chart/Chart.js'], _modules['Core/Globals.js'], _modules['Core/Legend.js'], _modules['Series/LineSeries.js'], _modules['Core/Options.js'], _modules['Core/Series/Point.js'], _modules['Core/Utilities.js']], function (BaseSeries, Chart, H, Legend, LineSeries, O, Point, U) {
-        /* *
-         *
-         *  (c) 2010-2020 Torstein Honsi
-         *
-         *  License: www.highcharts.com/license
-         *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
-         *
-         * */
-        var seriesTypes = BaseSeries.seriesTypes;
-        var hasTouch = H.hasTouch,
-            svg = H.svg;
-        var defaultOptions = O.defaultOptions;
-        var addEvent = U.addEvent,
-            createElement = U.createElement,
-            css = U.css,
-            defined = U.defined,
-            extend = U.extend,
-            fireEvent = U.fireEvent,
-            isArray = U.isArray,
-            isFunction = U.isFunction,
-            isNumber = U.isNumber,
-            isObject = U.isObject,
-            merge = U.merge,
-            objectEach = U.objectEach,
-            pick = U.pick;
-        /**
-         * @interface Highcharts.PointEventsOptionsObject
-         */ /**
-        * Fires when the point is selected either programmatically or following a click
-        * on the point. One parameter, `event`, is passed to the function. Returning
-        * `false` cancels the operation.
-        * @name Highcharts.PointEventsOptionsObject#select
-        * @type {Highcharts.PointSelectCallbackFunction|undefined}
-        */ /**
-        * Fires when the point is unselected either programmatically or following a
-        * click on the point. One parameter, `event`, is passed to the function.
-        * Returning `false` cancels the operation.
-        * @name Highcharts.PointEventsOptionsObject#unselect
-        * @type {Highcharts.PointUnselectCallbackFunction|undefined}
-        */
-        /**
-         * Information about the select/unselect event.
-         *
-         * @interface Highcharts.PointInteractionEventObject
-         * @extends global.Event
-         */ /**
-        * @name Highcharts.PointInteractionEventObject#accumulate
-        * @type {boolean}
-        */
+            if (seriesTypes[newType || initialType]) {
+              extend(series, seriesTypes[newType || initialType].prototype);
+            } else {
+              error(17, true, chart, {
+                missingModuleFor: newType || initialType,
+              });
+            }
+            // Re-register groups (#3094) and other preserved properties
+            preserve.forEach(function (prop) {
+              series[prop] = preserve[prop];
+            });
+            series.init(chart, options);
+            // Remove particular elements of the points. Check `series.options`
+            // because we need to consider the options being set on plotOptions as
+            // well.
+            if (keepPoints && this.points) {
+              seriesOptions = series.options;
+              // What kind of elements to destroy
+              if (seriesOptions.visible === false) {
+                kinds.graphic = 1;
+                kinds.dataLabel = 1;
+              } else if (!series._hasPointLabels) {
+                var marker = seriesOptions.marker,
+                  dataLabels = seriesOptions.dataLabels;
+                if (
+                  marker &&
+                  (marker.enabled === false || "symbol" in marker) // #10870
+                ) {
+                  kinds.graphic = 1;
+                }
+                if (dataLabels && dataLabels.enabled === false) {
+                  kinds.dataLabel = 1;
+                }
+              }
+              this.points.forEach(function (point) {
+                if (point && point.series) {
+                  point.resolveColor();
+                  // Destroy elements in order to recreate based on updated
+                  // series options.
+                  if (Object.keys(kinds).length) {
+                    point.destroyElements(kinds);
+                  }
+                  if (
+                    seriesOptions.showInLegend === false &&
+                    point.legendItem
+                  ) {
+                    chart.legend.destroyItem(point);
+                  }
+                }
+              }, this);
+            }
+            series.initialType = initialType;
+            chart.linkSeries(); // Links are lost in series.remove (#3028)
+            fireEvent(this, "afterUpdate");
+            if (pick(redraw, true)) {
+              chart.redraw(keepPoints ? void 0 : false);
+            }
+          },
+          /**
+           * Used from within series.update
+           *
+           * @private
+           * @function Highcharts.Series#setName
+           *
+           * @param {string} name
+           *
+           * @return {void}
+           */
+          setName: function (name) {
+            this.name = this.options.name = this.userOptions.name = name;
+            this.chart.isDirtyLegend = true;
+          },
+          /**
+           * Check if the option has changed.
+           *
+           * @private
+           * @function Highcharts.Series#hasOptionChanged
+           *
+           * @param {string} option
+           *
+           * @return {boolean}
+           */
+          hasOptionChanged: function (optionName) {
+            var chart = this.chart,
+              option = this.options[optionName],
+              plotOptions = chart.options.plotOptions,
+              oldOption = this.userOptions[optionName];
+            if (oldOption) {
+              return option !== oldOption;
+            }
+            return (
+              option !==
+              pick(
+                plotOptions &&
+                  plotOptions[this.type] &&
+                  plotOptions[this.type][optionName],
+                plotOptions &&
+                  plotOptions.series &&
+                  plotOptions.series[optionName],
+                option
+              )
+            );
+          },
+        }
+      );
+      // Extend the Axis.prototype for dynamic methods
+      extend(
+        Axis.prototype,
+        /** @lends Highcharts.Axis.prototype */ {
+          /**
+           * Update an axis object with a new set of options. The options are merged
+           * with the existing options, so only new or altered options need to be
+           * specified.
+           *
+           * @sample highcharts/members/axis-update/
+           *         Axis update demo
+           *
+           * @function Highcharts.Axis#update
+           *
+           * @param {Highcharts.AxisOptions} options
+           *        The new options that will be merged in with existing options on
+           *        the axis.
+           *
+           * @param {boolean} [redraw=true]
+           *        Whether to redraw the chart after the axis is altered. If doing
+           *        more operations on the chart, it is a good idea to set redraw to
+           *        false and call {@link Chart#redraw} after.
+           *
+           * @return {void}
+           */
+          update: function (options, redraw) {
+            var chart = this.chart,
+              newEvents = (options && options.events) || {};
+            options = merge(this.userOptions, options);
+            // Color Axis is not an array,
+            // This change is applied in the ColorAxis wrapper
+            if (chart.options[this.coll].indexOf) {
+              // Don't use this.options.index,
+              // StockChart has Axes in navigator too
+              chart.options[this.coll][
+                chart.options[this.coll].indexOf(this.userOptions)
+              ] = options;
+            }
+            // Remove old events, if no new exist (#8161)
+            objectEach(chart.options[this.coll].events, function (fn, ev) {
+              if (typeof newEvents[ev] === "undefined") {
+                newEvents[ev] = void 0;
+              }
+            });
+            this.destroy(true);
+            this.init(chart, extend(options, { events: newEvents }));
+            chart.isDirtyBox = true;
+            if (pick(redraw, true)) {
+              chart.redraw();
+            }
+          },
+          /**
+           * Remove the axis from the chart.
+           *
+           * @sample highcharts/members/chart-addaxis/
+           *         Add and remove axes
+           *
+           * @function Highcharts.Axis#remove
+           *
+           * @param {boolean} [redraw=true]
+           *        Whether to redraw the chart following the remove.
+           *
+           * @return {void}
+           */
+          remove: function (redraw) {
+            var chart = this.chart,
+              key = this.coll, // xAxis or yAxis
+              axisSeries = this.series,
+              i = axisSeries.length;
+            // Remove associated series (#2687)
+            while (i--) {
+              if (axisSeries[i]) {
+                axisSeries[i].remove(false);
+              }
+            }
+            // Remove the axis
+            erase(chart.axes, this);
+            erase(chart[key], this);
+            if (isArray(chart.options[key])) {
+              chart.options[key].splice(this.options.index, 1);
+            } else {
+              // color axis, #6488
+              delete chart.options[key];
+            }
+            chart[key].forEach(function (axis, i) {
+              // Re-index, #1706, #8075
+              axis.options.index = axis.userOptions.index = i;
+            });
+            this.destroy();
+            chart.isDirtyBox = true;
+            if (pick(redraw, true)) {
+              chart.redraw();
+            }
+          },
+          /**
+           * Update the axis title by options after render time.
+           *
+           * @sample highcharts/members/axis-settitle/
+           *         Set a new Y axis title
+           *
+           * @function Highcharts.Axis#setTitle
+           *
+           * @param {Highcharts.AxisTitleOptions} titleOptions
+           *        The additional title options.
+           *
+           * @param {boolean} [redraw=true]
+           *        Whether to redraw the chart after setting the title.
+           *
+           * @return {void}
+           */
+          setTitle: function (titleOptions, redraw) {
+            this.update({ title: titleOptions }, redraw);
+          },
+          /**
+           * Set new axis categories and optionally redraw.
+           *
+           * @sample highcharts/members/axis-setcategories/
+           *         Set categories by click on a button
+           *
+           * @function Highcharts.Axis#setCategories
+           *
+           * @param {Array<string>} categories
+           *        The new categories.
+           *
+           * @param {boolean} [redraw=true]
+           *        Whether to redraw the chart.
+           *
+           * @return {void}
+           */
+          setCategories: function (categories, redraw) {
+            this.update({ categories: categories }, redraw);
+          },
+        }
+      );
+    }
+  );
+  _registerModule(
+    _modules,
+    "Series/AreaSeries.js",
+    [
+      _modules["Core/Series/Series.js"],
+      _modules["Core/Color/Color.js"],
+      _modules["Core/Globals.js"],
+      _modules["Mixins/LegendSymbol.js"],
+      _modules["Core/Utilities.js"],
+    ],
+    function (BaseSeries, Color, H, LegendSymbolMixin, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      var color = Color.parse;
+      var objectEach = U.objectEach,
+        pick = U.pick;
+      var Series = H.Series;
+      /**
+       * Area series type.
+       *
+       * @private
+       * @class
+       * @name Highcharts.seriesTypes.area
+       *
+       * @augments Highcharts.Series
+       */
+      BaseSeries.seriesType(
+        "area",
+        "line",
         /**
-         * Gets fired when the point is selected either programmatically or following a
-         * click on the point.
-         *
-         * @callback Highcharts.PointSelectCallbackFunction
+         * The area series type.
          *
-         * @param {Highcharts.Point} this
-         *        Point where the event occured.
+         * @sample {highcharts} highcharts/demo/area-basic/
+         *         Area chart
+         * @sample {highstock} stock/demo/area/
+         *         Area chart
          *
-         * @param {Highcharts.PointInteractionEventObject} event
-         *        Event that occured.
+         * @extends      plotOptions.line
+         * @excluding    useOhlcData
+         * @product      highcharts highstock
+         * @optionparent plotOptions.area
          */
+        {
+          /**
+           * @see [fillColor](#plotOptions.area.fillColor)
+           * @see [fillOpacity](#plotOptions.area.fillOpacity)
+           *
+           * @apioption plotOptions.area.color
+           */
+          /**
+           * Fill color or gradient for the area. When `null`, the series' `color`
+           * is used with the series' `fillOpacity`.
+           *
+           * In styled mode, the fill color can be set with the `.highcharts-area`
+           * class name.
+           *
+           * @see [color](#plotOptions.area.color)
+           * @see [fillOpacity](#plotOptions.area.fillOpacity)
+           *
+           * @sample {highcharts} highcharts/plotoptions/area-fillcolor-default/
+           *         Null by default
+           * @sample {highcharts} highcharts/plotoptions/area-fillcolor-gradient/
+           *         Gradient
+           *
+           * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+           * @product   highcharts highstock
+           * @apioption plotOptions.area.fillColor
+           */
+          /**
+           * Fill opacity for the area. When you set an explicit `fillColor`,
+           * the `fillOpacity` is not applied. Instead, you should define the
+           * opacity in the `fillColor` with an rgba color definition. The
+           * `fillOpacity` setting, also the default setting, overrides the alpha
+           * component of the `color` setting.
+           *
+           * In styled mode, the fill opacity can be set with the
+           * `.highcharts-area` class name.
+           *
+           * @see [color](#plotOptions.area.color)
+           * @see [fillColor](#plotOptions.area.fillColor)
+           *
+           * @sample {highcharts} highcharts/plotoptions/area-fillopacity/
+           *         Automatic fill color and fill opacity of 0.1
+           *
+           * @type      {number}
+           * @default   {highcharts} 0.75
+           * @default   {highstock} 0.75
+           * @product   highcharts highstock
+           * @apioption plotOptions.area.fillOpacity
+           */
+          /**
+           * A separate color for the graph line. By default the line takes the
+           * `color` of the series, but the lineColor setting allows setting a
+           * separate color for the line without altering the `fillColor`.
+           *
+           * In styled mode, the line stroke can be set with the
+           * `.highcharts-graph` class name.
+           *
+           * @sample {highcharts} highcharts/plotoptions/area-linecolor/
+           *         Dark gray line
+           *
+           * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+           * @product   highcharts highstock
+           * @apioption plotOptions.area.lineColor
+           */
+          /**
+           * A separate color for the negative part of the area.
+           *
+           * In styled mode, a negative color is set with the
+           * `.highcharts-negative` class name.
+           *
+           * @see [negativeColor](#plotOptions.area.negativeColor)
+           *
+           * @sample {highcharts} highcharts/css/series-negative-color/
+           *         Negative color in styled mode
+           *
+           * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+           * @since     3.0
+           * @product   highcharts
+           * @apioption plotOptions.area.negativeFillColor
+           */
+          /**
+           * Whether the whole area or just the line should respond to mouseover
+           * tooltips and other mouse or touch events.
+           *
+           * @sample {highcharts|highstock} highcharts/plotoptions/area-trackbyarea/
+           *         Display the tooltip when the area is hovered
+           *
+           * @type      {boolean}
+           * @default   false
+           * @since     1.1.6
+           * @product   highcharts highstock
+           * @apioption plotOptions.area.trackByArea
+           */
+          /**
+           * The Y axis value to serve as the base for the area, for
+           * distinguishing between values above and below a threshold. The area
+           * between the graph and the threshold is filled.
+           *
+           * * If a number is given, the Y axis will scale to the threshold.
+           * * If `null`, the scaling behaves like a line series with fill between
+           *   the graph and the Y axis minimum.
+           * * If `Infinity` or `-Infinity`, the area between the graph and the
+           *   corresponding Y axis extreme is filled (since v6.1.0).
+           *
+           * @sample {highcharts} highcharts/plotoptions/area-threshold/
+           *         A threshold of 100
+           * @sample {highcharts} highcharts/plotoptions/area-threshold-infinity/
+           *         A threshold of Infinity
+           *
+           * @type    {number|null}
+           * @since   2.0
+           * @product highcharts highstock
+           */
+          threshold: 0,
+        },
+        /* eslint-disable valid-jsdoc */
         /**
-         * Fires when the point is unselected either programmatically or following a
-         * click on the point.
-         *
-         * @callback Highcharts.PointUnselectCallbackFunction
+         * @lends seriesTypes.area.prototype
+         */
+        {
+          singleStacks: false,
+          /**
+           * Return an array of stacked points, where null and missing points are
+           * replaced by dummy points in order for gaps to be drawn correctly in
+           * stacks.
+           * @private
+           */
+          getStackPoints: function (points) {
+            var series = this,
+              segment = [],
+              keys = [],
+              xAxis = this.xAxis,
+              yAxis = this.yAxis,
+              stack = yAxis.stacking.stacks[this.stackKey],
+              pointMap = {},
+              seriesIndex = series.index,
+              yAxisSeries = yAxis.series,
+              seriesLength = yAxisSeries.length,
+              visibleSeries,
+              upOrDown = pick(yAxis.options.reversedStacks, true) ? 1 : -1,
+              i;
+            points = points || this.points;
+            if (this.options.stacking) {
+              for (i = 0; i < points.length; i++) {
+                // Reset after point update (#7326)
+                points[i].leftNull = points[i].rightNull = void 0;
+                // Create a map where we can quickly look up the points by
+                // their X values.
+                pointMap[points[i].x] = points[i];
+              }
+              // Sort the keys (#1651)
+              objectEach(stack, function (stackX, x) {
+                // nulled after switching between
+                // grouping and not (#1651, #2336)
+                if (stackX.total !== null) {
+                  keys.push(x);
+                }
+              });
+              keys.sort(function (a, b) {
+                return a - b;
+              });
+              visibleSeries = yAxisSeries.map(function (s) {
+                return s.visible;
+              });
+              keys.forEach(function (x, idx) {
+                var y = 0,
+                  stackPoint,
+                  stackedValues;
+                if (pointMap[x] && !pointMap[x].isNull) {
+                  segment.push(pointMap[x]);
+                  // Find left and right cliff. -1 goes left, 1 goes
+                  // right.
+                  [-1, 1].forEach(function (direction) {
+                    var nullName = direction === 1 ? "rightNull" : "leftNull",
+                      cliffName = direction === 1 ? "rightCliff" : "leftCliff",
+                      cliff = 0,
+                      otherStack = stack[keys[idx + direction]];
+                    // If there is a stack next to this one,
+                    // to the left or to the right...
+                    if (otherStack) {
+                      i = seriesIndex;
+                      // Can go either up or down,
+                      // depending on reversedStacks
+                      while (i >= 0 && i < seriesLength) {
+                        stackPoint = otherStack.points[i];
+                        if (!stackPoint) {
+                          // If the next point in this series
+                          // is missing, mark the point
+                          // with point.leftNull or
+                          // point.rightNull = true.
+                          if (i === seriesIndex) {
+                            pointMap[x][nullName] = true;
+                            // If there are missing points in
+                            // the next stack in any of the
+                            // series below this one, we need
+                            // to substract the missing values
+                            // and add a hiatus to the left or
+                            // right.
+                          } else if (visibleSeries[i]) {
+                            stackedValues = stack[x].points[i];
+                            if (stackedValues) {
+                              cliff -= stackedValues[1] - stackedValues[0];
+                            }
+                          }
+                        }
+                        // When reversedStacks is true, loop up,
+                        // else loop down
+                        i += upOrDown;
+                      }
+                    }
+                    pointMap[x][cliffName] = cliff;
+                  });
+                  // There is no point for this X value in this series, so we
+                  // insert a dummy point in order for the areas to be drawn
+                  // correctly.
+                } else {
+                  // Loop down the stack to find the series below this
+                  // one that has a value (#1991)
+                  i = seriesIndex;
+                  while (i >= 0 && i < seriesLength) {
+                    stackPoint = stack[x].points[i];
+                    if (stackPoint) {
+                      y = stackPoint[1];
+                      break;
+                    }
+                    // When reversedStacks is true, loop up, else loop
+                    // down
+                    i += upOrDown;
+                  }
+                  y = yAxis.translate(
+                    // #6272
+                    y,
+                    0,
+                    1,
+                    0,
+                    1
+                  );
+                  segment.push({
+                    isNull: true,
+                    plotX: xAxis.translate(
+                      // #6272
+                      x,
+                      0,
+                      0,
+                      0,
+                      1
+                    ),
+                    x: x,
+                    plotY: y,
+                    yBottom: y,
+                  });
+                }
+              });
+            }
+            return segment;
+          },
+          /**
+           * @private
+           */
+          getGraphPath: function (points) {
+            var getGraphPath = Series.prototype.getGraphPath,
+              graphPath,
+              options = this.options,
+              stacking = options.stacking,
+              yAxis = this.yAxis,
+              topPath,
+              bottomPath,
+              bottomPoints = [],
+              graphPoints = [],
+              seriesIndex = this.index,
+              i,
+              areaPath,
+              plotX,
+              stacks = yAxis.stacking.stacks[this.stackKey],
+              threshold = options.threshold,
+              translatedThreshold = Math.round(
+                // #10909
+                yAxis.getThreshold(options.threshold)
+              ),
+              isNull,
+              yBottom,
+              connectNulls = pick(
+                // #10574
+                options.connectNulls,
+                stacking === "percent"
+              ),
+              // To display null points in underlying stacked series, this
+              // series graph must be broken, and the area also fall down to
+              // fill the gap left by the null point. #2069
+              addDummyPoints = function (i, otherI, side) {
+                var point = points[i],
+                  stackedValues =
+                    stacking && stacks[point.x].points[seriesIndex],
+                  nullVal = point[side + "Null"] || 0,
+                  cliffVal = point[side + "Cliff"] || 0,
+                  top,
+                  bottom,
+                  isNull = true;
+                if (cliffVal || nullVal) {
+                  top =
+                    (nullVal ? stackedValues[0] : stackedValues[1]) + cliffVal;
+                  bottom = stackedValues[0] + cliffVal;
+                  isNull = !!nullVal;
+                } else if (
+                  !stacking &&
+                  points[otherI] &&
+                  points[otherI].isNull
+                ) {
+                  top = bottom = threshold;
+                }
+                // Add to the top and bottom line of the area
+                if (typeof top !== "undefined") {
+                  graphPoints.push({
+                    plotX: plotX,
+                    plotY:
+                      top === null
+                        ? translatedThreshold
+                        : yAxis.getThreshold(top),
+                    isNull: isNull,
+                    isCliff: true,
+                  });
+                  bottomPoints.push({
+                    plotX: plotX,
+                    plotY:
+                      bottom === null
+                        ? translatedThreshold
+                        : yAxis.getThreshold(bottom),
+                    doCurve: false, // #1041, gaps in areaspline areas
+                  });
+                }
+              };
+            // Find what points to use
+            points = points || this.points;
+            // Fill in missing points
+            if (stacking) {
+              points = this.getStackPoints(points);
+            }
+            for (i = 0; i < points.length; i++) {
+              // Reset after series.update of stacking property (#12033)
+              if (!stacking) {
+                points[i].leftCliff =
+                  points[i].rightCliff =
+                  points[i].leftNull =
+                  points[i].rightNull =
+                    void 0;
+              }
+              isNull = points[i].isNull;
+              plotX = pick(points[i].rectPlotX, points[i].plotX);
+              yBottom = stacking ? points[i].yBottom : translatedThreshold;
+              if (!isNull || connectNulls) {
+                if (!connectNulls) {
+                  addDummyPoints(i, i - 1, "left");
+                }
+                // Skip null point when stacking is false and connectNulls
+                // true
+                if (!(isNull && !stacking && connectNulls)) {
+                  graphPoints.push(points[i]);
+                  bottomPoints.push({
+                    x: i,
+                    plotX: plotX,
+                    plotY: yBottom,
+                  });
+                }
+                if (!connectNulls) {
+                  addDummyPoints(i, i + 1, "right");
+                }
+              }
+            }
+            topPath = getGraphPath.call(this, graphPoints, true, true);
+            bottomPoints.reversed = true;
+            bottomPath = getGraphPath.call(this, bottomPoints, true, true);
+            var firstBottomPoint = bottomPath[0];
+            if (firstBottomPoint && firstBottomPoint[0] === "M") {
+              bottomPath[0] = ["L", firstBottomPoint[1], firstBottomPoint[2]];
+            }
+            areaPath = topPath.concat(bottomPath);
+            // TODO: don't set leftCliff and rightCliff when connectNulls?
+            graphPath = getGraphPath.call(
+              this,
+              graphPoints,
+              false,
+              connectNulls
+            );
+            areaPath.xMap = topPath.xMap;
+            this.areaPath = areaPath;
+            return graphPath;
+          },
+          /**
+           * Draw the graph and the underlying area. This method calls the Series
+           * base function and adds the area. The areaPath is calculated in the
+           * getSegmentPath method called from Series.prototype.drawGraph.
+           * @private
+           */
+          drawGraph: function () {
+            // Define or reset areaPath
+            this.areaPath = [];
+            // Call the base method
+            Series.prototype.drawGraph.apply(this);
+            // Define local variables
+            var series = this,
+              areaPath = this.areaPath,
+              options = this.options,
+              zones = this.zones,
+              props = [
+                ["area", "highcharts-area", this.color, options.fillColor],
+              ]; // area name, main color, fill color
+            zones.forEach(function (zone, i) {
+              props.push([
+                "zone-area-" + i,
+                "highcharts-area highcharts-zone-area-" +
+                  i +
+                  " " +
+                  zone.className,
+                zone.color || series.color,
+                zone.fillColor || options.fillColor,
+              ]);
+            });
+            props.forEach(function (prop) {
+              var areaKey = prop[0],
+                area = series[areaKey],
+                verb = area ? "animate" : "attr",
+                attribs = {};
+              // Create or update the area
+              if (area) {
+                // update
+                area.endX = series.preventGraphAnimation ? null : areaPath.xMap;
+                area.animate({ d: areaPath });
+              } else {
+                // create
+                attribs.zIndex = 0; // #1069
+                area = series[areaKey] = series.chart.renderer
+                  .path(areaPath)
+                  .addClass(prop[1])
+                  .add(series.group);
+                area.isArea = true;
+              }
+              if (!series.chart.styledMode) {
+                attribs.fill = pick(
+                  prop[3],
+                  color(prop[2])
+                    .setOpacity(pick(options.fillOpacity, 0.75))
+                    .get()
+                );
+              }
+              area[verb](attribs);
+              area.startX = areaPath.xMap;
+              area.shiftUnit = options.step ? 2 : 1;
+            });
+          },
+          drawLegendSymbol: LegendSymbolMixin.drawRectangle,
+        }
+      );
+      /* eslint-enable valid-jsdoc */
+      /**
+       * A `area` series. If the [type](#series.area.type) option is not
+       * specified, it is inherited from [chart.type](#chart.type).
+       *
+       * @extends   series,plotOptions.area
+       * @excluding dataParser, dataURL, useOhlcData
+       * @product   highcharts highstock
+       * @apioption series.area
+       */
+      /**
+       * @see [fillColor](#series.area.fillColor)
+       * @see [fillOpacity](#series.area.fillOpacity)
+       *
+       * @apioption series.area.color
+       */
+      /**
+       * An array of data points for the series. For the `area` series type,
+       * points can be given in the following ways:
+       *
+       * 1. An array of numerical values. In this case, the numerical values will be
+       *    interpreted as `y` options. The `x` values will be automatically
+       *    calculated, either starting at 0 and incremented by 1, or from
+       *    `pointStart` * and `pointInterval` given in the series options. If the
+       *    axis has categories, these will be used. Example:
+       *    ```js
+       *    data: [0, 5, 3, 5]
+       *    ```
+       *
+       * 2. An array of arrays with 2 values. In this case, the values correspond to
+       *    `x,y`. If the first value is a string, it is applied as the name of the
+       *    point, and the `x` value is inferred.
+       *    ```js
+       *    data: [
+       *        [0, 9],
+       *        [1, 7],
+       *        [2, 6]
+       *    ]
+       *    ```
+       *
+       * 3. An array of objects with named values. The following snippet shows only a
+       *    few settings, see the complete options set below. If the total number of
+       *    data points exceeds the series'
+       *    [turboThreshold](#series.area.turboThreshold), this option is not
+       *    available.
+       *    ```js
+       *    data: [{
+       *        x: 1,
+       *        y: 9,
+       *        name: "Point2",
+       *        color: "#00FF00"
+       *    }, {
+       *        x: 1,
+       *        y: 6,
+       *        name: "Point1",
+       *        color: "#FF00FF"
+       *    }]
+       *    ```
+       *
+       * @sample {highcharts} highcharts/chart/reflow-true/
+       *         Numerical values
+       * @sample {highcharts} highcharts/series/data-array-of-arrays/
+       *         Arrays of numeric x and y
+       * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
+       *         Arrays of datetime x and y
+       * @sample {highcharts} highcharts/series/data-array-of-name-value/
+       *         Arrays of point.name and y
+       * @sample {highcharts} highcharts/series/data-array-of-objects/
+       *         Config objects
+       *
+       * @type      {Array<number|Array<(number|string),(number|null)>|null|*>}
+       * @extends   series.line.data
+       * @product   highcharts highstock
+       * @apioption series.area.data
+       */
+      /**
+       * @see [color](#series.area.color)
+       * @see [fillOpacity](#series.area.fillOpacity)
+       *
+       * @apioption series.area.fillColor
+       */
+      /**
+       * @see [color](#series.area.color)
+       * @see [fillColor](#series.area.fillColor)
+       *
+       * @default   {highcharts} 0.75
+       * @default   {highstock} 0.75
+       * @apioption series.area.fillOpacity
+       */
+      (""); // adds doclets above to transpilat
+    }
+  );
+  _registerModule(
+    _modules,
+    "Series/SplineSeries.js",
+    [_modules["Core/Series/Series.js"], _modules["Core/Utilities.js"]],
+    function (BaseSeries, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      var pick = U.pick;
+      /**
+       * Spline series type.
+       *
+       * @private
+       * @class
+       * @name Highcharts.seriesTypes.spline
+       *
+       * @augments Highcarts.Series
+       */
+      BaseSeries.seriesType(
+        "spline",
+        "line",
+        /**
+         * A spline series is a special type of line series, where the segments
+         * between the data points are smoothed.
          *
-         * @param {Highcharts.Point} this
-         *        Point where the event occured.
+         * @sample {highcharts} highcharts/demo/spline-irregular-time/
+         *         Spline chart
+         * @sample {highstock} stock/demo/spline/
+         *         Spline chart
          *
-         * @param {Highcharts.PointInteractionEventObject} event
-         *        Event that occured.
+         * @extends      plotOptions.series
+         * @excluding    step, boostThreshold, boostBlending
+         * @product      highcharts highstock
+         * @optionparent plotOptions.spline
          */
-        ''; // detach doclets above
-        /* eslint-disable valid-jsdoc */
+        {},
         /**
-         * TrackerMixin for points and graphs.
-         *
-         * @private
-         * @mixin Highcharts.TrackerMixin
+         * @lends seriesTypes.spline.prototype
          */
-        var TrackerMixin = H.TrackerMixin = {
-                /**
-                 * Draw the tracker for a point.
-                 *
-                 * @private
-                 * @function Highcharts.TrackerMixin.drawTrackerPoint
-                 * @param {Highcharts.Series} this
-                 * @fires Highcharts.Series#event:afterDrawTracker
-                 */
-                drawTrackerPoint: function () {
-                    var series = this,
-            chart = series.chart,
-            pointer = chart.pointer,
-            onMouseOver = function (e) {
-                        var point = pointer.getPointFromEvent(e);
-                    // undefined on graph in scatterchart
-                    if (typeof point !== 'undefined') {
-                        pointer.isDirectTouch = true;
-                        point.onMouseOver(e);
-                    }
-                }, dataLabels;
-                // Add reference to the point
-                series.points.forEach(function (point) {
-                    dataLabels = (isArray(point.dataLabels) ?
-                        point.dataLabels :
-                        (point.dataLabel ? [point.dataLabel] : []));
-                    if (point.graphic) {
-                        point.graphic.element.point = point;
-                    }
-                    dataLabels.forEach(function (dataLabel) {
-                        if (dataLabel.div) {
-                            dataLabel.div.point = point;
-                        }
-                        else {
-                            dataLabel.element.point = point;
-                        }
-                    });
-                });
-                // Add the event listeners, we need to do this only once
-                if (!series._hasTracking) {
-                    series.trackerGroups.forEach(function (key) {
-                        if (series[key]) {
-                            // we don't always have dataLabelsGroup
-                            series[key]
-                                .addClass('highcharts-tracker')
-                                .on('mouseover', onMouseOver)
-                                .on('mouseout', function (e) {
-                                pointer.onTrackerMouseOut(e);
-                            });
-                            if (hasTouch) {
-                                series[key].on('touchstart', onMouseOver);
-                            }
-                            if (!chart.styledMode && series.options.cursor) {
-                                series[key]
-                                    .css(css)
-                                    .css({ cursor: series.options.cursor });
-                            }
-                        }
-                    });
-                    series._hasTracking = true;
-                }
-                fireEvent(this, 'afterDrawTracker');
-            },
-            /**
-             * Draw the tracker object that sits above all data labels and markers to
-             * track mouse events on the graph or points. For the line type charts
-             * the tracker uses the same graphPath, but with a greater stroke width
-             * for better control.
-             *
-             * @private
-             * @function Highcharts.TrackerMixin.drawTrackerGraph
-             * @param {Highcharts.Series} this
-             * @fires Highcharts.Series#event:afterDrawTracker
-             */
-            drawTrackerGraph: function () {
-                var series = this,
-                    options = series.options,
-                    trackByArea = options.trackByArea,
-                    trackerPath = [].concat(trackByArea ?
-                        series.areaPath :
-                        series.graphPath), 
-                    // trackerPathLength = trackerPath.length,
-                    chart = series.chart,
-                    pointer = chart.pointer,
-                    renderer = chart.renderer,
-                    snap = chart.options.tooltip.snap,
-                    tracker = series.tracker,
-                    i,
-                    onMouseOver = function (e) {
-                        if (chart.hoverSeries !== series) {
-                            series.onMouseOver();
-                    }
-                }, 
-                /*
-                 * Empirical lowest possible opacities for TRACKER_FILL for an
-                 * element to stay invisible but clickable
-                 * IE6: 0.002
-                 * IE7: 0.002
-                 * IE8: 0.002
-                 * IE9: 0.00000000001 (unlimited)
-                 * IE10: 0.0001 (exporting only)
-                 * FF: 0.00000000001 (unlimited)
-                 * Chrome: 0.000001
-                 * Safari: 0.000001
-                 * Opera: 0.00000000001 (unlimited)
-                 */
-                TRACKER_FILL = 'rgba(192,192,192,' + (svg ? 0.0001 : 0.002) + ')';
-                // Draw the tracker
-                if (tracker) {
-                    tracker.attr({ d: trackerPath });
-                }
-                else if (series.graph) { // create
-                    series.tracker = renderer.path(trackerPath)
-                        .attr({
-                        visibility: series.visible ? 'visible' : 'hidden',
-                        zIndex: 2
+        {
+          /* eslint-disable valid-jsdoc */
+          /**
+           * Get the spline segment from a given point's previous neighbour to the
+           * given point.
+           *
+           * @private
+           * @function Highcharts.seriesTypes.spline#getPointSpline
+           *
+           * @param {Array<Highcharts.Point>}
+           *
+           * @param {Highcharts.Point} point
+           *
+           * @param {number} i
+           *
+           * @return {Highcharts.SVGPathArray}
+           */
+          getPointSpline: function (points, point, i) {
+            var // 1 means control points midway between points, 2 means 1/3
+              // from the point, 3 is 1/4 etc
+              smoothing = 1.5,
+              denom = smoothing + 1,
+              plotX = point.plotX || 0,
+              plotY = point.plotY || 0,
+              lastPoint = points[i - 1],
+              nextPoint = points[i + 1],
+              leftContX,
+              leftContY,
+              rightContX,
+              rightContY,
+              ret;
+            /**
+             * @private
+             */
+            function doCurve(otherPoint) {
+              return (
+                otherPoint &&
+                !otherPoint.isNull &&
+                otherPoint.doCurve !== false &&
+                // #6387, area splines next to null:
+                !point.isCliff
+              );
+            }
+            // Find control points
+            if (doCurve(lastPoint) && doCurve(nextPoint)) {
+              var lastX = lastPoint.plotX || 0,
+                lastY = lastPoint.plotY || 0,
+                nextX = nextPoint.plotX || 0,
+                nextY = nextPoint.plotY || 0,
+                correction = 0;
+              leftContX = (smoothing * plotX + lastX) / denom;
+              leftContY = (smoothing * plotY + lastY) / denom;
+              rightContX = (smoothing * plotX + nextX) / denom;
+              rightContY = (smoothing * plotY + nextY) / denom;
+              // Have the two control points make a straight line through main
+              // point
+              if (rightContX !== leftContX) {
+                // #5016, division by zero
+                correction =
+                  ((rightContY - leftContY) * (rightContX - plotX)) /
+                    (rightContX - leftContX) +
+                  plotY -
+                  rightContY;
+              }
+              leftContY += correction;
+              rightContY += correction;
+              // to prevent false extremes, check that control points are
+              // between neighbouring points' y values
+              if (leftContY > lastY && leftContY > plotY) {
+                leftContY = Math.max(lastY, plotY);
+                // mirror of left control point
+                rightContY = 2 * plotY - leftContY;
+              } else if (leftContY < lastY && leftContY < plotY) {
+                leftContY = Math.min(lastY, plotY);
+                rightContY = 2 * plotY - leftContY;
+              }
+              if (rightContY > nextY && rightContY > plotY) {
+                rightContY = Math.max(nextY, plotY);
+                leftContY = 2 * plotY - rightContY;
+              } else if (rightContY < nextY && rightContY < plotY) {
+                rightContY = Math.min(nextY, plotY);
+                leftContY = 2 * plotY - rightContY;
+              }
+              // record for drawing in next point
+              point.rightContX = rightContX;
+              point.rightContY = rightContY;
+            }
+            // Visualize control points for debugging
+            /*
+            if (leftContX) {
+                this.chart.renderer.circle(
+                        leftContX + this.chart.plotLeft,
+                        leftContY + this.chart.plotTop,
+                        2
+                    )
+                    .attr({
+                        stroke: 'red',
+                        'stroke-width': 2,
+                        fill: 'none',
+                        zIndex: 9
                     })
-                        .addClass(trackByArea ?
-                        'highcharts-tracker-area' :
-                        'highcharts-tracker-line')
-                        .add(series.group);
-                    if (!chart.styledMode) {
-                        series.tracker.attr({
-                            'stroke-linecap': 'round',
-                            'stroke-linejoin': 'round',
-                            stroke: TRACKER_FILL,
-                            fill: trackByArea ? TRACKER_FILL : 'none',
-                            'stroke-width': series.graph.strokeWidth() +
-                                (trackByArea ? 0 : 2 * snap)
-                        });
-                    }
-                    // The tracker is added to the series group, which is clipped, but
-                    // is covered by the marker group. So the marker group also needs to
-                    // capture events.
-                    [series.tracker, series.markerGroup].forEach(function (tracker) {
-                        tracker.addClass('highcharts-tracker')
-                            .on('mouseover', onMouseOver)
-                            .on('mouseout', function (e) {
-                            pointer.onTrackerMouseOut(e);
-                        });
-                        if (options.cursor && !chart.styledMode) {
-                            tracker.css({ cursor: options.cursor });
-                        }
-                        if (hasTouch) {
-                            tracker.on('touchstart', onMouseOver);
-                        }
-                    });
-                }
-                fireEvent(this, 'afterDrawTracker');
+                    .add();
+                this.chart.renderer.path(['M', leftContX + this.chart.plotLeft,
+                    leftContY + this.chart.plotTop,
+                    'L', plotX + this.chart.plotLeft, plotY + this.chart.plotTop])
+                    .attr({
+                        stroke: 'red',
+                        'stroke-width': 2,
+                        zIndex: 9
+                    })
+                    .add();
             }
-        };
-        /* End TrackerMixin */
-        // Add tracking event listener to the series group, so the point graphics
-        // themselves act as trackers
-        if (seriesTypes.column) {
-            /**
-             * @private
-             * @borrows Highcharts.TrackerMixin.drawTrackerPoint as Highcharts.seriesTypes.column#drawTracker
-             */
-            seriesTypes.column.prototype.drawTracker = TrackerMixin.drawTrackerPoint;
-        }
-        if (seriesTypes.pie) {
-            /**
-             * @private
-             * @borrows Highcharts.TrackerMixin.drawTrackerPoint as Highcharts.seriesTypes.pie#drawTracker
-             */
-            seriesTypes.pie.prototype.drawTracker = TrackerMixin.drawTrackerPoint;
-        }
-        if (seriesTypes.scatter) {
-            /**
-             * @private
-             * @borrows Highcharts.TrackerMixin.drawTrackerPoint as Highcharts.seriesTypes.scatter#drawTracker
-             */
-            seriesTypes.scatter.prototype.drawTracker = TrackerMixin.drawTrackerPoint;
-        }
-        // Extend Legend for item events.
-        extend(Legend.prototype, {
-            /**
-             * @private
-             * @function Highcharts.Legend#setItemEvents
-             * @param {Highcharts.BubbleLegend|Point|Highcharts.Series} item
-             * @param {Highcharts.SVGElement} legendItem
-             * @param {boolean} [useHTML=false]
-             * @fires Highcharts.Point#event:legendItemClick
-             * @fires Highcharts.Series#event:legendItemClick
-             */
-            setItemEvents: function (item, legendItem, useHTML) {
-                var legend = this,
-                    boxWrapper = legend.chart.renderer.boxWrapper,
-                    isPoint = item instanceof Point,
-                    activeClass = 'highcharts-legend-' +
-                        (isPoint ? 'point' : 'series') + '-active',
-                    styledMode = legend.chart.styledMode, 
-                    // When `useHTML`, the symbol is rendered in other group, so
-                    // we need to apply events listeners to both places
-                    legendItems = useHTML ?
-                        [legendItem,
-                    item.legendSymbol] :
-                        [item.legendGroup];
-                // Set the events on the item group, or in case of useHTML, the item
-                // itself (#1249)
-                legendItems.forEach(function (element) {
-                    if (element) {
-                        element
-                            .on('mouseover', function () {
-                            if (item.visible) {
-                                legend.allItems.forEach(function (inactiveItem) {
-                                    if (item !== inactiveItem) {
-                                        inactiveItem.setState('inactive', !isPoint);
-                                    }
-                                });
-                            }
-                            item.setState('hover');
-                            // A CSS class to dim or hide other than the hovered
-                            // series.
-                            // Works only if hovered series is visible (#10071).
-                            if (item.visible) {
-                                boxWrapper.addClass(activeClass);
-                            }
-                            if (!styledMode) {
-                                legendItem.css(legend.options.itemHoverStyle);
-                            }
-                        })
-                            .on('mouseout', function () {
-                            if (!legend.chart.styledMode) {
-                                legendItem.css(merge(item.visible ?
-                                    legend.itemStyle :
-                                    legend.itemHiddenStyle));
-                            }
-                            legend.allItems.forEach(function (inactiveItem) {
-                                if (item !== inactiveItem) {
-                                    inactiveItem.setState('', !isPoint);
-                                }
-                            });
-                            // A CSS class to dim or hide other than the hovered
-                            // series.
-                            boxWrapper.removeClass(activeClass);
-                            item.setState();
-                        })
-                            .on('click', function (event) {
-                            var strLegendItemClick = 'legendItemClick',
-                                fnLegendItemClick = function () {
-                                    if (item.setVisible) {
-                                        item.setVisible();
-                                }
-                                // Reset inactive state
-                                legend.allItems.forEach(function (inactiveItem) {
-                                    if (item !== inactiveItem) {
-                                        inactiveItem.setState(item.visible ? 'inactive' : '', !isPoint);
-                                    }
-                                });
-                            };
-                            // A CSS class to dim or hide other than the hovered
-                            // series. Event handling in iOS causes the activeClass
-                            // to be added prior to click in some cases (#7418).
-                            boxWrapper.removeClass(activeClass);
-                            // Pass over the click/touch event. #4.
-                            event = {
-                                browserEvent: event
-                            };
-                            // click the name or symbol
-                            if (item.firePointEvent) { // point
-                                item.firePointEvent(strLegendItemClick, event, fnLegendItemClick);
-                            }
-                            else {
-                                fireEvent(item, strLegendItemClick, event, fnLegendItemClick);
-                            }
-                        });
-                    }
-                });
-            },
-            /**
-             * @private
-             * @function Highcharts.Legend#createCheckboxForItem
-             * @param {Highcharts.BubbleLegend|Point|Highcharts.Series} item
-             * @fires Highcharts.Series#event:checkboxClick
-             */
-            createCheckboxForItem: function (item) {
-                var legend = this;
-                item.checkbox = createElement('input', {
-                    type: 'checkbox',
-                    className: 'highcharts-legend-checkbox',
-                    checked: item.selected,
-                    defaultChecked: item.selected // required by IE7
-                }, legend.options.itemCheckboxStyle, legend.chart.container);
-                addEvent(item.checkbox, 'click', function (event) {
-                    var target = event.target;
-                    fireEvent(item.series || item, 'checkboxClick', {
-                        checked: target.checked,
-                        item: item
-                    }, function () {
-                        item.select();
-                    });
-                });
+            if (rightContX) {
+                this.chart.renderer.circle(
+                        rightContX + this.chart.plotLeft,
+                        rightContY + this.chart.plotTop,
+                        2
+                    )
+                    .attr({
+                        stroke: 'green',
+                        'stroke-width': 2,
+                        fill: 'none',
+                        zIndex: 9
+                    })
+                    .add();
+                this.chart.renderer.path(['M', rightContX + this.chart.plotLeft,
+                    rightContY + this.chart.plotTop,
+                    'L', plotX + this.chart.plotLeft, plotY + this.chart.plotTop])
+                    .attr({
+                        stroke: 'green',
+                        'stroke-width': 2,
+                        zIndex: 9
+                    })
+                    .add();
             }
-        });
-        // Extend the Chart object with interaction
-        extend(Chart.prototype, /** @lends Chart.prototype */ {
-            /**
-             * Display the zoom button, so users can reset zoom to the default view
-             * settings.
-             *
-             * @function Highcharts.Chart#showResetZoom
-             *
-             * @fires Highcharts.Chart#event:afterShowResetZoom
-             * @fires Highcharts.Chart#event:beforeShowResetZoom
+                // */
+            ret = [
+              "C",
+              pick(lastPoint.rightContX, lastPoint.plotX, 0),
+              pick(lastPoint.rightContY, lastPoint.plotY, 0),
+              pick(leftContX, plotX, 0),
+              pick(leftContY, plotY, 0),
+              plotX,
+              plotY,
+            ];
+            // reset for updating series later
+            lastPoint.rightContX = lastPoint.rightContY = void 0;
+            return ret;
+          },
+          /* eslint-enable valid-jsdoc */
+        }
+      );
+      /**
+       * A `spline` series. If the [type](#series.spline.type) option is
+       * not specified, it is inherited from [chart.type](#chart.type).
+       *
+       * @extends   series,plotOptions.spline
+       * @excluding dataParser, dataURL, step, boostThreshold, boostBlending
+       * @product   highcharts highstock
+       * @apioption series.spline
+       */
+      /**
+       * An array of data points for the series. For the `spline` series type,
+       * points can be given in the following ways:
+       *
+       * 1. An array of numerical values. In this case, the numerical values will be
+       *    interpreted as `y` options. The `x` values will be automatically
+       *    calculated, either starting at 0 and incremented by 1, or from
+       *    `pointStart` and `pointInterval` given in the series options. If the axis
+       *    has categories, these will be used. Example:
+       *    ```js
+       *    data: [0, 5, 3, 5]
+       *    ```
+       *
+       * 2. An array of arrays with 2 values. In this case, the values correspond to
+       *    `x,y`. If the first value is a string, it is applied as the name of the
+       *    point, and the `x` value is inferred.
+       *    ```js
+       *    data: [
+       *        [0, 9],
+       *        [1, 2],
+       *        [2, 8]
+       *    ]
+       *    ```
+       *
+       * 3. An array of objects with named values. The following snippet shows only a
+       *    few settings, see the complete options set below. If the total number of
+       *    data points exceeds the series'
+       *    [turboThreshold](#series.spline.turboThreshold),
+       *    this option is not available.
+       *    ```js
+       *    data: [{
+       *        x: 1,
+       *        y: 9,
+       *        name: "Point2",
+       *        color: "#00FF00"
+       *    }, {
+       *        x: 1,
+       *        y: 0,
+       *        name: "Point1",
+       *        color: "#FF00FF"
+       *    }]
+       *    ```
+       *
+       * @sample {highcharts} highcharts/chart/reflow-true/
+       *         Numerical values
+       * @sample {highcharts} highcharts/series/data-array-of-arrays/
+       *         Arrays of numeric x and y
+       * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
+       *         Arrays of datetime x and y
+       * @sample {highcharts} highcharts/series/data-array-of-name-value/
+       *         Arrays of point.name and y
+       * @sample {highcharts} highcharts/series/data-array-of-objects/
+       *         Config objects
+       *
+       * @type      {Array<number|Array<(number|string),(number|null)>|null|*>}
+       * @extends   series.line.data
+       * @product   highcharts highstock
+       * @apioption series.spline.data
+       */
+      (""); // adds doclets above intro transpilat
+    }
+  );
+  _registerModule(
+    _modules,
+    "Series/AreaSplineSeries.js",
+    [
+      _modules["Core/Series/Series.js"],
+      _modules["Mixins/LegendSymbol.js"],
+      _modules["Core/Options.js"],
+    ],
+    function (BaseSeries, LegendSymbolMixin, O) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      var defaultOptions = O.defaultOptions;
+      var areaProto = BaseSeries.seriesTypes.area.prototype;
+      /**
+       * AreaSpline series type.
+       *
+       * @private
+       * @class
+       * @name Highcharts.seriesTypes.areaspline
+       *
+       * @augments Highcharts.Series
+       */
+      BaseSeries.seriesType(
+        "areaspline",
+        "spline",
+        /**
+         * The area spline series is an area series where the graph between the
+         * points is smoothed into a spline.
+         *
+         * @sample {highcharts} highcharts/demo/areaspline/
+         *         Area spline chart
+         * @sample {highstock} stock/demo/areaspline/
+         *         Area spline chart
+         *
+         * @extends   plotOptions.area
+         * @excluding step, boostThreshold, boostBlending
+         * @product   highcharts highstock
+         * @apioption plotOptions.areaspline
+         */
+        /**
+         * @see [fillColor](#plotOptions.areaspline.fillColor)
+         * @see [fillOpacity](#plotOptions.areaspline.fillOpacity)
+         *
+         * @apioption plotOptions.areaspline.color
+         */
+        /**
+         * @see [color](#plotOptions.areaspline.color)
+         * @see [fillOpacity](#plotOptions.areaspline.fillOpacity)
+         *
+         * @apioption plotOptions.areaspline.fillColor
+         */
+        /**
+         * @see [color](#plotOptions.areaspline.color)
+         * @see [fillColor](#plotOptions.areaspline.fillColor)
+         *
+         * @default   {highcharts} 0.75
+         * @default   {highstock} 0.75
+         * @apioption plotOptions.areaspline.fillOpacity
+         */
+        defaultOptions.plotOptions.area,
+        {
+          getStackPoints: areaProto.getStackPoints,
+          getGraphPath: areaProto.getGraphPath,
+          drawGraph: areaProto.drawGraph,
+          drawLegendSymbol: LegendSymbolMixin.drawRectangle,
+        }
+      );
+      /**
+       * A `areaspline` series. If the [type](#series.areaspline.type) option
+       * is not specified, it is inherited from [chart.type](#chart.type).
+       *
+       *
+       * @extends   series,plotOptions.areaspline
+       * @excluding dataParser, dataURL, step, boostThreshold, boostBlending
+       * @product   highcharts highstock
+       * @apioption series.areaspline
+       */
+      /**
+       * @see [fillColor](#series.areaspline.fillColor)
+       * @see [fillOpacity](#series.areaspline.fillOpacity)
+       *
+       * @apioption series.areaspline.color
+       */
+      /**
+       * An array of data points for the series. For the `areaspline` series
+       * type, points can be given in the following ways:
+       *
+       * 1. An array of numerical values. In this case, the numerical values will be
+       *    interpreted as `y` options. The `x` values will be automatically
+       *    calculated, either starting at 0 and incremented by 1, or from
+       *    `pointStart` and `pointInterval` given in the series options. If the axis
+       *    has categories, these will be used. Example:
+       *    ```js
+       *    data: [0, 5, 3, 5]
+       *    ```
+       *
+       * 2. An array of arrays with 2 values. In this case, the values correspond to
+       *    `x,y`. If the first value is a string, it is applied as the name of the
+       *    point, and the `x` value is inferred.
+       *    ```js
+       *    data: [
+       *        [0, 10],
+       *        [1, 9],
+       *        [2, 3]
+       *    ]
+       *    ```
+       *
+       * 3. An array of objects with named values. The following snippet shows only a
+       *    few settings, see the complete options set below. If the total number of
+       *    data points exceeds the series'
+       *    [turboThreshold](#series.areaspline.turboThreshold), this option is not
+       *    available.
+       *    ```js
+       *    data: [{
+       *        x: 1,
+       *        y: 4,
+       *        name: "Point2",
+       *        color: "#00FF00"
+       *    }, {
+       *        x: 1,
+       *        y: 4,
+       *        name: "Point1",
+       *        color: "#FF00FF"
+       *    }]
+       *    ```
+       *
+       * @sample {highcharts} highcharts/chart/reflow-true/
+       *         Numerical values
+       * @sample {highcharts} highcharts/series/data-array-of-arrays/
+       *         Arrays of numeric x and y
+       * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
+       *         Arrays of datetime x and y
+       * @sample {highcharts} highcharts/series/data-array-of-name-value/
+       *         Arrays of point.name and y
+       * @sample {highcharts} highcharts/series/data-array-of-objects/
+       *         Config objects
+       *
+       * @type      {Array<number|Array<(number|string),(number|null)>|null|*>}
+       * @extends   series.line.data
+       * @product   highcharts highstock
+       * @apioption series.areaspline.data
+       */
+      /**
+       * @see [color](#series.areaspline.color)
+       * @see [fillOpacity](#series.areaspline.fillOpacity)
+       *
+       * @apioption series.areaspline.fillColor
+       */
+      /**
+       * @see [color](#series.areaspline.color)
+       * @see [fillColor](#series.areaspline.fillColor)
+       *
+       * @default   {highcharts} 0.75
+       * @default   {highstock} 0.75
+       * @apioption series.areaspline.fillOpacity
+       */
+      (""); // adds doclets above into transpilat
+    }
+  );
+  _registerModule(
+    _modules,
+    "Series/ColumnSeries.js",
+    [
+      _modules["Core/Animation/AnimationUtilities.js"],
+      _modules["Core/Series/Series.js"],
+      _modules["Core/Color/Color.js"],
+      _modules["Core/Globals.js"],
+      _modules["Mixins/LegendSymbol.js"],
+      _modules["Series/LineSeries.js"],
+      _modules["Core/Utilities.js"],
+    ],
+    function (A, BaseSeries, Color, H, LegendSymbolMixin, LineSeries, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      var animObject = A.animObject;
+      var color = Color.parse;
+      var noop = H.noop;
+      var clamp = U.clamp,
+        defined = U.defined,
+        extend = U.extend,
+        isArray = U.isArray,
+        isNumber = U.isNumber,
+        merge = U.merge,
+        pick = U.pick,
+        objectEach = U.objectEach;
+      /**
+       * Adjusted width and x offset of the columns for grouping.
+       *
+       * @private
+       * @interface Highcharts.ColumnMetricsObject
+       */ /**
+       * Width of the columns.
+       * @name Highcharts.ColumnMetricsObject#width
+       * @type {number}
+       */ /**
+       * Offset of the columns.
+       * @name Highcharts.ColumnMetricsObject#offset
+       * @type {number}
+       */
+      (""); // detach doclets above
+      /**
+       * The column series type.
+       *
+       * @private
+       * @class
+       * @name Highcharts.seriesTypes.column
+       *
+       * @augments Highcharts.Series
+       */
+      var ColumnSeries = BaseSeries.seriesType(
+        "column",
+        "line",
+        /**
+         * Column series display one column per value along an X axis.
+         *
+         * @sample {highcharts} highcharts/demo/column-basic/
+         *         Column chart
+         * @sample {highstock} stock/demo/column/
+         *         Column chart
+         *
+         * @extends      plotOptions.line
+         * @excluding    connectEnds, connectNulls, gapSize, gapUnit, linecap,
+         *               lineWidth, marker, step, useOhlcData
+         * @product      highcharts highstock
+         * @optionparent plotOptions.column
+         */
+        {
+          /**
+           * The corner radius of the border surrounding each column or bar.
+           *
+           * @sample {highcharts} highcharts/plotoptions/column-borderradius/
+           *         Rounded columns
+           *
+           * @product highcharts highstock gantt
+           *
+           * @private
+           */
+          borderRadius: 0,
+          /**
+           * When using automatic point colors pulled from the global
+           * [colors](colors) or series-specific
+           * [plotOptions.column.colors](series.colors) collections, this option
+           * determines whether the chart should receive one color per series or
+           * one color per point.
+           *
+           * In styled mode, the `colors` or `series.colors` arrays are not
+           * supported, and instead this option gives the points individual color
+           * class names on the form `highcharts-color-{n}`.
+           *
+           * @see [series colors](#plotOptions.column.colors)
+           *
+           * @sample {highcharts} highcharts/plotoptions/column-colorbypoint-false/
+           *         False by default
+           * @sample {highcharts} highcharts/plotoptions/column-colorbypoint-true/
+           *         True
+           *
+           * @type      {boolean}
+           * @default   false
+           * @since     2.0
+           * @product   highcharts highstock gantt
+           * @apioption plotOptions.column.colorByPoint
+           */
+          /**
+           * A series specific or series type specific color set to apply instead
+           * of the global [colors](#colors) when [colorByPoint](
+           * #plotOptions.column.colorByPoint) is true.
+           *
+           * @type      {Array<Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject>}
+           * @since     3.0
+           * @product   highcharts highstock gantt
+           * @apioption plotOptions.column.colors
+           */
+          /**
+           * When `true`, the columns will center in the category, ignoring null
+           * or missing points. When `false`, space will be reserved for null or
+           * missing points.
+           *
+           * @sample {highcharts} highcharts/series-column/centerincategory/
+           *         Center in category
+           *
+           * @since   8.0.1
+           * @product highcharts highstock gantt
+           *
+           * @private
+           */
+          centerInCategory: false,
+          /**
+           * Padding between each value groups, in x axis units.
+           *
+           * @sample {highcharts} highcharts/plotoptions/column-grouppadding-default/
+           *         0.2 by default
+           * @sample {highcharts} highcharts/plotoptions/column-grouppadding-none/
+           *         No group padding - all columns are evenly spaced
+           *
+           * @product highcharts highstock gantt
+           *
+           * @private
+           */
+          groupPadding: 0.2,
+          /**
+           * Whether to group non-stacked columns or to let them render
+           * independent of each other. Non-grouped columns will be laid out
+           * individually and overlap each other.
+           *
+           * @sample {highcharts} highcharts/plotoptions/column-grouping-false/
+           *         Grouping disabled
+           * @sample {highstock} highcharts/plotoptions/column-grouping-false/
+           *         Grouping disabled
+           *
+           * @type      {boolean}
+           * @default   true
+           * @since     2.3.0
+           * @product   highcharts highstock gantt
+           * @apioption plotOptions.column.grouping
+           */
+          /**
+           * @ignore-option
+           * @private
+           */
+          marker: null,
+          /**
+           * The maximum allowed pixel width for a column, translated to the
+           * height of a bar in a bar chart. This prevents the columns from
+           * becoming too wide when there is a small number of points in the
+           * chart.
+           *
+           * @see [pointWidth](#plotOptions.column.pointWidth)
+           *
+           * @sample {highcharts} highcharts/plotoptions/column-maxpointwidth-20/
+           *         Limited to 50
+           * @sample {highstock} highcharts/plotoptions/column-maxpointwidth-20/
+           *         Limited to 50
+           *
+           * @type      {number}
+           * @since     4.1.8
+           * @product   highcharts highstock gantt
+           * @apioption plotOptions.column.maxPointWidth
+           */
+          /**
+           * Padding between each column or bar, in x axis units.
+           *
+           * @sample {highcharts} highcharts/plotoptions/column-pointpadding-default/
+           *         0.1 by default
+           * @sample {highcharts} highcharts/plotoptions/column-pointpadding-025/
+           *          0.25
+           * @sample {highcharts} highcharts/plotoptions/column-pointpadding-none/
+           *         0 for tightly packed columns
+           *
+           * @product highcharts highstock gantt
+           *
+           * @private
+           */
+          pointPadding: 0.1,
+          /**
+           * A pixel value specifying a fixed width for each column or bar point.
+           * When `null`, the width is calculated from the `pointPadding` and
+           * `groupPadding`. The width effects the dimension that is not based on
+           * the point value. For column series it is the hoizontal length and for
+           * bar series it is the vertical length.
+           *
+           * @see [maxPointWidth](#plotOptions.column.maxPointWidth)
+           *
+           * @sample {highcharts} highcharts/plotoptions/column-pointwidth-20/
+           *         20px wide columns regardless of chart width or the amount of
+           *         data points
+           *
+           * @type      {number}
+           * @since     1.2.5
+           * @product   highcharts highstock gantt
+           * @apioption plotOptions.column.pointWidth
+           */
+          /**
+           * A pixel value specifying a fixed width for the column or bar.
+           * Overrides pointWidth on the series.
+           *
+           * @see [series.pointWidth](#plotOptions.column.pointWidth)
+           *
+           * @type      {number}
+           * @default   undefined
+           * @since     7.0.0
+           * @product   highcharts highstock gantt
+           * @apioption series.column.data.pointWidth
+           */
+          /**
+           * The minimal height for a column or width for a bar. By default,
+           * 0 values are not shown. To visualize a 0 (or close to zero) point,
+           * set the minimal point length to a pixel value like 3\. In stacked
+           * column charts, minPointLength might not be respected for tightly
+           * packed values.
+           *
+           * @sample {highcharts} highcharts/plotoptions/column-minpointlength/
+           *         Zero base value
+           * @sample {highcharts} highcharts/plotoptions/column-minpointlength-pos-and-neg/
+           *         Positive and negative close to zero values
+           *
+           * @product highcharts highstock gantt
+           *
+           * @private
+           */
+          minPointLength: 0,
+          /**
+           * When the series contains less points than the crop threshold, all
+           * points are drawn, event if the points fall outside the visible plot
+           * area at the current zoom. The advantage of drawing all points
+           * (including markers and columns), is that animation is performed on
+           * updates. On the other hand, when the series contains more points than
+           * the crop threshold, the series data is cropped to only contain points
+           * that fall within the plot area. The advantage of cropping away
+           * invisible points is to increase performance on large series.
+           *
+           * @product highcharts highstock gantt
+           *
+           * @private
+           */
+          cropThreshold: 50,
+          /**
+           * The X axis range that each point is valid for. This determines the
+           * width of the column. On a categorized axis, the range will be 1
+           * by default (one category unit). On linear and datetime axes, the
+           * range will be computed as the distance between the two closest data
+           * points.
+           *
+           * The default `null` means it is computed automatically, but this
+           * option can be used to override the automatic value.
+           *
+           * This option is set by default to 1 if data sorting is enabled.
+           *
+           * @sample {highcharts} highcharts/plotoptions/column-pointrange/
+           *         Set the point range to one day on a data set with one week
+           *         between the points
+           *
+           * @type    {number|null}
+           * @since   2.3
+           * @product highcharts highstock gantt
+           *
+           * @private
+           */
+          pointRange: null,
+          states: {
+            /**
+             * Options for the hovered point. These settings override the normal
+             * state options when a point is moused over or touched.
+             *
+             * @extends   plotOptions.series.states.hover
+             * @excluding halo, lineWidth, lineWidthPlus, marker
+             * @product   highcharts highstock gantt
              */
-            showResetZoom: function () {
-                var chart = this,
-                    lang = defaultOptions.lang,
-                    btnOptions = chart.options.chart.resetZoomButton,
-                    theme = btnOptions.theme,
-                    states = theme.states,
-                    alignTo = (btnOptions.relativeTo === 'chart' ||
-                        btnOptions.relativeTo === 'spaceBox' ?
-                        null :
-                        'plotBox');
-                /**
-                 * @private
-                 */
-                function zoomOut() {
-                    chart.zoomOut();
-                }
-                fireEvent(this, 'beforeShowResetZoom', null, function () {
-                    chart.resetZoomButton = chart.renderer
-                        .button(lang.resetZoom, null, null, zoomOut, theme, states && states.hover)
-                        .attr({
-                        align: btnOptions.position.align,
-                        title: lang.resetZoomTitle
-                    })
-                        .addClass('highcharts-reset-zoom')
-                        .add()
-                        .align(btnOptions.position, false, alignTo);
-                });
-                fireEvent(this, 'afterShowResetZoom');
+            hover: {
+              /** @ignore-option */
+              halo: false,
+              /**
+               * A specific border color for the hovered point. Defaults to
+               * inherit the normal state border color.
+               *
+               * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+               * @product   highcharts gantt
+               * @apioption plotOptions.column.states.hover.borderColor
+               */
+              /**
+               * A specific color for the hovered point.
+               *
+               * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+               * @product   highcharts gantt
+               * @apioption plotOptions.column.states.hover.color
+               */
+              /**
+               * How much to brighten the point on interaction. Requires the
+               * main color to be defined in hex or rgb(a) format.
+               *
+               * In styled mode, the hover brightening is by default replaced
+               * with a fill-opacity set in the `.highcharts-point:hover`
+               * rule.
+               *
+               * @sample {highcharts} highcharts/plotoptions/column-states-hover-brightness/
+               *         Brighten by 0.5
+               *
+               * @product highcharts highstock gantt
+               */
+              brightness: 0.1,
             },
             /**
-             * Zoom the chart out after a user has zoomed in. See also
-             * [Axis.setExtremes](/class-reference/Highcharts.Axis#setExtremes).
-             *
-             * @function Highcharts.Chart#zoomOut
+             * Options for the selected point. These settings override the
+             * normal state options when a point is selected.
              *
-             * @fires Highcharts.Chart#event:selection
+             * @extends   plotOptions.series.states.select
+             * @excluding halo, lineWidth, lineWidthPlus, marker
+             * @product   highcharts highstock gantt
              */
-            zoomOut: function () {
-                fireEvent(this, 'selection', { resetSelection: true }, this.zoom);
+            select: {
+              /**
+               * A specific color for the selected point.
+               *
+               * @type    {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+               * @default #cccccc
+               * @product highcharts highstock gantt
+               */
+              color: "#cccccc",
+              /**
+               * A specific border color for the selected point.
+               *
+               * @type    {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+               * @default #000000
+               * @product highcharts highstock gantt
+               */
+              borderColor: "#000000",
             },
+          },
+          dataLabels: {
+            align: void 0,
+            verticalAlign: void 0,
             /**
-             * Zoom into a given portion of the chart given by axis coordinates.
+             * The y position offset of the label relative to the point in
+             * pixels.
              *
-             * @private
-             * @function Highcharts.Chart#zoom
-             * @param {Highcharts.SelectEventObject} event
-             */
-            zoom: function (event) {
-                var chart = this,
-                    hasZoomed,
-                    pointer = chart.pointer,
-                    displayButton = false,
-                    mouseDownPos = chart.inverted ? pointer.mouseDownX : pointer.mouseDownY,
-                    resetZoomButton;
-                // If zoom is called with no arguments, reset the axes
-                if (!event || event.resetSelection) {
-                    chart.axes.forEach(function (axis) {
-                        hasZoomed = axis.zoom();
-                    });
-                    pointer.initiated = false; // #6804
-                }
-                else { // else, zoom in on all axes
-                    event.xAxis.concat(event.yAxis).forEach(function (axisData) {
-                        var axis = axisData.axis,
-                            axisStartPos = chart.inverted ? axis.left : axis.top,
-                            axisEndPos = chart.inverted ?
-                                axisStartPos + axis.width : axisStartPos + axis.height,
-                            isXAxis = axis.isXAxis,
-                            isWithinPane = false;
-                        // Check if zoomed area is within the pane (#1289).
-                        // In case of multiple panes only one pane should be zoomed.
-                        if ((!isXAxis &&
-                            mouseDownPos >= axisStartPos &&
-                            mouseDownPos <= axisEndPos) ||
-                            isXAxis ||
-                            !defined(mouseDownPos)) {
-                            isWithinPane = true;
-                        }
-                        // don't zoom more than minRange
-                        if (pointer[isXAxis ? 'zoomX' : 'zoomY'] && isWithinPane) {
-                            hasZoomed = axis.zoom(axisData.min, axisData.max);
-                            if (axis.displayBtn) {
-                                displayButton = true;
-                            }
-                        }
+             * @type {number}
+             */
+            y: void 0,
+          },
+          // false doesn't work well: https://jsfiddle.net/highcharts/hz8fopan/14/
+          /**
+           * @ignore-option
+           * @private
+           */
+          startFromThreshold: true,
+          stickyTracking: false,
+          tooltip: {
+            distance: 6,
+          },
+          /**
+           * The Y axis value to serve as the base for the columns, for
+           * distinguishing between values above and below a threshold. If `null`,
+           * the columns extend from the padding Y axis minimum.
+           *
+           * @type    {number|null}
+           * @since   2.0
+           * @product highcharts
+           *
+           * @private
+           */
+          threshold: 0,
+          /**
+           * The width of the border surrounding each column or bar. Defaults to
+           * `1` when there is room for a border, but to `0` when the columns are
+           * so dense that a border would cover the next column.
+           *
+           * In styled mode, the stroke width can be set with the
+           * `.highcharts-point` rule.
+           *
+           * @sample {highcharts} highcharts/plotoptions/column-borderwidth/
+           *         2px black border
+           *
+           * @type      {number}
+           * @default   undefined
+           * @product   highcharts highstock gantt
+           * @apioption plotOptions.column.borderWidth
+           */
+          /**
+           * The color of the border surrounding each column or bar.
+           *
+           * In styled mode, the border stroke can be set with the
+           * `.highcharts-point` rule.
+           *
+           * @sample {highcharts} highcharts/plotoptions/column-bordercolor/
+           *         Dark gray border
+           *
+           * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+           * @default   #ffffff
+           * @product   highcharts highstock gantt
+           *
+           * @private
+           */
+          borderColor: "#ffffff",
+        },
+        /**
+         * @lends seriesTypes.column.prototype
+         */
+        {
+          cropShoulder: 0,
+          // When tooltip is not shared, this series (and derivatives) requires
+          // direct touch/hover. KD-tree does not apply.
+          directTouch: true,
+          trackerGroups: ["group", "dataLabelsGroup"],
+          // use separate negative stacks, unlike area stacks where a negative
+          // point is substracted from previous (#1910)
+          negStacks: true,
+          /* eslint-disable valid-jsdoc */
+          /**
+           * Initialize the series. Extends the basic Series.init method by
+           * marking other series of the same type as dirty.
+           *
+           * @private
+           * @function Highcharts.seriesTypes.column#init
+           * @return {void}
+           */
+          init: function () {
+            LineSeries.prototype.init.apply(this, arguments);
+            var series = this,
+              chart = series.chart;
+            // if the series is added dynamically, force redraw of other
+            // series affected by a new column
+            if (chart.hasRendered) {
+              chart.series.forEach(function (otherSeries) {
+                if (otherSeries.type === series.type) {
+                  otherSeries.isDirty = true;
+                }
+              });
+            }
+          },
+          /**
+           * Return the width and x offset of the columns adjusted for grouping,
+           * groupPadding, pointPadding, pointWidth etc.
+           *
+           * @private
+           * @function Highcharts.seriesTypes.column#getColumnMetrics
+           * @return {Highcharts.ColumnMetricsObject}
+           */
+          getColumnMetrics: function () {
+            var series = this,
+              options = series.options,
+              xAxis = series.xAxis,
+              yAxis = series.yAxis,
+              reversedStacks = xAxis.options.reversedStacks,
+              // Keep backward compatibility: reversed xAxis had reversed
+              // stacks
+              reverseStacks =
+                (xAxis.reversed && !reversedStacks) ||
+                (!xAxis.reversed && reversedStacks),
+              stackKey,
+              stackGroups = {},
+              columnCount = 0;
+            // Get the total number of column type series. This is called on
+            // every series. Consider moving this logic to a chart.orderStacks()
+            // function and call it on init, addSeries and removeSeries
+            if (options.grouping === false) {
+              columnCount = 1;
+            } else {
+              series.chart.series.forEach(function (otherSeries) {
+                var otherYAxis = otherSeries.yAxis,
+                  otherOptions = otherSeries.options,
+                  columnIndex;
+                if (
+                  otherSeries.type === series.type &&
+                  (otherSeries.visible ||
+                    !series.chart.options.chart.ignoreHiddenSeries) &&
+                  yAxis.len === otherYAxis.len &&
+                  yAxis.pos === otherYAxis.pos
+                ) {
+                  // #642, #2086
+                  if (
+                    otherOptions.stacking &&
+                    otherOptions.stacking !== "group"
+                  ) {
+                    stackKey = otherSeries.stackKey;
+                    if (typeof stackGroups[stackKey] === "undefined") {
+                      stackGroups[stackKey] = columnCount++;
+                    }
+                    columnIndex = stackGroups[stackKey];
+                  } else if (otherOptions.grouping !== false) {
+                    // #1162
+                    columnIndex = columnCount++;
+                  }
+                  otherSeries.columnIndex = columnIndex;
+                }
+              });
+            }
+            var categoryWidth = Math.min(
+                Math.abs(xAxis.transA) *
+                  ((xAxis.ordinal && xAxis.ordinal.slope) ||
+                    options.pointRange ||
+                    xAxis.closestPointRange ||
+                    xAxis.tickInterval ||
+                    1), // #2610
+                xAxis.len // #1535
+              ),
+              groupPadding = categoryWidth * options.groupPadding,
+              groupWidth = categoryWidth - 2 * groupPadding,
+              pointOffsetWidth = groupWidth / (columnCount || 1),
+              pointWidth = Math.min(
+                options.maxPointWidth || xAxis.len,
+                pick(
+                  options.pointWidth,
+                  pointOffsetWidth * (1 - 2 * options.pointPadding)
+                )
+              ),
+              pointPadding = (pointOffsetWidth - pointWidth) / 2,
+              // #1251, #3737
+              colIndex = (series.columnIndex || 0) + (reverseStacks ? 1 : 0),
+              pointXOffset =
+                pointPadding +
+                (groupPadding +
+                  colIndex * pointOffsetWidth -
+                  categoryWidth / 2) *
+                  (reverseStacks ? -1 : 1);
+            // Save it for reading in linked series (Error bars particularly)
+            series.columnMetrics = {
+              width: pointWidth,
+              offset: pointXOffset,
+              paddedWidth: pointOffsetWidth,
+              columnCount: columnCount,
+            };
+            return series.columnMetrics;
+          },
+          /**
+           * Make the columns crisp. The edges are rounded to the nearest full
+           * pixel.
+           *
+           * @private
+           * @function Highcharts.seriesTypes.column#crispCol
+           * @param {number} x
+           * @param {number} y
+           * @param {number} w
+           * @param {number} h
+           * @return {Highcharts.BBoxObject}
+           */
+          crispCol: function (x, y, w, h) {
+            var chart = this.chart,
+              borderWidth = this.borderWidth,
+              xCrisp = -(borderWidth % 2 ? 0.5 : 0),
+              yCrisp = borderWidth % 2 ? 0.5 : 1,
+              right,
+              bottom,
+              fromTop;
+            if (chart.inverted && chart.renderer.isVML) {
+              yCrisp += 1;
+            }
+            // Horizontal. We need to first compute the exact right edge, then
+            // round it and compute the width from there.
+            if (this.options.crisp) {
+              right = Math.round(x + w) + xCrisp;
+              x = Math.round(x) + xCrisp;
+              w = right - x;
+            }
+            // Vertical
+            bottom = Math.round(y + h) + yCrisp;
+            fromTop = Math.abs(y) <= 0.5 && bottom > 0.5; // #4504, #4656
+            y = Math.round(y) + yCrisp;
+            h = bottom - y;
+            // Top edges are exceptions
+            if (fromTop && h) {
+              // #5146
+              y -= 1;
+              h += 1;
+            }
+            return {
+              x: x,
+              y: y,
+              width: w,
+              height: h,
+            };
+          },
+          /**
+           * Adjust for missing columns, according to the `centerInCategory`
+           * option. Missing columns are either single points or stacks where the
+           * point or points are either missing or null.
+           *
+           * @private
+           * @function Highcharts.seriesTypes.column#adjustForMissingColumns
+           * @param {number} x
+           *        The x coordinate of the column, left side
+           * @param {number} pointWidth
+           *        The pointWidth, already computed upstream
+           * @param {Highcharts.ColumnPoint} point
+           *        The point instance
+           * @param {Highcharts.ColumnMetricsObject} metrics
+           *        The series-wide column metrics
+           * @return {number}
+           *        The adjusted x position, or the original if not adjusted
+           */
+          adjustForMissingColumns: function (x, pointWidth, point, metrics) {
+            var _this = this;
+            var stacking = this.options.stacking;
+            if (!point.isNull && metrics.columnCount > 1) {
+              var indexInCategory_1 = 0;
+              var totalInCategory_1 = 0;
+              // Loop over all the stacks on the Y axis. When stacking is
+              // enabled, these are real point stacks. When stacking is not
+              // enabled, but `centerInCategory` is true, there is one stack
+              // handling the grouping of points in each category. This is
+              // done in the `setGroupedPoints` function.
+              objectEach(
+                this.yAxis.stacking && this.yAxis.stacking.stacks,
+                function (stack) {
+                  if (typeof point.x === "number") {
+                    var stackItem = stack[point.x.toString()];
+                    if (stackItem) {
+                      var pointValues = stackItem.points[_this.index],
+                        total = stackItem.total;
+                      // If true `stacking` is enabled, count the
+                      // total number of non-null stacks in the
+                      // category, and note which index this point is
+                      // within those stacks.
+                      if (stacking) {
+                        if (pointValues) {
+                          indexInCategory_1 = totalInCategory_1;
+                        }
+                        if (stackItem.hasValidPoints) {
+                          totalInCategory_1++;
+                        }
+                        // If `stacking` is not enabled, look for the
+                        // index and total of the `group` stack.
+                      } else if (isArray(pointValues)) {
+                        indexInCategory_1 = pointValues[1];
+                        totalInCategory_1 = total || 0;
+                      }
+                    }
+                  }
+                }
+              );
+              // Compute the adjusted x position
+              var boxWidth =
+                (totalInCategory_1 - 1) * metrics.paddedWidth + pointWidth;
+              x =
+                (point.plotX || 0) +
+                boxWidth / 2 -
+                pointWidth -
+                indexInCategory_1 * metrics.paddedWidth;
+            }
+            return x;
+          },
+          /**
+           * Translate each point to the plot area coordinate system and find
+           * shape positions
+           *
+           * @private
+           * @function Highcharts.seriesTypes.column#translate
+           */
+          translate: function () {
+            var series = this,
+              chart = series.chart,
+              options = series.options,
+              dense = (series.dense =
+                series.closestPointRange * series.xAxis.transA < 2),
+              borderWidth = (series.borderWidth = pick(
+                options.borderWidth,
+                dense ? 0 : 1 // #3635
+              )),
+              xAxis = series.xAxis,
+              yAxis = series.yAxis,
+              threshold = options.threshold,
+              translatedThreshold = (series.translatedThreshold =
+                yAxis.getThreshold(threshold)),
+              minPointLength = pick(options.minPointLength, 5),
+              metrics = series.getColumnMetrics(),
+              seriesPointWidth = metrics.width,
+              // postprocessed for border width
+              seriesBarW = (series.barW = Math.max(
+                seriesPointWidth,
+                1 + 2 * borderWidth
+              )),
+              seriesXOffset = (series.pointXOffset = metrics.offset),
+              dataMin = series.dataMin,
+              dataMax = series.dataMax;
+            if (chart.inverted) {
+              translatedThreshold -= 0.5; // #3355
+            }
+            // When the pointPadding is 0, we want the columns to be packed
+            // tightly, so we allow individual columns to have individual sizes.
+            // When pointPadding is greater, we strive for equal-width columns
+            // (#2694).
+            if (options.pointPadding) {
+              seriesBarW = Math.ceil(seriesBarW);
+            }
+            LineSeries.prototype.translate.apply(series);
+            // Record the new values
+            series.points.forEach(function (point) {
+              var yBottom = pick(point.yBottom, translatedThreshold),
+                safeDistance = 999 + Math.abs(yBottom),
+                pointWidth = seriesPointWidth,
+                plotX = point.plotX || 0,
+                // Don't draw too far outside plot area (#1303, #2241,
+                // #4264)
+                plotY = clamp(
+                  point.plotY,
+                  -safeDistance,
+                  yAxis.len + safeDistance
+                ),
+                barX = plotX + seriesXOffset,
+                barW = seriesBarW,
+                barY = Math.min(plotY, yBottom),
+                up,
+                barH = Math.max(plotY, yBottom) - barY;
+              // Handle options.minPointLength
+              if (minPointLength && Math.abs(barH) < minPointLength) {
+                barH = minPointLength;
+                up =
+                  (!yAxis.reversed && !point.negative) ||
+                  (yAxis.reversed && point.negative);
+                // Reverse zeros if there's no positive value in the series
+                // in visible range (#7046)
+                if (
+                  isNumber(threshold) &&
+                  isNumber(dataMax) &&
+                  point.y === threshold &&
+                  dataMax <= threshold &&
+                  // and if there's room for it (#7311)
+                  (yAxis.min || 0) < threshold &&
+                  // if all points are the same value (i.e zero) not draw
+                  // as negative points (#10646)
+                  dataMin !== dataMax
+                ) {
+                  up = !up;
+                }
+                // If stacked...
+                barY =
+                  Math.abs(barY - translatedThreshold) > minPointLength
+                    ? // ...keep position
+                      yBottom - minPointLength
+                    : // #1485, #4051
+                      translatedThreshold - (up ? minPointLength : 0);
+              }
+              // Handle point.options.pointWidth
+              // @todo Handle grouping/stacking too. Calculate offset properly
+              if (defined(point.options.pointWidth)) {
+                pointWidth = barW = Math.ceil(point.options.pointWidth);
+                barX -= Math.round((pointWidth - seriesPointWidth) / 2);
+              }
+              // Adjust for null or missing points
+              if (options.centerInCategory) {
+                barX = series.adjustForMissingColumns(
+                  barX,
+                  pointWidth,
+                  point,
+                  metrics
+                );
+              }
+              // Cache for access in polar
+              point.barX = barX;
+              point.pointWidth = pointWidth;
+              // Fix the tooltip on center of grouped columns (#1216, #424,
+              // #3648)
+              point.tooltipPos = chart.inverted
+                ? [
+                    yAxis.len + yAxis.pos - chart.plotLeft - plotY,
+                    xAxis.len +
+                      xAxis.pos -
+                      chart.plotTop -
+                      (plotX || 0) -
+                      seriesXOffset -
+                      barW / 2,
+                    barH,
+                  ]
+                : [barX + barW / 2, plotY + yAxis.pos - chart.plotTop, barH];
+              // Register shape type and arguments to be used in drawPoints
+              // Allow shapeType defined on pointClass level
+              point.shapeType = series.pointClass.prototype.shapeType || "rect";
+              point.shapeArgs = series.crispCol.apply(
+                series,
+                point.isNull
+                  ? // #3169, drilldown from null must have a position to work
+                    // from #6585, dataLabel should be placed on xAxis, not
+                    // floating in the middle of the chart
+                    [barX, translatedThreshold, barW, 0]
+                  : [barX, barY, barW, barH]
+              );
+            });
+          },
+          getSymbol: noop,
+          /**
+           * Use a solid rectangle like the area series types
+           *
+           * @private
+           * @function Highcharts.seriesTypes.column#drawLegendSymbol
+           *
+           * @param {Highcharts.Legend} legend
+           *        The legend object
+           *
+           * @param {Highcharts.Series|Highcharts.Point} item
+           *        The series (this) or point
+           */
+          drawLegendSymbol: LegendSymbolMixin.drawRectangle,
+          /**
+           * Columns have no graph
+           *
+           * @private
+           * @function Highcharts.seriesTypes.column#drawGraph
+           */
+          drawGraph: function () {
+            this.group[this.dense ? "addClass" : "removeClass"](
+              "highcharts-dense-data"
+            );
+          },
+          /**
+           * Get presentational attributes
+           *
+           * @private
+           * @function Highcharts.seriesTypes.column#pointAttribs
+           *
+           * @param {Highcharts.ColumnPoint} point
+           *
+           * @param {string} state
+           *
+           * @return {Highcharts.SVGAttributes}
+           */
+          pointAttribs: function (point, state) {
+            var options = this.options,
+              stateOptions,
+              ret,
+              p2o = this.pointAttrToOptions || {},
+              strokeOption = p2o.stroke || "borderColor",
+              strokeWidthOption = p2o["stroke-width"] || "borderWidth",
+              fill = (point && point.color) || this.color,
+              // set to fill when borderColor null:
+              stroke =
+                (point && point[strokeOption]) ||
+                options[strokeOption] ||
+                this.color ||
+                fill,
+              strokeWidth =
+                (point && point[strokeWidthOption]) ||
+                options[strokeWidthOption] ||
+                this[strokeWidthOption] ||
+                0,
+              dashstyle =
+                (point && point.options.dashStyle) || options.dashStyle,
+              opacity = pick(point && point.opacity, options.opacity, 1),
+              zone,
+              brightness;
+            // Handle zone colors
+            if (point && this.zones.length) {
+              zone = point.getZone();
+              // When zones are present, don't use point.color (#4267).
+              // Changed order (#6527), added support for colorAxis (#10670)
+              fill =
+                point.options.color ||
+                (zone && (zone.color || point.nonZonedColor)) ||
+                this.color;
+              if (zone) {
+                stroke = zone.borderColor || stroke;
+                dashstyle = zone.dashStyle || dashstyle;
+                strokeWidth = zone.borderWidth || strokeWidth;
+              }
+            }
+            // Select or hover states
+            if (state && point) {
+              stateOptions = merge(
+                options.states[state],
+                // #6401
+                (point.options.states && point.options.states[state]) || {}
+              );
+              brightness = stateOptions.brightness;
+              fill =
+                stateOptions.color ||
+                (typeof brightness !== "undefined" &&
+                  color(fill).brighten(stateOptions.brightness).get()) ||
+                fill;
+              stroke = stateOptions[strokeOption] || stroke;
+              strokeWidth = stateOptions[strokeWidthOption] || strokeWidth;
+              dashstyle = stateOptions.dashStyle || dashstyle;
+              opacity = pick(stateOptions.opacity, opacity);
+            }
+            ret = {
+              fill: fill,
+              stroke: stroke,
+              "stroke-width": strokeWidth,
+              opacity: opacity,
+            };
+            if (dashstyle) {
+              ret.dashstyle = dashstyle;
+            }
+            return ret;
+          },
+          /**
+           * Draw the columns. For bars, the series.group is rotated, so the same
+           * coordinates apply for columns and bars. This method is inherited by
+           * scatter series.
+           *
+           * @private
+           * @function Highcharts.seriesTypes.column#drawPoints
+           */
+          drawPoints: function () {
+            var series = this,
+              chart = this.chart,
+              options = series.options,
+              renderer = chart.renderer,
+              animationLimit = options.animationLimit || 250,
+              shapeArgs;
+            // draw the columns
+            series.points.forEach(function (point) {
+              var plotY = point.plotY,
+                graphic = point.graphic,
+                hasGraphic = !!graphic,
+                verb =
+                  graphic && chart.pointCount < animationLimit
+                    ? "animate"
+                    : "attr";
+              if (isNumber(plotY) && point.y !== null) {
+                shapeArgs = point.shapeArgs;
+                // When updating a series between 2d and 3d or cartesian and
+                // polar, the shape type changes.
+                if (graphic && point.hasNewShapeType()) {
+                  graphic = graphic.destroy();
+                }
+                // Set starting position for point sliding animation.
+                if (series.enabledDataSorting) {
+                  point.startXPos = series.xAxis.reversed
+                    ? -(shapeArgs ? shapeArgs.width : 0)
+                    : series.xAxis.width;
+                }
+                if (!graphic) {
+                  point.graphic = graphic = renderer[point.shapeType](
+                    shapeArgs
+                  ).add(point.group || series.group);
+                  if (
+                    graphic &&
+                    series.enabledDataSorting &&
+                    chart.hasRendered &&
+                    chart.pointCount < animationLimit
+                  ) {
+                    graphic.attr({
+                      x: point.startXPos,
                     });
+                    hasGraphic = true;
+                    verb = "animate";
+                  }
                 }
-                // Show or hide the Reset zoom button
-                resetZoomButton = chart.resetZoomButton;
-                if (displayButton && !resetZoomButton) {
-                    chart.showResetZoom();
-                }
-                else if (!displayButton && isObject(resetZoomButton)) {
-                    chart.resetZoomButton = resetZoomButton.destroy();
+                if (graphic && hasGraphic) {
+                  // update
+                  graphic[verb](merge(shapeArgs));
                 }
-                // Redraw
-                if (hasZoomed) {
-                    chart.redraw(pick(chart.options.chart.animation, event && event.animation, chart.pointCount < 100));
+                // Border radius is not stylable (#6900)
+                if (options.borderRadius) {
+                  graphic[verb]({
+                    r: options.borderRadius,
+                  });
                 }
-            },
+                // Presentational
+                if (!chart.styledMode) {
+                  graphic[verb](
+                    series.pointAttribs(point, point.selected && "select")
+                  ).shadow(
+                    point.allowShadow !== false && options.shadow,
+                    null,
+                    options.stacking && !options.borderRadius
+                  );
+                }
+                graphic.addClass(point.getClassName(), true);
+              } else if (graphic) {
+                point.graphic = graphic.destroy(); // #1269
+              }
+            });
+          },
+          /**
+           * Animate the column heights one by one from zero.
+           *
+           * @private
+           * @function Highcharts.seriesTypes.column#animate
+           *
+           * @param {boolean} init
+           *        Whether to initialize the animation or run it
+           */
+          animate: function (init) {
+            var series = this,
+              yAxis = this.yAxis,
+              options = series.options,
+              inverted = this.chart.inverted,
+              attr = {},
+              translateProp = inverted ? "translateX" : "translateY",
+              translateStart,
+              translatedThreshold;
+            if (init) {
+              attr.scaleY = 0.001;
+              translatedThreshold = clamp(
+                yAxis.toPixels(options.threshold),
+                yAxis.pos,
+                yAxis.pos + yAxis.len
+              );
+              if (inverted) {
+                attr.translateX = translatedThreshold - yAxis.len;
+              } else {
+                attr.translateY = translatedThreshold;
+              }
+              // apply finnal clipping (used in Highstock) (#7083)
+              // animation is done by scaleY, so cliping is for panes
+              if (series.clipBox) {
+                series.setClip();
+              }
+              series.group.attr(attr);
+            } else {
+              // run the animation
+              translateStart = series.group.attr(translateProp);
+              series.group.animate(
+                { scaleY: 1 },
+                extend(animObject(series.options.animation), {
+                  // Do the scale synchronously to ensure smooth
+                  // updating (#5030, #7228)
+                  step: function (val, fx) {
+                    if (series.group) {
+                      attr[translateProp] =
+                        translateStart + fx.pos * (yAxis.pos - translateStart);
+                      series.group.attr(attr);
+                    }
+                  },
+                })
+              );
+            }
+          },
+          /**
+           * Remove this series from the chart
+           *
+           * @private
+           * @function Highcharts.seriesTypes.column#remove
+           */
+          remove: function () {
+            var series = this,
+              chart = series.chart;
+            // column and bar series affects other series of the same type
+            // as they are either stacked or grouped
+            if (chart.hasRendered) {
+              chart.series.forEach(function (otherSeries) {
+                if (otherSeries.type === series.type) {
+                  otherSeries.isDirty = true;
+                }
+              });
+            }
+            LineSeries.prototype.remove.apply(series, arguments);
+          },
+        }
+      );
+      /* eslint-enable valid-jsdoc */
+      /**
+       * A `column` series. If the [type](#series.column.type) option is
+       * not specified, it is inherited from [chart.type](#chart.type).
+       *
+       * @extends   series,plotOptions.column
+       * @excluding connectNulls, dataParser, dataURL, gapSize, gapUnit, linecap,
+       *            lineWidth, marker, connectEnds, step
+       * @product   highcharts highstock
+       * @apioption series.column
+       */
+      /**
+       * An array of data points for the series. For the `column` series type,
+       * points can be given in the following ways:
+       *
+       * 1. An array of numerical values. In this case, the numerical values will be
+       *    interpreted as `y` options. The `x` values will be automatically
+       *    calculated, either starting at 0 and incremented by 1, or from
+       *    `pointStart` and `pointInterval` given in the series options. If the axis
+       *    has categories, these will be used. Example:
+       *    ```js
+       *    data: [0, 5, 3, 5]
+       *    ```
+       *
+       * 2. An array of arrays with 2 values. In this case, the values correspond to
+       *    `x,y`. If the first value is a string, it is applied as the name of the
+       *    point, and the `x` value is inferred.
+       *    ```js
+       *    data: [
+       *        [0, 6],
+       *        [1, 2],
+       *        [2, 6]
+       *    ]
+       *    ```
+       *
+       * 3. An array of objects with named values. The following snippet shows only a
+       *    few settings, see the complete options set below. If the total number of
+       *    data points exceeds the series'
+       *    [turboThreshold](#series.column.turboThreshold), this option is not
+       *    available.
+       *    ```js
+       *    data: [{
+       *        x: 1,
+       *        y: 9,
+       *        name: "Point2",
+       *        color: "#00FF00"
+       *    }, {
+       *        x: 1,
+       *        y: 6,
+       *        name: "Point1",
+       *        color: "#FF00FF"
+       *    }]
+       *    ```
+       *
+       * @sample {highcharts} highcharts/chart/reflow-true/
+       *         Numerical values
+       * @sample {highcharts} highcharts/series/data-array-of-arrays/
+       *         Arrays of numeric x and y
+       * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
+       *         Arrays of datetime x and y
+       * @sample {highcharts} highcharts/series/data-array-of-name-value/
+       *         Arrays of point.name and y
+       * @sample {highcharts} highcharts/series/data-array-of-objects/
+       *         Config objects
+       *
+       * @type      {Array<number|Array<(number|string),(number|null)>|null|*>}
+       * @extends   series.line.data
+       * @excluding marker
+       * @product   highcharts highstock
+       * @apioption series.column.data
+       */
+      /**
+       * The color of the border surrounding the column or bar.
+       *
+       * In styled mode, the border stroke can be set with the `.highcharts-point`
+       * rule.
+       *
+       * @sample {highcharts} highcharts/plotoptions/column-bordercolor/
+       *         Dark gray border
+       *
+       * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+       * @product   highcharts highstock
+       * @apioption series.column.data.borderColor
+       */
+      /**
+       * The width of the border surrounding the column or bar.
+       *
+       * In styled mode, the stroke width can be set with the `.highcharts-point`
+       * rule.
+       *
+       * @sample {highcharts} highcharts/plotoptions/column-borderwidth/
+       *         2px black border
+       *
+       * @type      {number}
+       * @product   highcharts highstock
+       * @apioption series.column.data.borderWidth
+       */
+      /**
+       * A name for the dash style to use for the column or bar. Overrides
+       * dashStyle on the series.
+       *
+       * In styled mode, the stroke dash-array can be set with the same classes as
+       * listed under [data.color](#series.column.data.color).
+       *
+       * @see [series.pointWidth](#plotOptions.column.dashStyle)
+       *
+       * @type      {Highcharts.DashStyleValue}
+       * @apioption series.column.data.dashStyle
+       */
+      /**
+       * A pixel value specifying a fixed width for the column or bar. Overrides
+       * pointWidth on the series. The width effects the dimension that is not based
+       * on the point value.
+       *
+       * @see [series.pointWidth](#plotOptions.column.pointWidth)
+       *
+       * @type      {number}
+       * @apioption series.column.data.pointWidth
+       */
+      /**
+       * @excluding halo, lineWidth, lineWidthPlus, marker
+       * @product   highcharts highstock
+       * @apioption series.column.states.hover
+       */
+      /**
+       * @excluding halo, lineWidth, lineWidthPlus, marker
+       * @product   highcharts highstock
+       * @apioption series.column.states.select
+       */
+      (""); // includes above doclets in transpilat
+
+      return ColumnSeries;
+    }
+  );
+  _registerModule(
+    _modules,
+    "Series/BarSeries.js",
+    [_modules["Core/Series/Series.js"]],
+    function (Series) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      /**
+       * Bar series type.
+       *
+       * @private
+       * @class
+       * @name Highcharts.seriesTypes.bar
+       *
+       * @augments Highcharts.Series
+       */
+      Series.seriesType(
+        "bar",
+        "column",
+        /**
+         * A bar series is a special type of column series where the columns are
+         * horizontal.
+         *
+         * @sample highcharts/demo/bar-basic/
+         *         Bar chart
+         *
+         * @extends   plotOptions.column
+         * @product   highcharts
+         * @apioption plotOptions.bar
+         */
+        /**
+         * @ignore
+         */
+        null,
+        {
+          inverted: true,
+        }
+      );
+      /**
+       * A `bar` series. If the [type](#series.bar.type) option is not specified,
+       * it is inherited from [chart.type](#chart.type).
+       *
+       * @extends   series,plotOptions.bar
+       * @excluding connectNulls, dashStyle, dataParser, dataURL, gapSize, gapUnit,
+       *            linecap, lineWidth, marker, connectEnds, step
+       * @product   highcharts
+       * @apioption series.bar
+       */
+      /**
+       * An array of data points for the series. For the `bar` series type,
+       * points can be given in the following ways:
+       *
+       * 1. An array of numerical values. In this case, the numerical values will be
+       *    interpreted as `y` options. The `x` values will be automatically
+       *    calculated, either starting at 0 and incremented by 1, or from
+       *    `pointStart` and `pointInterval` given in the series options. If the axis
+       *    has categories, these will be used. Example:
+       *    ```js
+       *    data: [0, 5, 3, 5]
+       *    ```
+       *
+       * 2. An array of arrays with 2 values. In this case, the values correspond to
+       *    `x,y`. If the first value is a string, it is applied as the name of the
+       *    point, and the `x` value is inferred.
+       *    ```js
+       *    data: [
+       *        [0, 5],
+       *        [1, 10],
+       *        [2, 3]
+       *    ]
+       *    ```
+       *
+       * 3. An array of objects with named values. The following snippet shows only a
+       *    few settings, see the complete options set below. If the total number of
+       *    data points exceeds the series'
+       *    [turboThreshold](#series.bar.turboThreshold), this option is not
+       *    available.
+       *    ```js
+       *    data: [{
+       *        x: 1,
+       *        y: 1,
+       *        name: "Point2",
+       *        color: "#00FF00"
+       *    }, {
+       *        x: 1,
+       *        y: 10,
+       *        name: "Point1",
+       *        color: "#FF00FF"
+       *    }]
+       *    ```
+       *
+       * @sample {highcharts} highcharts/chart/reflow-true/
+       *         Numerical values
+       * @sample {highcharts} highcharts/series/data-array-of-arrays/
+       *         Arrays of numeric x and y
+       * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
+       *         Arrays of datetime x and y
+       * @sample {highcharts} highcharts/series/data-array-of-name-value/
+       *         Arrays of point.name and y
+       * @sample {highcharts} highcharts/series/data-array-of-objects/
+       *         Config objects
+       *
+       * @type      {Array<number|Array<(number|string),(number|null)>|null|*>}
+       * @extends   series.column.data
+       * @product   highcharts
+       * @apioption series.bar.data
+       */
+      /**
+       * @excluding halo,lineWidth,lineWidthPlus,marker
+       * @product   highcharts highstock
+       * @apioption series.bar.states.hover
+       */
+      /**
+       * @excluding halo,lineWidth,lineWidthPlus,marker
+       * @product   highcharts highstock
+       * @apioption series.bar.states.select
+       */
+      (""); // gets doclets above into transpilat
+    }
+  );
+  _registerModule(
+    _modules,
+    "Series/ScatterSeries.js",
+    [
+      _modules["Core/Series/Series.js"],
+      _modules["Core/Globals.js"],
+      _modules["Core/Utilities.js"],
+    ],
+    function (BaseSeries, H, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      var addEvent = U.addEvent;
+      var Series = H.Series;
+      /**
+       * Scatter series type.
+       *
+       * @private
+       * @class
+       * @name Highcharts.seriesTypes.scatter
+       *
+       * @augments Highcharts.Series
+       */
+      BaseSeries.seriesType(
+        "scatter",
+        "line",
+        /**
+         * A scatter plot uses cartesian coordinates to display values for two
+         * variables for a set of data.
+         *
+         * @sample {highcharts} highcharts/demo/scatter/
+         *         Scatter plot
+         *
+         * @extends      plotOptions.line
+         * @excluding    cropThreshold, pointPlacement, shadow, useOhlcData
+         * @product      highcharts highstock
+         * @optionparent plotOptions.scatter
+         */
+        {
+          /**
+           * The width of the line connecting the data points.
+           *
+           * @sample {highcharts} highcharts/plotoptions/scatter-linewidth-none/
+           *         0 by default
+           * @sample {highcharts} highcharts/plotoptions/scatter-linewidth-1/
+           *         1px
+           *
+           * @product highcharts highstock
+           */
+          lineWidth: 0,
+          findNearestPointBy: "xy",
+          /**
+           * Apply a jitter effect for the rendered markers. When plotting
+           * discrete values, a little random noise may help telling the points
+           * apart. The jitter setting applies a random displacement of up to `n`
+           * axis units in either direction. So for example on a horizontal X
+           * axis, setting the `jitter.x` to 0.24 will render the point in a
+           * random position between 0.24 units to the left and 0.24 units to the
+           * right of the true axis position. On a category axis, setting it to
+           * 0.5 will fill up the bin and make the data appear continuous.
+           *
+           * When rendered on top of a box plot or a column series, a jitter value
+           * of 0.24 will correspond to the underlying series' default
+           * [groupPadding](
+           * https://api.highcharts.com/highcharts/plotOptions.column.groupPadding)
+           * and [pointPadding](
+           * https://api.highcharts.com/highcharts/plotOptions.column.pointPadding)
+           * settings.
+           *
+           * @sample {highcharts} highcharts/series-scatter/jitter
+           *         Jitter on a scatter plot
+           *
+           * @sample {highcharts} highcharts/series-scatter/jitter-boxplot
+           *         Jittered scatter plot on top of a box plot
+           *
+           * @product highcharts highstock
+           * @since 7.0.2
+           */
+          jitter: {
+            /**
+             * The maximal X offset for the random jitter effect.
+             */
+            x: 0,
+            /**
+             * The maximal Y offset for the random jitter effect.
+             */
+            y: 0,
+          },
+          marker: {
+            enabled: true, // Overrides auto-enabling in line series (#3647)
+          },
+          /**
+           * Sticky tracking of mouse events. When true, the `mouseOut` event
+           * on a series isn't triggered until the mouse moves over another
+           * series, or out of the plot area. When false, the `mouseOut` event on
+           * a series is triggered when the mouse leaves the area around the
+           * series' graph or markers. This also implies the tooltip. When
+           * `stickyTracking` is false and `tooltip.shared` is false, the tooltip
+           * will be hidden when moving the mouse between series.
+           *
+           * @type      {boolean}
+           * @default   false
+           * @product   highcharts highstock
+           * @apioption plotOptions.scatter.stickyTracking
+           */
+          /**
+           * A configuration object for the tooltip rendering of each single
+           * series. Properties are inherited from [tooltip](#tooltip).
+           * Overridable properties are `headerFormat`, `pointFormat`,
+           * `yDecimals`, `xDateFormat`, `yPrefix` and `ySuffix`. Unlike other
+           * series, in a scatter plot the series.name by default shows in the
+           * headerFormat and point.x and point.y in the pointFormat.
+           *
+           * @product highcharts highstock
+           */
+          tooltip: {
+            headerFormat:
+              '<span style="color:{point.color}">\u25CF</span> ' +
+              '<span style="font-size: 10px"> {series.name}</span><br/>',
+            pointFormat: "x: <b>{point.x}</b><br/>y: <b>{point.y}</b><br/>",
+          },
+          // Prototype members
+        },
+        {
+          sorted: false,
+          requireSorting: false,
+          noSharedTooltip: true,
+          trackerGroups: ["group", "markerGroup", "dataLabelsGroup"],
+          takeOrdinalPosition: false,
+          /* eslint-disable valid-jsdoc */
+          /**
+           * @private
+           * @function Highcharts.seriesTypes.scatter#drawGraph
+           */
+          drawGraph: function () {
+            if (
+              this.options.lineWidth ||
+              // In case we have a graph from before and we update the line
+              // width to 0 (#13816)
+              (this.options.lineWidth === 0 &&
+                this.graph &&
+                this.graph.strokeWidth())
+            ) {
+              Series.prototype.drawGraph.call(this);
+            }
+          },
+          // Optionally add the jitter effect
+          applyJitter: function () {
+            var series = this,
+              jitter = this.options.jitter,
+              len = this.points.length;
             /**
-             * Pan the chart by dragging the mouse across the pane. This function is
-             * called on mouse move, and the distance to pan is computed from chartX
-             * compared to the first chartX position in the dragging operation.
-             *
+             * Return a repeatable, pseudo-random number based on an integer
+             * seed.
              * @private
-             * @function Highcharts.Chart#pan
-             * @param {Highcharts.PointerEventObject} e
-             * @param {string} panning
              */
-            pan: function (e, panning) {
-                var chart = this,
-                    hoverPoints = chart.hoverPoints,
-                    panningOptions,
-                    chartOptions = chart.options.chart,
-                    hasMapNavigation = chart.options.mapNavigation &&
-                        chart.options.mapNavigation.enabled,
-                    doRedraw,
-                    type;
-                if (typeof panning === 'object') {
-                    panningOptions = panning;
-                }
-                else {
-                    panningOptions = {
-                        enabled: panning,
-                        type: 'x'
-                    };
-                }
-                if (chartOptions && chartOptions.panning) {
-                    chartOptions.panning = panningOptions;
-                }
-                type = panningOptions.type;
-                fireEvent(this, 'pan', { originalEvent: e }, function () {
-                    // remove active points for shared tooltip
-                    if (hoverPoints) {
-                        hoverPoints.forEach(function (point) {
-                            point.setState();
-                        });
-                    }
-                    // panning axis mapping
-                    var xy = [1]; // x
-                        if (type === 'xy') {
-                            xy = [1, 0];
-                    }
-                    else if (type === 'y') {
-                        xy = [0];
-                    }
-                    xy.forEach(function (isX) {
-                        var axis = chart[isX ? 'xAxis' : 'yAxis'][0], horiz = axis.horiz, mousePos = e[horiz ? 'chartX' : 'chartY'], mouseDown = horiz ? 'mouseDownX' : 'mouseDownY', startPos = chart[mouseDown], halfPointRange = (axis.pointRange || 0) / 2, pointRangeDirection = (axis.reversed && !chart.inverted) ||
-                                (!axis.reversed && chart.inverted) ?
-                                -1 :
-                                1, extremes = axis.getExtremes(), panMin = axis.toValue(startPos - mousePos, true) +
-                                halfPointRange * pointRangeDirection, panMax = axis.toValue(startPos + axis.len - mousePos, true) -
-                                halfPointRange * pointRangeDirection, flipped = panMax < panMin, newMin = flipped ? panMax : panMin, newMax = flipped ? panMin : panMax, hasVerticalPanning = axis.hasVerticalPanning(), paddedMin, paddedMax, spill, panningState = axis.panningState;
-                        // General calculations of panning state.
-                        // This is related to using vertical panning. (#11315).
-                        axis.series.forEach(function (series) {
-                            if (hasVerticalPanning &&
-                                !isX && (!panningState || panningState.isDirty)) {
-                                var processedData = series.getProcessedData(true),
-                                    dataExtremes = series.getExtremes(processedData.yData,
-                                    true);
-                                if (!panningState) {
-                                    panningState = {
-                                        startMin: Number.MAX_VALUE,
-                                        startMax: -Number.MAX_VALUE
-                                    };
-                                }
-                                if (isNumber(dataExtremes.dataMin) &&
-                                    isNumber(dataExtremes.dataMax)) {
-                                    panningState.startMin = Math.min(dataExtremes.dataMin, panningState.startMin);
-                                    panningState.startMax = Math.max(dataExtremes.dataMax, panningState.startMax);
-                                }
-                            }
-                        });
-                        paddedMin = Math.min(pick(panningState === null || panningState === void 0 ? void 0 : panningState.startMin, extremes.dataMin), halfPointRange ?
-                            extremes.min :
-                            axis.toValue(axis.toPixels(extremes.min) -
-                                axis.minPixelPadding));
-                        paddedMax = Math.max(pick(panningState === null || panningState === void 0 ? void 0 : panningState.startMax, extremes.dataMax), halfPointRange ?
-                            extremes.max :
-                            axis.toValue(axis.toPixels(extremes.max) +
-                                axis.minPixelPadding));
-                        axis.panningState = panningState;
-                        // It is not necessary to calculate extremes on ordinal axis,
-                        // because they are already calculated, so we don't want to
-                        // override them.
-                        if (!axis.isOrdinal) {
-                            // If the new range spills over, either to the min or max,
-                            // adjust the new range.
-                            spill = paddedMin - newMin;
-                            if (spill > 0) {
-                                newMax += spill;
-                                newMin = paddedMin;
-                            }
-                            spill = newMax - paddedMax;
-                            if (spill > 0) {
-                                newMax = paddedMax;
-                                newMin -= spill;
-                            }
-                            // Set new extremes if they are actually new
-                            if (axis.series.length &&
-                                newMin !== extremes.min &&
-                                newMax !== extremes.max &&
-                                newMin >= paddedMin &&
-                                newMax <= paddedMax) {
-                                axis.setExtremes(newMin, newMax, false, false, { trigger: 'pan' });
-                                if (!chart.resetZoomButton &&
-                                    !hasMapNavigation &&
-                                    // Show reset zoom button only when both newMin and
-                                    // newMax values are between padded axis range.
-                                    newMin !== paddedMin &&
-                                    newMax !== paddedMax &&
-                                    type.match('y')) {
-                                    chart.showResetZoom();
-                                    axis.displayBtn = false;
-                                }
-                                doRedraw = true;
-                            }
-                            // set new reference for next run:
-                            chart[mouseDown] = mousePos;
-                        }
-                    });
-                    if (doRedraw) {
-                        chart.redraw(false);
-                    }
-                    css(chart.container, { cursor: 'move' });
-                });
+            function unrandom(seed) {
+              var rand = Math.sin(seed) * 10000;
+              return rand - Math.floor(rand);
             }
-        });
-        // Extend the Point object with interaction
-        extend(Point.prototype, /** @lends Highcharts.Point.prototype */ {
-            /**
-             * Toggle the selection status of a point.
-             *
-             * @see Highcharts.Chart#getSelectedPoints
-             *
-             * @sample highcharts/members/point-select/
-             *         Select a point from a button
-             * @sample highcharts/chart/events-selection-points/
-             *         Select a range of points through a drag selection
-             * @sample maps/series/data-id/
-             *         Select a point in Highmaps
-             *
-             * @function Highcharts.Point#select
-             *
-             * @param {boolean} [selected]
-             * When `true`, the point is selected. When `false`, the point is
-             * unselected. When `null` or `undefined`, the selection state is toggled.
-             *
-             * @param {boolean} [accumulate=false]
-             * When `true`, the selection is added to other selected points.
-             * When `false`, other selected points are deselected. Internally in
-             * Highcharts, when
-             * [allowPointSelect](https://api.highcharts.com/highcharts/plotOptions.series.allowPointSelect)
-             * is `true`, selected points are accumulated on Control, Shift or Cmd
-             * clicking the point.
-             *
-             * @fires Highcharts.Point#event:select
-             * @fires Highcharts.Point#event:unselect
-             */
-            select: function (selected, accumulate) {
-                var point = this,
-                    series = point.series,
-                    chart = series.chart;
-                selected = pick(selected, !point.selected);
-                this.selectedStaging = selected;
-                // fire the event with the default handler
-                point.firePointEvent(selected ? 'select' : 'unselect', { accumulate: accumulate }, function () {
-                    /**
-                     * Whether the point is selected or not.
-                     *
-                     * @see Point#select
-                     * @see Chart#getSelectedPoints
-                     *
-                     * @name Highcharts.Point#selected
-                     * @type {boolean}
-                     */
-                    point.selected = point.options.selected = selected;
-                    series.options.data[series.data.indexOf(point)] =
-                        point.options;
-                    point.setState(selected && 'select');
-                    // unselect all other points unless Ctrl or Cmd + click
-                    if (!accumulate) {
-                        chart.getSelectedPoints().forEach(function (loopPoint) {
-                            var loopSeries = loopPoint.series;
-                            if (loopPoint.selected && loopPoint !== point) {
-                                loopPoint.selected = loopPoint.options.selected =
-                                    false;
-                                loopSeries.options.data[loopSeries.data.indexOf(loopPoint)] = loopPoint.options;
-                                // Programatically selecting a point should restore
-                                // normal state, but when click happened on other
-                                // point, set inactive state to match other points
-                                loopPoint.setState(chart.hoverPoints &&
-                                    loopSeries.options.inactiveOtherPoints ?
-                                    'inactive' : '');
-                                loopPoint.firePointEvent('unselect');
-                            }
-                        });
-                    }
+            if (jitter) {
+              this.points.forEach(function (point, i) {
+                ["x", "y"].forEach(function (dim, j) {
+                  var axis,
+                    plotProp = "plot" + dim.toUpperCase(),
+                    min,
+                    max,
+                    translatedJitter;
+                  if (jitter[dim] && !point.isNull) {
+                    axis = series[dim + "Axis"];
+                    translatedJitter = jitter[dim] * axis.transA;
+                    if (axis && !axis.isLog) {
+                      // Identify the outer bounds of the jitter range
+                      min = Math.max(0, point[plotProp] - translatedJitter);
+                      max = Math.min(
+                        axis.len,
+                        point[plotProp] + translatedJitter
+                      );
+                      // Find a random position within this range
+                      point[plotProp] =
+                        min + (max - min) * unrandom(i + j * len);
+                      // Update clientX for the tooltip k-d-tree
+                      if (dim === "x") {
+                        point.clientX = point.plotX;
+                      }
+                    }
+                  }
                 });
-                delete this.selectedStaging;
-            },
-            /**
-             * Runs on mouse over the point. Called internally from mouse and touch
-             * events.
-             *
-             * @function Highcharts.Point#onMouseOver
-             *
-             * @param {Highcharts.PointerEventObject} [e]
-             *        The event arguments.
-             */
-            onMouseOver: function (e) {
-                var point = this,
-                    series = point.series,
-                    chart = series.chart,
-                    pointer = chart.pointer;
-                e = e ?
-                    pointer.normalize(e) :
-                    // In cases where onMouseOver is called directly without an event
-                    pointer.getChartCoordinatesFromPoint(point, chart.inverted);
-                pointer.runPointActions(e, point);
-            },
-            /**
-             * Runs on mouse out from the point. Called internally from mouse and touch
-             * events.
-             *
-             * @function Highcharts.Point#onMouseOut
-             * @fires Highcharts.Point#event:mouseOut
-             */
-            onMouseOut: function () {
-                var point = this,
-                    chart = point.series.chart;
-                point.firePointEvent('mouseOut');
-                if (!point.series.options.inactiveOtherPoints) {
-                    (chart.hoverPoints || []).forEach(function (p) {
-                        p.setState();
-                    });
-                }
-                chart.hoverPoints = chart.hoverPoint = null;
-            },
-            /**
-             * Import events from the series' and point's options. Only do it on
-             * demand, to save processing time on hovering.
-             *
-             * @private
-             * @function Highcharts.Point#importEvents
-             */
-            importEvents: function () {
-                if (!this.hasImportedEvents) {
-                    var point = this,
-                        options = merge(point.series.options.point,
-                        point.options),
-                        events = options.events;
-                    point.events = events;
-                    objectEach(events, function (event, eventType) {
-                        if (isFunction(event)) {
-                            addEvent(point, eventType, event);
-                        }
-                    });
-                    this.hasImportedEvents = true;
-                }
-            },
-            /**
-             * Set the point's state.
-             *
-             * @function Highcharts.Point#setState
-             *
-             * @param {Highcharts.PointStateValue|""} [state]
-             *        The new state, can be one of `'hover'`, `'select'`, `'inactive'`,
-             *        or `''` (an empty string), `'normal'` or `undefined` to set to
-             *        normal state.
-             * @param {boolean} [move]
-             *        State for animation.
-             *
-             * @fires Highcharts.Point#event:afterSetState
-             */
-            setState: function (state, move) {
-                var point = this,
-                    series = point.series,
-                    previousState = point.state,
-                    stateOptions = (series.options.states[state || 'normal'] ||
-                        {}),
-                    markerOptions = (defaultOptions.plotOptions[series.type].marker &&
-                        series.options.marker),
-                    normalDisabled = (markerOptions && markerOptions.enabled === false),
-                    markerStateOptions = ((markerOptions &&
-                        markerOptions.states &&
-                        markerOptions.states[state || 'normal']) || {}),
-                    stateDisabled = markerStateOptions.enabled === false,
-                    stateMarkerGraphic = series.stateMarkerGraphic,
-                    pointMarker = point.marker || {},
-                    chart = series.chart,
-                    halo = series.halo,
-                    haloOptions,
-                    markerAttribs,
-                    pointAttribs,
-                    pointAttribsAnimation,
-                    hasMarkers = (markerOptions && series.markerAttribs),
-                    newSymbol;
-                state = state || ''; // empty string
-                if (
-                // already has this state
-                (state === point.state && !move) ||
-                    // selected points don't respond to hover
-                    (point.selected && state !== 'select') ||
-                    // series' state options is disabled
-                    (stateOptions.enabled === false) ||
-                    // general point marker's state options is disabled
-                    (state && (stateDisabled ||
-                        (normalDisabled &&
-                            markerStateOptions.enabled === false))) ||
-                    // individual point marker's state options is disabled
-                    (state &&
-                        pointMarker.states &&
-                        pointMarker.states[state] &&
-                        pointMarker.states[state].enabled === false) // #1610
-                ) {
-                    return;
-                }
-                point.state = state;
-                if (hasMarkers) {
-                    markerAttribs = series.markerAttribs(point, state);
-                }
-                // Apply hover styles to the existing point
-                if (point.graphic) {
-                    if (previousState) {
-                        point.graphic.removeClass('highcharts-point-' + previousState);
-                    }
-                    if (state) {
-                        point.graphic.addClass('highcharts-point-' + state);
-                    }
-                    if (!chart.styledMode) {
-                        pointAttribs = series.pointAttribs(point, state);
-                        pointAttribsAnimation = pick(chart.options.chart.animation, stateOptions.animation);
-                        // Some inactive points (e.g. slices in pie) should apply
-                        // oppacity also for it's labels
-                        if (series.options.inactiveOtherPoints && pointAttribs.opacity) {
-                            (point.dataLabels || []).forEach(function (label) {
-                                if (label) {
-                                    label.animate({
-                                        opacity: pointAttribs.opacity
-                                    }, pointAttribsAnimation);
-                                }
-                            });
-                            if (point.connector) {
-                                point.connector.animate({
-                                    opacity: pointAttribs.opacity
-                                }, pointAttribsAnimation);
-                            }
-                        }
-                        point.graphic.animate(pointAttribs, pointAttribsAnimation);
-                    }
-                    if (markerAttribs) {
-                        point.graphic.animate(markerAttribs, pick(
-                        // Turn off globally:
-                        chart.options.chart.animation, markerStateOptions.animation, markerOptions.animation));
-                    }
-                    // Zooming in from a range with no markers to a range with markers
-                    if (stateMarkerGraphic) {
-                        stateMarkerGraphic.hide();
-                    }
-                }
-                else {
-                    // if a graphic is not applied to each point in the normal state,
-                    // create a shared graphic for the hover state
-                    if (state && markerStateOptions) {
-                        newSymbol = pointMarker.symbol || series.symbol;
-                        // If the point has another symbol than the previous one, throw
-                        // away the state marker graphic and force a new one (#1459)
-                        if (stateMarkerGraphic &&
-                            stateMarkerGraphic.currentSymbol !== newSymbol) {
-                            stateMarkerGraphic = stateMarkerGraphic.destroy();
-                        }
-                        // Add a new state marker graphic
-                        if (markerAttribs) {
-                            if (!stateMarkerGraphic) {
-                                if (newSymbol) {
-                                    series.stateMarkerGraphic = stateMarkerGraphic =
-                                        chart.renderer
-                                            .symbol(newSymbol, markerAttribs.x, markerAttribs.y, markerAttribs.width, markerAttribs.height)
-                                            .add(series.markerGroup);
-                                    stateMarkerGraphic.currentSymbol = newSymbol;
-                                }
-                                // Move the existing graphic
-                            }
-                            else {
-                                stateMarkerGraphic[move ? 'animate' : 'attr']({
-                                    x: markerAttribs.x,
-                                    y: markerAttribs.y
-                                });
-                            }
-                        }
-                        if (!chart.styledMode && stateMarkerGraphic) {
-                            stateMarkerGraphic.attr(series.pointAttribs(point, state));
-                        }
-                    }
-                    if (stateMarkerGraphic) {
-                        stateMarkerGraphic[state && point.isInside ? 'show' : 'hide'](); // #2450
-                        stateMarkerGraphic.element.point = point; // #4310
-                    }
-                }
-                // Show me your halo
-                haloOptions = stateOptions.halo;
-                var markerGraphic = (point.graphic || stateMarkerGraphic);
-                var markerVisibility = (markerGraphic && markerGraphic.visibility || 'inherit');
-                if (haloOptions &&
-                    haloOptions.size &&
-                    markerGraphic &&
-                    markerVisibility !== 'hidden' &&
-                    !point.isCluster) {
-                    if (!halo) {
-                        series.halo = halo = chart.renderer.path()
-                            // #5818, #5903, #6705
-                            .add(markerGraphic.parentGroup);
-                    }
-                    halo.show()[move ? 'animate' : 'attr']({
-                        d: point.haloPath(haloOptions.size)
-                    });
-                    halo.attr({
-                        'class': 'highcharts-halo highcharts-color-' +
-                            pick(point.colorIndex, series.colorIndex) +
-                            (point.className ? ' ' + point.className : ''),
-                        'visibility': markerVisibility,
-                        'zIndex': -1 // #4929, #8276
-                    });
-                    halo.point = point; // #6055
-                    if (!chart.styledMode) {
-                        halo.attr(extend({
-                            'fill': point.color || series.color,
-                            'fill-opacity': haloOptions.opacity
-                        }, haloOptions.attributes));
-                    }
-                }
-                else if (halo && halo.point && halo.point.haloPath) {
-                    // Animate back to 0 on the current halo point (#6055)
-                    halo.animate({ d: halo.point.haloPath(0) }, null, 
-                    // Hide after unhovering. The `complete` callback runs in the
-                    // halo's context (#7681).
-                    halo.hide);
-                }
-                fireEvent(point, 'afterSetState');
-            },
+              });
+            }
+          },
+          /* eslint-enable valid-jsdoc */
+        }
+      );
+      /* eslint-disable no-invalid-this */
+      addEvent(Series, "afterTranslate", function () {
+        if (this.applyJitter) {
+          this.applyJitter();
+        }
+      });
+      /* eslint-enable no-invalid-this */
+      /**
+       * A `scatter` series. If the [type](#series.scatter.type) option is
+       * not specified, it is inherited from [chart.type](#chart.type).
+       *
+       * @extends   series,plotOptions.scatter
+       * @excluding cropThreshold, dataParser, dataURL, useOhlcData
+       * @product   highcharts highstock
+       * @apioption series.scatter
+       */
+      /**
+       * An array of data points for the series. For the `scatter` series
+       * type, points can be given in the following ways:
+       *
+       * 1. An array of numerical values. In this case, the numerical values will be
+       *    interpreted as `y` options. The `x` values will be automatically
+       *    calculated, either starting at 0 and incremented by 1, or from
+       *    `pointStart` and `pointInterval` given in the series options. If the axis
+       *    has categories, these will be used. Example:
+       *    ```js
+       *    data: [0, 5, 3, 5]
+       *    ```
+       *
+       * 2. An array of arrays with 2 values. In this case, the values correspond to
+       *    `x,y`. If the first value is a string, it is applied as the name of the
+       *    point, and the `x` value is inferred.
+       *    ```js
+       *    data: [
+       *        [0, 0],
+       *        [1, 8],
+       *        [2, 9]
+       *    ]
+       *    ```
+       *
+       * 3. An array of objects with named values. The following snippet shows only a
+       *    few settings, see the complete options set below. If the total number of
+       *    data points exceeds the series'
+       *    [turboThreshold](#series.scatter.turboThreshold), this option is not
+       *    available.
+       *    ```js
+       *    data: [{
+       *        x: 1,
+       *        y: 2,
+       *        name: "Point2",
+       *        color: "#00FF00"
+       *    }, {
+       *        x: 1,
+       *        y: 4,
+       *        name: "Point1",
+       *        color: "#FF00FF"
+       *    }]
+       *    ```
+       *
+       * @sample {highcharts} highcharts/chart/reflow-true/
+       *         Numerical values
+       * @sample {highcharts} highcharts/series/data-array-of-arrays/
+       *         Arrays of numeric x and y
+       * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
+       *         Arrays of datetime x and y
+       * @sample {highcharts} highcharts/series/data-array-of-name-value/
+       *         Arrays of point.name and y
+       * @sample {highcharts} highcharts/series/data-array-of-objects/
+       *         Config objects
+       *
+       * @type      {Array<number|Array<(number|string),(number|null)>|null|*>}
+       * @extends   series.line.data
+       * @product   highcharts highstock
+       * @apioption series.scatter.data
+       */
+      (""); // adds doclets above to transpilat
+    }
+  );
+  _registerModule(
+    _modules,
+    "Mixins/CenteredSeries.js",
+    [_modules["Core/Globals.js"], _modules["Core/Utilities.js"]],
+    function (H, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      /**
+       * @private
+       * @interface Highcharts.RadianAngles
+       */ /**
+       * @name Highcharts.RadianAngles#end
+       * @type {number}
+       */ /**
+       * @name Highcharts.RadianAngles#start
+       * @type {number}
+       */
+      var isNumber = U.isNumber,
+        pick = U.pick,
+        relativeLength = U.relativeLength;
+      var deg2rad = H.deg2rad;
+      /* eslint-disable valid-jsdoc */
+      /**
+       * @private
+       * @mixin Highcharts.CenteredSeriesMixin
+       */
+      var centeredSeriesMixin = (H.CenteredSeriesMixin = {
+        /**
+         * Get the center of the pie based on the size and center options relative
+         * to the plot area. Borrowed by the polar and gauge series types.
+         *
+         * @private
+         * @function Highcharts.CenteredSeriesMixin.getCenter
+         *
+         * @return {Array<number>}
+         */
+        getCenter: function () {
+          var options = this.options,
+            chart = this.chart,
+            slicingRoom = 2 * (options.slicedOffset || 0),
+            handleSlicingRoom,
+            plotWidth = chart.plotWidth - 2 * slicingRoom,
+            plotHeight = chart.plotHeight - 2 * slicingRoom,
+            centerOption = options.center,
+            smallestSize = Math.min(plotWidth, plotHeight),
+            size = options.size,
+            innerSize = options.innerSize || 0,
+            positions,
+            i,
+            value;
+          if (typeof size === "string") {
+            size = parseFloat(size);
+          }
+          if (typeof innerSize === "string") {
+            innerSize = parseFloat(innerSize);
+          }
+          positions = [
+            pick(centerOption[0], "50%"),
+            pick(centerOption[1], "50%"),
+            // Prevent from negative values
+            pick(size && size < 0 ? void 0 : options.size, "100%"),
+            pick(
+              innerSize && innerSize < 0 ? void 0 : options.innerSize || 0,
+              "0%"
+            ),
+          ];
+          // No need for inner size in angular (gauges) series but still required
+          // for pie series
+          if (chart.angular && !(this instanceof H.Series)) {
+            positions[3] = 0;
+          }
+          for (i = 0; i < 4; ++i) {
+            value = positions[i];
+            handleSlicingRoom = i < 2 || (i === 2 && /%$/.test(value));
+            // i == 0: centerX, relative to width
+            // i == 1: centerY, relative to height
+            // i == 2: size, relative to smallestSize
+            // i == 3: innerSize, relative to size
+            positions[i] =
+              relativeLength(
+                value,
+                [plotWidth, plotHeight, smallestSize, positions[2]][i]
+              ) + (handleSlicingRoom ? slicingRoom : 0);
+          }
+          // innerSize cannot be larger than size (#3632)
+          if (positions[3] > positions[2]) {
+            positions[3] = positions[2];
+          }
+          return positions;
+        },
+        /**
+         * getStartAndEndRadians - Calculates start and end angles in radians.
+         * Used in series types such as pie and sunburst.
+         *
+         * @private
+         * @function Highcharts.CenteredSeriesMixin.getStartAndEndRadians
+         *
+         * @param {number} [start]
+         *        Start angle in degrees.
+         *
+         * @param {number} [end]
+         *        Start angle in degrees.
+         *
+         * @return {Highcharts.RadianAngles}
+         *         Returns an object containing start and end angles as radians.
+         */
+        getStartAndEndRadians: function (start, end) {
+          var startAngle = isNumber(start) ? start : 0, // must be a number
+            endAngle =
+              isNumber(end) && // must be a number
+              end > startAngle && // must be larger than the start angle
+              // difference must be less than 360 degrees
+              end - startAngle < 360
+                ? end
+                : startAngle + 360,
+            correction = -90;
+          return {
+            start: deg2rad * (startAngle + correction),
+            end: deg2rad * (endAngle + correction),
+          };
+        },
+      });
+
+      return centeredSeriesMixin;
+    }
+  );
+  _registerModule(
+    _modules,
+    "Series/PieSeries.js",
+    [
+      _modules["Core/Animation/AnimationUtilities.js"],
+      _modules["Core/Series/Series.js"],
+      _modules["Mixins/CenteredSeries.js"],
+      _modules["Core/Globals.js"],
+      _modules["Mixins/LegendSymbol.js"],
+      _modules["Series/LineSeries.js"],
+      _modules["Core/Series/Point.js"],
+      _modules["Core/Renderer/SVG/SVGRenderer.js"],
+      _modules["Core/Utilities.js"],
+    ],
+    function (
+      A,
+      BaseSeries,
+      CenteredSeriesMixin,
+      H,
+      LegendSymbolMixin,
+      LineSeries,
+      Point,
+      SVGRenderer,
+      U
+    ) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      var setAnimation = A.setAnimation;
+      var getStartAndEndRadians = CenteredSeriesMixin.getStartAndEndRadians;
+      var noop = H.noop;
+      var addEvent = U.addEvent,
+        clamp = U.clamp,
+        defined = U.defined,
+        fireEvent = U.fireEvent,
+        isNumber = U.isNumber,
+        merge = U.merge,
+        pick = U.pick,
+        relativeLength = U.relativeLength;
+      /**
+       * Pie series type.
+       *
+       * @private
+       * @class
+       * @name Highcharts.seriesTypes.pie
+       *
+       * @augments Highcharts.Series
+       */
+      BaseSeries.seriesType(
+        "pie",
+        "line",
+        /**
+         * A pie chart is a circular graphic which is divided into slices to
+         * illustrate numerical proportion.
+         *
+         * @sample highcharts/demo/pie-basic/
+         *         Pie chart
+         *
+         * @extends      plotOptions.line
+         * @excluding    animationLimit, boostThreshold, connectEnds, connectNulls,
+         *               cropThreshold, dashStyle, dataSorting, dragDrop,
+         *               findNearestPointBy, getExtremesFromAll, label, lineWidth,
+         *               marker, negativeColor, pointInterval, pointIntervalUnit,
+         *               pointPlacement, pointStart, softThreshold, stacking, step,
+         *               threshold, turboThreshold, zoneAxis, zones, dataSorting,
+         *               boostBlending
+         * @product      highcharts
+         * @optionparent plotOptions.pie
+         */
+        {
+          /**
+           * @excluding legendItemClick
+           * @apioption plotOptions.pie.events
+           */
+          /**
+           * Fires when the checkbox next to the point name in the legend is
+           * clicked. One parameter, event, is passed to the function. The state
+           * of the checkbox is found by event.checked. The checked item is found
+           * by event.item. Return false to prevent the default action which is to
+           * toggle the select state of the series.
+           *
+           * @sample {highcharts} highcharts/plotoptions/series-events-checkboxclick/
+           *         Alert checkbox status
+           *
+           * @type      {Function}
+           * @since     1.2.0
+           * @product   highcharts
+           * @context   Highcharts.Point
+           * @apioption plotOptions.pie.events.checkboxClick
+           */
+          /**
+           * Fires when the legend item belonging to the pie point (slice) is
+           * clicked. The `this` keyword refers to the point itself. One
+           * parameter, `event`, is passed to the function, containing common
+           * event information. The default action is to toggle the visibility of
+           * the point. This can be prevented by calling `event.preventDefault()`.
+           *
+           * @sample {highcharts} highcharts/plotoptions/pie-point-events-legenditemclick/
+           *         Confirm toggle visibility
+           *
+           * @type      {Highcharts.PointLegendItemClickCallbackFunction}
+           * @since     1.2.0
+           * @product   highcharts
+           * @apioption plotOptions.pie.point.events.legendItemClick
+           */
+          /**
+           * The center of the pie chart relative to the plot area. Can be
+           * percentages or pixel values. The default behaviour (as of 3.0) is to
+           * center the pie so that all slices and data labels are within the plot
+           * area. As a consequence, the pie may actually jump around in a chart
+           * with dynamic values, as the data labels move. In that case, the
+           * center should be explicitly set, for example to `["50%", "50%"]`.
+           *
+           * @sample {highcharts} highcharts/plotoptions/pie-center/
+           *         Centered at 100, 100
+           *
+           * @type    {Array<(number|string|null),(number|string|null)>}
+           * @default [null, null]
+           * @product highcharts
+           *
+           * @private
+           */
+          center: [null, null],
+          /**
+           * The color of the pie series. A pie series is represented as an empty
+           * circle if the total sum of its values is 0. Use this property to
+           * define the color of its border.
+           *
+           * In styled mode, the color can be defined by the
+           * [colorIndex](#plotOptions.series.colorIndex) option. Also, the series
+           * color can be set with the `.highcharts-series`,
+           * `.highcharts-color-{n}`, `.highcharts-{type}-series` or
+           * `.highcharts-series-{n}` class, or individual classes given by the
+           * `className` option.
+           *
+           * @sample {highcharts} highcharts/plotoptions/pie-emptyseries/
+           *         Empty pie series
+           *
+           * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+           * @default   #cccccc
+           * @apioption plotOptions.pie.color
+           */
+          /**
+           * @product highcharts
+           *
+           * @private
+           */
+          clip: false,
+          /**
+           * @ignore-option
+           *
+           * @private
+           */
+          colorByPoint: true,
+          /**
+           * A series specific or series type specific color set to use instead
+           * of the global [colors](#colors).
+           *
+           * @sample {highcharts} highcharts/demo/pie-monochrome/
+           *         Set default colors for all pies
+           *
+           * @type      {Array<Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject>}
+           * @since     3.0
+           * @product   highcharts
+           * @apioption plotOptions.pie.colors
+           */
+          /**
+           * @declare   Highcharts.SeriesPieDataLabelsOptionsObject
+           * @extends   plotOptions.series.dataLabels
+           * @excluding align, allowOverlap, inside, staggerLines, step
+           * @private
+           */
+          dataLabels: {
+            /**
+             * Alignment method for data labels. Possible values are:
+             *
+             * - `toPlotEdges`: Each label touches the nearest vertical edge of
+             *   the plot area.
+             *
+             * - `connectors`: Connectors have the same x position and the
+             *   widest label of each half (left & right) touches the nearest
+             *   vertical edge of the plot area.
+             *
+             * @sample {highcharts} highcharts/plotoptions/pie-datalabels-alignto-connectors/
+             *         alignTo: connectors
+             * @sample {highcharts} highcharts/plotoptions/pie-datalabels-alignto-plotedges/
+             *         alignTo: plotEdges
+             *
+             * @type      {string}
+             * @since     7.0.0
+             * @product   highcharts
+             * @apioption plotOptions.pie.dataLabels.alignTo
+             */
+            allowOverlap: true,
             /**
-             * Get the path definition for the halo, which is usually a shadow-like
-             * circle around the currently hovered point.
+             * The color of the line connecting the data label to the pie slice.
+             * The default color is the same as the point's color.
              *
-             * @function Highcharts.Point#haloPath
+             * In styled mode, the connector stroke is given in the
+             * `.highcharts-data-label-connector` class.
              *
-             * @param {number} size
-             *        The radius of the circular halo.
+             * @sample {highcharts} highcharts/plotoptions/pie-datalabels-connectorcolor/
+             *         Blue connectors
+             * @sample {highcharts} highcharts/css/pie-point/
+             *         Styled connectors
              *
-             * @return {Highcharts.SVGPathArray}
-             *         The path definition.
+             * @type      {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+             * @since     2.1
+             * @product   highcharts
+             * @apioption plotOptions.pie.dataLabels.connectorColor
              */
-            haloPath: function (size) {
-                var series = this.series,
-                    chart = series.chart;
-                return chart.renderer.symbols.circle(Math.floor(this.plotX) - size, this.plotY - size, size * 2, size * 2);
-            }
-        });
-        // Extend the Series object with interaction
-        extend(LineSeries.prototype, /** @lends Highcharts.Series.prototype */ {
             /**
-             * Runs on mouse over the series graphical items.
+             * The distance from the data label to the connector. Note that
+             * data labels also have a default `padding`, so in order for the
+             * connector to touch the text, the `padding` must also be 0.
              *
-             * @function Highcharts.Series#onMouseOver
-             * @fires Highcharts.Series#event:mouseOver
+             * @sample {highcharts} highcharts/plotoptions/pie-datalabels-connectorpadding/
+             *         No padding
+             *
+             * @since   2.1
+             * @product highcharts
              */
-            onMouseOver: function () {
-                var series = this,
-                    chart = series.chart,
-                    hoverSeries = chart.hoverSeries,
-                    pointer = chart.pointer;
-                pointer.setHoverChartIndex();
-                // set normal state to previous series
-                if (hoverSeries && hoverSeries !== series) {
-                    hoverSeries.onMouseOut();
-                }
-                // trigger the event, but to save processing time,
-                // only if defined
-                if (series.options.events.mouseOver) {
-                    fireEvent(series, 'mouseOver');
-                }
-                // hover this
-                series.setState('hover');
-                /**
-                 * Contains the original hovered series.
-                 *
-                 * @name Highcharts.Chart#hoverSeries
-                 * @type {Highcharts.Series|null}
-                 */
-                chart.hoverSeries = series;
-            },
+            connectorPadding: 5,
             /**
-             * Runs on mouse out of the series graphical items.
+             * Specifies the method that is used to generate the connector path.
+             * Highcharts provides 3 built-in connector shapes: `'fixedOffset'`
+             * (default), `'straight'` and `'crookedLine'`. Using
+             * `'crookedLine'` has the most sense (in most of the cases) when
+             * `'alignTo'` is set.
              *
-             * @function Highcharts.Series#onMouseOut
+             * Users can provide their own method by passing a function instead
+             * of a String. 3 arguments are passed to the callback:
              *
-             * @fires Highcharts.Series#event:mouseOut
-             */
-            onMouseOut: function () {
-                // trigger the event only if listeners exist
-                var series = this,
-                    options = series.options,
-                    chart = series.chart,
-                    tooltip = chart.tooltip,
-                    hoverPoint = chart.hoverPoint;
-                // #182, set to null before the mouseOut event fires
-                chart.hoverSeries = null;
-                // trigger mouse out on the point, which must be in this series
-                if (hoverPoint) {
-                    hoverPoint.onMouseOut();
-                }
-                // fire the mouse out event
-                if (series && options.events.mouseOut) {
-                    fireEvent(series, 'mouseOut');
-                }
-                // hide the tooltip
-                if (tooltip &&
-                    !series.stickyTracking &&
-                    (!tooltip.shared || series.noSharedTooltip)) {
-                    tooltip.hide();
-                }
-                // Reset all inactive states
-                chart.series.forEach(function (s) {
-                    s.setState('', true);
-                });
-            },
-            /**
-             * Set the state of the series. Called internally on mouse interaction
-             * operations, but it can also be called directly to visually
-             * highlight a series.
-             *
-             * @function Highcharts.Series#setState
-             *
-             * @param {Highcharts.SeriesStateValue|""} [state]
-             *        The new state, can be either `'hover'`, `'inactive'`, `'select'`,
-             *        or `''` (an empty string), `'normal'` or `undefined` to set to
-             *        normal state.
-             * @param {boolean} [inherit]
-             *        Determines if state should be inherited by points too.
+             * - Object that holds the information about the coordinates of the
+             *   label (`x` & `y` properties) and how the label is located in
+             *   relation to the pie (`alignment` property). `alignment` can by
+             *   one of the following:
+             *   `'left'` (pie on the left side of the data label),
+             *   `'right'` (pie on the right side of the data label) or
+             *   `'center'` (data label overlaps the pie).
+             *
+             * - Object that holds the information about the position of the
+             *   connector. Its `touchingSliceAt`  porperty tells the position
+             *   of the place where the connector touches the slice.
+             *
+             * - Data label options
+             *
+             * The function has to return an SVG path definition in array form
+             * (see the example).
+             *
+             * @sample {highcharts} highcharts/plotoptions/pie-datalabels-connectorshape-string/
+             *         connectorShape is a String
+             * @sample {highcharts} highcharts/plotoptions/pie-datalabels-connectorshape-function/
+             *         connectorShape is a function
+             *
+             * @type    {string|Function}
+             * @since   7.0.0
+             * @product highcharts
              */
-            setState: function (state, inherit) {
-                var series = this,
-                    options = series.options,
-                    graph = series.graph,
-                    inactiveOtherPoints = options.inactiveOtherPoints,
-                    stateOptions = options.states,
-                    lineWidth = options.lineWidth,
-                    opacity = options.opacity, 
-                    // By default a quick animation to hover/inactive,
-                    // slower to un-hover
-                    stateAnimation = pick((stateOptions[state || 'normal'] &&
-                        stateOptions[state || 'normal'].animation),
-                    series.chart.options.chart.animation),
-                    attribs,
-                    i = 0;
-                state = state || '';
-                if (series.state !== state) {
-                    // Toggle class names
-                    [
-                        series.group,
-                        series.markerGroup,
-                        series.dataLabelsGroup
-                    ].forEach(function (group) {
-                        if (group) {
-                            // Old state
-                            if (series.state) {
-                                group.removeClass('highcharts-series-' + series.state);
-                            }
-                            // New state
-                            if (state) {
-                                group.addClass('highcharts-series-' + state);
-                            }
-                        }
-                    });
-                    series.state = state;
-                    if (!series.chart.styledMode) {
-                        if (stateOptions[state] &&
-                            stateOptions[state].enabled === false) {
-                            return;
-                        }
-                        if (state) {
-                            lineWidth = (stateOptions[state].lineWidth ||
-                                lineWidth + (stateOptions[state].lineWidthPlus || 0)); // #4035
-                            opacity = pick(stateOptions[state].opacity, opacity);
-                        }
-                        if (graph && !graph.dashstyle) {
-                            attribs = {
-                                'stroke-width': lineWidth
-                            };
-                            // Animate the graph stroke-width.
-                            graph.animate(attribs, stateAnimation);
-                            while (series['zone-graph-' + i]) {
-                                series['zone-graph-' + i].attr(attribs);
-                                i = i + 1;
-                            }
-                        }
-                        // For some types (pie, networkgraph, sankey) opacity is
-                        // resolved on a point level
-                        if (!inactiveOtherPoints) {
-                            [
-                                series.group,
-                                series.markerGroup,
-                                series.dataLabelsGroup,
-                                series.labelBySeries
-                            ].forEach(function (group) {
-                                if (group) {
-                                    group.animate({
-                                        opacity: opacity
-                                    }, stateAnimation);
-                                }
-                            });
-                        }
-                    }
-                }
-                // Don't loop over points on a series that doesn't apply inactive state
-                // to siblings markers (e.g. line, column)
-                if (inherit && inactiveOtherPoints && series.points) {
-                    series.setAllPointsToState(state);
-                }
-            },
+            connectorShape: "fixedOffset",
             /**
-             * Set the state for all points in the series.
+             * The width of the line connecting the data label to the pie slice.
              *
-             * @function Highcharts.Series#setAllPointsToState
+             * In styled mode, the connector stroke width is given in the
+             * `.highcharts-data-label-connector` class.
              *
-             * @private
+             * @sample {highcharts} highcharts/plotoptions/pie-datalabels-connectorwidth-disabled/
+             *         Disable the connector
+             * @sample {highcharts} highcharts/css/pie-point/
+             *         Styled connectors
              *
-             * @param {string} [state]
-             *        Can be either `hover` or undefined to set to normal state.
+             * @type      {number}
+             * @default   1
+             * @since     2.1
+             * @product   highcharts
+             * @apioption plotOptions.pie.dataLabels.connectorWidth
              */
-            setAllPointsToState: function (state) {
-                this.points.forEach(function (point) {
-                    if (point.setState) {
-                        point.setState(state);
-                    }
-                });
-            },
             /**
-             * Show or hide the series.
+             * Works only if `connectorShape` is `'crookedLine'`. It defines how
+             * far from the vertical plot edge the coonnector path should be
+             * crooked.
              *
-             * @function Highcharts.Series#setVisible
+             * @sample {highcharts} highcharts/plotoptions/pie-datalabels-crookdistance/
+             *         crookDistance set to 90%
              *
-             * @param {boolean} [visible]
-             * True to show the series, false to hide. If undefined, the visibility is
-             * toggled.
+             * @since   7.0.0
+             * @product highcharts
+             */
+            crookDistance: "70%",
+            /**
+             * The distance of the data label from the pie's edge. Negative
+             * numbers put the data label on top of the pie slices. Can also be
+             * defined as a percentage of pie's radius. Connectors are only
+             * shown for data labels outside the pie.
              *
-             * @param {boolean} [redraw=true]
-             * Whether to redraw the chart after the series is altered. If doing more
-             * operations on the chart, it is a good idea to set redraw to false and
-             * call {@link Chart#redraw|chart.redraw()} after.
+             * @sample {highcharts} highcharts/plotoptions/pie-datalabels-distance/
+             *         Data labels on top of the pie
              *
-             * @fires Highcharts.Series#event:hide
-             * @fires Highcharts.Series#event:show
+             * @type    {number|string}
+             * @since   2.1
+             * @product highcharts
              */
-            setVisible: function (vis, redraw) {
-                var series = this,
-                    chart = series.chart,
-                    legendItem = series.legendItem,
-                    showOrHide,
-                    ignoreHiddenSeries = chart.options.chart.ignoreHiddenSeries,
-                    oldVisibility = series.visible;
-                // if called without an argument, toggle visibility
-                series.visible =
-                    vis =
-                        series.options.visible =
-                            series.userOptions.visible =
-                                typeof vis === 'undefined' ? !oldVisibility : vis; // #5618
-                showOrHide = vis ? 'show' : 'hide';
-                // show or hide elements
-                [
-                    'group',
-                    'dataLabelsGroup',
-                    'markerGroup',
-                    'tracker',
-                    'tt'
-                ].forEach(function (key) {
-                    if (series[key]) {
-                        series[key][showOrHide]();
-                    }
-                });
-                // hide tooltip (#1361)
-                if (chart.hoverSeries === series ||
-                    (chart.hoverPoint && chart.hoverPoint.series) === series) {
-                    series.onMouseOut();
-                }
-                if (legendItem) {
-                    chart.legend.colorizeItem(series, vis);
-                }
-                // rescale or adapt to resized chart
-                series.isDirty = true;
-                // in a stack, all other series are affected
-                if (series.options.stacking) {
-                    chart.series.forEach(function (otherSeries) {
-                        if (otherSeries.options.stacking && otherSeries.visible) {
-                            otherSeries.isDirty = true;
-                        }
-                    });
-                }
-                // show or hide linked series
-                series.linkedSeries.forEach(function (otherSeries) {
-                    otherSeries.setVisible(vis, false);
-                });
-                if (ignoreHiddenSeries) {
-                    chart.isDirtyBox = true;
-                }
-                fireEvent(series, showOrHide);
-                if (redraw !== false) {
-                    chart.redraw();
-                }
-            },
+            distance: 30,
+            enabled: true,
             /**
-             * Show the series if hidden.
+             * A
+             * [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting)
+             * for the data label. Available variables are the same as for
+             * `formatter`.
              *
-             * @sample highcharts/members/series-hide/
-             *         Toggle visibility from a button
+             * @sample {highcharts} highcharts/plotoptions/series-datalabels-format/
+             *         Add a unit
              *
-             * @function Highcharts.Series#show
-             * @fires Highcharts.Series#event:show
+             * @type      {string}
+             * @default   undefined
+             * @since     3.0
+             * @apioption plotOptions.pie.dataLabels.format
              */
-            show: function () {
-                this.setVisible(true);
-            },
+            // eslint-disable-next-line valid-jsdoc
             /**
-             * Hide the series if visible. If the
-             * [chart.ignoreHiddenSeries](https://api.highcharts.com/highcharts/chart.ignoreHiddenSeries)
-             * option is true, the chart is redrawn without this series.
-             *
-             * @sample highcharts/members/series-hide/
-             *         Toggle visibility from a button
+             * Callback JavaScript function to format the data label. Note that
+             * if a `format` is defined, the format takes precedence and the
+             * formatter is ignored.
              *
-             * @function Highcharts.Series#hide
-             * @fires Highcharts.Series#event:hide
+             * @type {Highcharts.DataLabelsFormatterCallbackFunction}
+             * @default function () { return this.point.isNull ? void 0 : this.point.name; }
              */
-            hide: function () {
-                this.setVisible(false);
+            formatter: function () {
+              return this.point.isNull ? void 0 : this.point.name;
             },
             /**
-             * Select or unselect the series. This means its
-             * {@link Highcharts.Series.selected|selected}
-             * property is set, the checkbox in the legend is toggled and when selected,
-             * the series is returned by the {@link Highcharts.Chart#getSelectedSeries}
-             * function.
+             * Whether to render the connector as a soft arc or a line with
+             * sharp break. Works only if `connectorShape` equals to
+             * `fixedOffset`.
              *
-             * @sample highcharts/members/series-select/
-             *         Select a series from a button
+             * @sample {highcharts} highcharts/plotoptions/pie-datalabels-softconnector-true/
+             *         Soft
+             * @sample {highcharts} highcharts/plotoptions/pie-datalabels-softconnector-false/
+             *         Non soft
              *
-             * @function Highcharts.Series#select
-             *
-             * @param {boolean} [selected]
-             * True to select the series, false to unselect. If undefined, the selection
-             * state is toggled.
+             * @since   2.1.7
+             * @product highcharts
+             */
+            softConnector: true,
+            /**
+             * @sample {highcharts} highcharts/plotoptions/pie-datalabels-overflow
+             *         Long labels truncated with an ellipsis
+             * @sample {highcharts} highcharts/plotoptions/pie-datalabels-overflow-wrap
+             *         Long labels are wrapped
              *
-             * @fires Highcharts.Series#event:select
-             * @fires Highcharts.Series#event:unselect
+             * @type      {Highcharts.CSSObject}
+             * @apioption plotOptions.pie.dataLabels.style
+             */
+            x: 0,
+          },
+          /**
+           * If the total sum of the pie's values is 0, the series is represented
+           * as an empty circle . The `fillColor` option defines the color of that
+           * circle. Use [pie.borderWidth](#plotOptions.pie.borderWidth) to set
+           * the border thickness.
+           *
+           * @sample {highcharts} highcharts/plotoptions/pie-emptyseries/
+           *         Empty pie series
+           *
+           * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+           * @private
+           */
+          fillColor: void 0,
+          /**
+           * The end angle of the pie in degrees where 0 is top and 90 is right.
+           * Defaults to `startAngle` plus 360.
+           *
+           * @sample {highcharts} highcharts/demo/pie-semi-circle/
+           *         Semi-circle donut
+           *
+           * @type      {number}
+           * @since     1.3.6
+           * @product   highcharts
+           * @apioption plotOptions.pie.endAngle
+           */
+          /**
+           * Equivalent to [chart.ignoreHiddenSeries](#chart.ignoreHiddenSeries),
+           * this option tells whether the series shall be redrawn as if the
+           * hidden point were `null`.
+           *
+           * The default value changed from `false` to `true` with Highcharts
+           * 3.0.
+           *
+           * @sample {highcharts} highcharts/plotoptions/pie-ignorehiddenpoint/
+           *         True, the hiddden point is ignored
+           *
+           * @since   2.3.0
+           * @product highcharts
+           *
+           * @private
+           */
+          ignoreHiddenPoint: true,
+          /**
+           * @ignore-option
+           *
+           * @private
+           */
+          inactiveOtherPoints: true,
+          /**
+           * The size of the inner diameter for the pie. A size greater than 0
+           * renders a donut chart. Can be a percentage or pixel value.
+           * Percentages are relative to the pie size. Pixel values are given as
+           * integers.
+           *
+           *
+           * Note: in Highcharts < 4.1.2, the percentage was relative to the plot
+           * area, not the pie size.
+           *
+           * @sample {highcharts} highcharts/plotoptions/pie-innersize-80px/
+           *         80px inner size
+           * @sample {highcharts} highcharts/plotoptions/pie-innersize-50percent/
+           *         50% of the plot area
+           * @sample {highcharts} highcharts/demo/3d-pie-donut/
+           *         3D donut
+           *
+           * @type      {number|string}
+           * @default   0
+           * @since     2.0
+           * @product   highcharts
+           * @apioption plotOptions.pie.innerSize
+           */
+          /**
+           * @ignore-option
+           *
+           * @private
+           */
+          legendType: "point",
+          /**
+           * @ignore-option
+           *
+           * @private
+           */
+          marker: null,
+          /**
+           * The minimum size for a pie in response to auto margins. The pie will
+           * try to shrink to make room for data labels in side the plot area,
+           *  but only to this size.
+           *
+           * @type      {number|string}
+           * @default   80
+           * @since     3.0
+           * @product   highcharts
+           * @apioption plotOptions.pie.minSize
+           */
+          /**
+           * The diameter of the pie relative to the plot area. Can be a
+           * percentage or pixel value. Pixel values are given as integers. The
+           * default behaviour (as of 3.0) is to scale to the plot area and give
+           * room for data labels within the plot area.
+           * [slicedOffset](#plotOptions.pie.slicedOffset) is also included in the
+           * default size calculation. As a consequence, the size of the pie may
+           * vary when points are updated and data labels more around. In that
+           * case it is best to set a fixed value, for example `"75%"`.
+           *
+           * @sample {highcharts} highcharts/plotoptions/pie-size/
+           *         Smaller pie
+           *
+           * @type    {number|string|null}
+           * @product highcharts
+           *
+           * @private
+           */
+          size: null,
+          /**
+           * Whether to display this particular series or series type in the
+           * legend. Since 2.1, pies are not shown in the legend by default.
+           *
+           * @sample {highcharts} highcharts/plotoptions/series-showinlegend/
+           *         One series in the legend, one hidden
+           *
+           * @product highcharts
+           *
+           * @private
+           */
+          showInLegend: false,
+          /**
+           * If a point is sliced, moved out from the center, how many pixels
+           * should it be moved?.
+           *
+           * @sample {highcharts} highcharts/plotoptions/pie-slicedoffset-20/
+           *         20px offset
+           *
+           * @product highcharts
+           *
+           * @private
+           */
+          slicedOffset: 10,
+          /**
+           * The start angle of the pie slices in degrees where 0 is top and 90
+           * right.
+           *
+           * @sample {highcharts} highcharts/plotoptions/pie-startangle-90/
+           *         Start from right
+           *
+           * @type      {number}
+           * @default   0
+           * @since     2.3.4
+           * @product   highcharts
+           * @apioption plotOptions.pie.startAngle
+           */
+          /**
+           * Sticky tracking of mouse events. When true, the `mouseOut` event
+           * on a series isn't triggered until the mouse moves over another
+           * series, or out of the plot area. When false, the `mouseOut` event on
+           * a series is triggered when the mouse leaves the area around the
+           * series'  graph or markers. This also implies the tooltip. When
+           * `stickyTracking` is false and `tooltip.shared` is false, the tooltip
+           * will be hidden when moving the mouse between series.
+           *
+           * @product highcharts
+           *
+           * @private
+           */
+          stickyTracking: false,
+          tooltip: {
+            followPointer: true,
+          },
+          /**
+           * The color of the border surrounding each slice. When `null`, the
+           * border takes the same color as the slice fill. This can be used
+           * together with a `borderWidth` to fill drawing gaps created by
+           * antialiazing artefacts in borderless pies.
+           *
+           * In styled mode, the border stroke is given in the `.highcharts-point`
+           * class.
+           *
+           * @sample {highcharts} highcharts/plotoptions/pie-bordercolor-black/
+           *         Black border
+           *
+           * @type    {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
+           * @default #ffffff
+           * @product highcharts
+           *
+           * @private
+           */
+          borderColor: "#ffffff",
+          /**
+           * The width of the border surrounding each slice.
+           *
+           * When setting the border width to 0, there may be small gaps between
+           * the slices due to SVG antialiasing artefacts. To work around this,
+           * keep the border width at 0.5 or 1, but set the `borderColor` to
+           * `null` instead.
+           *
+           * In styled mode, the border stroke width is given in the
+           * `.highcharts-point` class.
+           *
+           * @sample {highcharts} highcharts/plotoptions/pie-borderwidth/
+           *         3px border
+           *
+           * @product highcharts
+           *
+           * @private
+           */
+          borderWidth: 1,
+          /**
+           * @ignore-options
+           * @private
+           */
+          lineWidth: void 0,
+          states: {
+            /**
+             * @extends   plotOptions.series.states.hover
+             * @excluding marker, lineWidth, lineWidthPlus
+             * @product   highcharts
              */
-            select: function (selected) {
-                var series = this;
-                series.selected =
-                    selected =
-                        this.options.selected = (typeof selected === 'undefined' ?
-                            !series.selected :
-                            selected);
-                if (series.checkbox) {
-                    series.checkbox.checked = selected;
+            hover: {
+              /**
+               * How much to brighten the point on interaction. Requires the
+               * main color to be defined in hex or rgb(a) format.
+               *
+               * In styled mode, the hover brightness is by default replaced
+               * by a fill-opacity given in the `.highcharts-point-hover`
+               * class.
+               *
+               * @sample {highcharts} highcharts/plotoptions/pie-states-hover-brightness/
+               *         Brightened by 0.5
+               *
+               * @product highcharts
+               */
+              brightness: 0.1,
+            },
+          },
+        },
+        /* eslint-disable valid-jsdoc */
+        /**
+         * @lends seriesTypes.pie.prototype
+         */
+        {
+          isCartesian: false,
+          requireSorting: false,
+          directTouch: true,
+          noSharedTooltip: true,
+          trackerGroups: ["group", "dataLabelsGroup"],
+          axisTypes: [],
+          pointAttribs: BaseSeries.seriesTypes.column.prototype.pointAttribs,
+          /**
+           * Animate the pies in
+           *
+           * @private
+           * @function Highcharts.seriesTypes.pie#animate
+           *
+           * @param {boolean} [init=false]
+           */
+          animate: function (init) {
+            var series = this,
+              points = series.points,
+              startAngleRad = series.startAngleRad;
+            if (!init) {
+              points.forEach(function (point) {
+                var graphic = point.graphic,
+                  args = point.shapeArgs;
+                if (graphic && args) {
+                  // start values
+                  graphic.attr({
+                    // animate from inner radius (#779)
+                    r: pick(
+                      point.startR,
+                      series.center && series.center[3] / 2
+                    ),
+                    start: startAngleRad,
+                    end: startAngleRad,
+                  });
+                  // animate
+                  graphic.animate(
+                    {
+                      r: args.r,
+                      start: args.start,
+                      end: args.end,
+                    },
+                    series.options.animation
+                  );
                 }
-                fireEvent(series, selected ? 'select' : 'unselect');
+              });
+            }
+          },
+          // Define hasData function for non-cartesian series.
+          // Returns true if the series has points at all.
+          hasData: function () {
+            return !!this.processedXData.length; // != 0
+          },
+          /**
+           * Recompute total chart sum and update percentages of points.
+           *
+           * @private
+           * @function Highcharts.seriesTypes.pie#updateTotals
+           * @return {void}
+           */
+          updateTotals: function () {
+            var i,
+              total = 0,
+              points = this.points,
+              len = points.length,
+              point,
+              ignoreHiddenPoint = this.options.ignoreHiddenPoint;
+            // Get the total sum
+            for (i = 0; i < len; i++) {
+              point = points[i];
+              total +=
+                ignoreHiddenPoint && !point.visible
+                  ? 0
+                  : point.isNull
+                  ? 0
+                  : point.y;
+            }
+            this.total = total;
+            // Set each point's properties
+            for (i = 0; i < len; i++) {
+              point = points[i];
+              point.percentage =
+                total > 0 && (point.visible || !ignoreHiddenPoint)
+                  ? (point.y / total) * 100
+                  : 0;
+              point.total = total;
+            }
+          },
+          /**
+           * Extend the generatePoints method by adding total and percentage
+           * properties to each point
+           *
+           * @private
+           * @function Highcharts.seriesTypes.pie#generatePoints
+           * @return {void}
+           */
+          generatePoints: function () {
+            LineSeries.prototype.generatePoints.call(this);
+            this.updateTotals();
+          },
+          /**
+           * Utility for getting the x value from a given y, used for
+           * anticollision logic in data labels. Added point for using specific
+           * points' label distance.
+           * @private
+           */
+          getX: function (y, left, point) {
+            var center = this.center,
+              // Variable pie has individual radius
+              radius = this.radii ? this.radii[point.index] : center[2] / 2,
+              angle,
+              x;
+            angle = Math.asin(
+              clamp((y - center[1]) / (radius + point.labelDistance), -1, 1)
+            );
+            x =
+              center[0] +
+              (left ? -1 : 1) *
+                (Math.cos(angle) * (radius + point.labelDistance)) +
+              (point.labelDistance > 0
+                ? (left ? -1 : 1) * this.options.dataLabels.padding
+                : 0);
+            return x;
+          },
+          /**
+           * Do translation for pie slices
+           *
+           * @private
+           * @function Highcharts.seriesTypes.pie#translate
+           * @param {Array<number>} [positions]
+           * @return {void}
+           */
+          translate: function (positions) {
+            this.generatePoints();
+            var series = this,
+              cumulative = 0,
+              precision = 1000, // issue #172
+              options = series.options,
+              slicedOffset = options.slicedOffset,
+              connectorOffset = slicedOffset + (options.borderWidth || 0),
+              finalConnectorOffset,
+              start,
+              end,
+              angle,
+              radians = getStartAndEndRadians(
+                options.startAngle,
+                options.endAngle
+              ),
+              startAngleRad = (series.startAngleRad = radians.start),
+              endAngleRad = (series.endAngleRad = radians.end),
+              circ = endAngleRad - startAngleRad, // 2 * Math.PI,
+              points = series.points,
+              // the x component of the radius vector for a given point
+              radiusX,
+              radiusY,
+              labelDistance = options.dataLabels.distance,
+              ignoreHiddenPoint = options.ignoreHiddenPoint,
+              i,
+              len = points.length,
+              point;
+            // Get positions - either an integer or a percentage string must be
+            // given. If positions are passed as a parameter, we're in a
+            // recursive loop for adjusting space for data labels.
+            if (!positions) {
+              series.center = positions = series.getCenter();
+            }
+            // Calculate the geometry for each point
+            for (i = 0; i < len; i++) {
+              point = points[i];
+              // set start and end angle
+              start = startAngleRad + cumulative * circ;
+              if (!ignoreHiddenPoint || point.visible) {
+                cumulative += point.percentage / 100;
+              }
+              end = startAngleRad + cumulative * circ;
+              // set the shape
+              point.shapeType = "arc";
+              point.shapeArgs = {
+                x: positions[0],
+                y: positions[1],
+                r: positions[2] / 2,
+                innerR: positions[3] / 2,
+                start: Math.round(start * precision) / precision,
+                end: Math.round(end * precision) / precision,
+              };
+              // Used for distance calculation for specific point.
+              point.labelDistance = pick(
+                point.options.dataLabels && point.options.dataLabels.distance,
+                labelDistance
+              );
+              // Compute point.labelDistance if it's defined as percentage
+              // of slice radius (#8854)
+              point.labelDistance = relativeLength(
+                point.labelDistance,
+                point.shapeArgs.r
+              );
+              // Saved for later dataLabels distance calculation.
+              series.maxLabelDistance = Math.max(
+                series.maxLabelDistance || 0,
+                point.labelDistance
+              );
+              // The angle must stay within -90 and 270 (#2645)
+              angle = (end + start) / 2;
+              if (angle > 1.5 * Math.PI) {
+                angle -= 2 * Math.PI;
+              } else if (angle < -Math.PI / 2) {
+                angle += 2 * Math.PI;
+              }
+              // Center for the sliced out slice
+              point.slicedTranslation = {
+                translateX: Math.round(Math.cos(angle) * slicedOffset),
+                translateY: Math.round(Math.sin(angle) * slicedOffset),
+              };
+              // set the anchor point for tooltips
+              radiusX = (Math.cos(angle) * positions[2]) / 2;
+              radiusY = (Math.sin(angle) * positions[2]) / 2;
+              point.tooltipPos = [
+                positions[0] + radiusX * 0.7,
+                positions[1] + radiusY * 0.7,
+              ];
+              point.half = angle < -Math.PI / 2 || angle > Math.PI / 2 ? 1 : 0;
+              point.angle = angle;
+              // Set the anchor point for data labels. Use point.labelDistance
+              // instead of labelDistance // #1174
+              // finalConnectorOffset - not override connectorOffset value.
+              finalConnectorOffset = Math.min(
+                connectorOffset,
+                point.labelDistance / 5
+              ); // #1678
+              point.labelPosition = {
+                natural: {
+                  // initial position of the data label - it's utilized for
+                  // finding the final position for the label
+                  x:
+                    positions[0] +
+                    radiusX +
+                    Math.cos(angle) * point.labelDistance,
+                  y:
+                    positions[1] +
+                    radiusY +
+                    Math.sin(angle) * point.labelDistance,
+                },
+                final: {
+                  // used for generating connector path -
+                  // initialized later in drawDataLabels function
+                  // x: undefined,
+                  // y: undefined
+                },
+                // left - pie on the left side of the data label
+                // right - pie on the right side of the data label
+                // center - data label overlaps the pie
+                alignment:
+                  point.labelDistance < 0
+                    ? "center"
+                    : point.half
+                    ? "right"
+                    : "left",
+                connectorPosition: {
+                  breakAt: {
+                    x:
+                      positions[0] +
+                      radiusX +
+                      Math.cos(angle) * finalConnectorOffset,
+                    y:
+                      positions[1] +
+                      radiusY +
+                      Math.sin(angle) * finalConnectorOffset,
+                  },
+                  touchingSliceAt: {
+                    x: positions[0] + radiusX,
+                    y: positions[1] + radiusY,
+                  },
+                },
+              };
+            }
+            fireEvent(series, "afterTranslate");
+          },
+          /**
+           * Called internally to draw auxiliary graph in pie-like series in
+           * situtation when the default graph is not sufficient enough to present
+           * the data well. Auxiliary graph is saved in the same object as
+           * regular graph.
+           *
+           * @private
+           * @function Highcharts.seriesTypes.pie#drawEmpty
+           */
+          drawEmpty: function () {
+            var centerX,
+              centerY,
+              start = this.startAngleRad,
+              end = this.endAngleRad,
+              options = this.options;
+            // Draw auxiliary graph if there're no visible points.
+            if (this.total === 0 && this.center) {
+              centerX = this.center[0];
+              centerY = this.center[1];
+              if (!this.graph) {
+                this.graph = this.chart.renderer
+                  .arc(centerX, centerY, this.center[1] / 2, 0, start, end)
+                  .addClass("highcharts-empty-series")
+                  .add(this.group);
+              }
+              this.graph.attr({
+                d: SVGRenderer.prototype.symbols.arc(
+                  centerX,
+                  centerY,
+                  this.center[2] / 2,
+                  0,
+                  {
+                    start: start,
+                    end: end,
+                    innerR: this.center[3] / 2,
+                  }
+                ),
+              });
+              if (!this.chart.styledMode) {
+                this.graph.attr({
+                  "stroke-width": options.borderWidth,
+                  fill: options.fillColor || "none",
+                  stroke: options.color || "#cccccc",
+                });
+              }
+            } else if (this.graph) {
+              // Destroy the graph object.
+              this.graph = this.graph.destroy();
+            }
+          },
+          /**
+           * Draw the data points
+           *
+           * @private
+           * @function Highcharts.seriesTypes.pie#drawPoints
+           * @return {void}
+           */
+          redrawPoints: function () {
+            var series = this,
+              chart = series.chart,
+              renderer = chart.renderer,
+              groupTranslation,
+              graphic,
+              pointAttr,
+              shapeArgs,
+              shadow = series.options.shadow;
+            this.drawEmpty();
+            if (shadow && !series.shadowGroup && !chart.styledMode) {
+              series.shadowGroup = renderer
+                .g("shadow")
+                .attr({ zIndex: -1 })
+                .add(series.group);
+            }
+            // draw the slices
+            series.points.forEach(function (point) {
+              var animateTo = {};
+              graphic = point.graphic;
+              if (!point.isNull && graphic) {
+                shapeArgs = point.shapeArgs;
+                // If the point is sliced, use special translation, else use
+                // plot area translation
+                groupTranslation = point.getTranslate();
+                if (!chart.styledMode) {
+                  // Put the shadow behind all points
+                  var shadowGroup = point.shadowGroup;
+                  if (shadow && !shadowGroup) {
+                    shadowGroup = point.shadowGroup = renderer
+                      .g("shadow")
+                      .add(series.shadowGroup);
+                  }
+                  if (shadowGroup) {
+                    shadowGroup.attr(groupTranslation);
+                  }
+                  pointAttr = series.pointAttribs(
+                    point,
+                    point.selected && "select"
+                  );
+                }
+                // Draw the slice
+                if (!point.delayedRendering) {
+                  graphic.setRadialReference(series.center);
+                  if (!chart.styledMode) {
+                    merge(true, animateTo, pointAttr);
+                  }
+                  merge(true, animateTo, shapeArgs, groupTranslation);
+                  graphic.animate(animateTo);
+                } else {
+                  graphic
+                    .setRadialReference(series.center)
+                    .attr(shapeArgs)
+                    .attr(groupTranslation);
+                  if (!chart.styledMode) {
+                    graphic
+                      .attr(pointAttr)
+                      .attr({ "stroke-linejoin": "round" })
+                      .shadow(shadow, shadowGroup);
+                  }
+                  point.delayedRendering = false;
+                }
+                graphic.attr({
+                  visibility: point.visible ? "inherit" : "hidden",
+                });
+                graphic.addClass(point.getClassName());
+              } else if (graphic) {
+                point.graphic = graphic.destroy();
+              }
+            });
+          },
+          /**
+           * Slices in pie chart are initialized in DOM, but it's shapes and
+           * animations are normally run in `drawPoints()`.
+           * @private
+           */
+          drawPoints: function () {
+            var renderer = this.chart.renderer;
+            this.points.forEach(function (point) {
+              // When updating a series between 2d and 3d or cartesian and
+              // polar, the shape type changes.
+              if (point.graphic && point.hasNewShapeType()) {
+                point.graphic = point.graphic.destroy();
+              }
+              if (!point.graphic) {
+                point.graphic = renderer[point.shapeType](point.shapeArgs).add(
+                  point.series.group
+                );
+                point.delayedRendering = true;
+              }
+            });
+          },
+          /**
+           * @private
+           * @deprecated
+           * @function Highcharts.seriesTypes.pie#searchPoint
+           */
+          searchPoint: noop,
+          /**
+           * Utility for sorting data labels
+           *
+           * @private
+           * @function Highcharts.seriesTypes.pie#sortByAngle
+           * @param {Array<Highcharts.Point>} points
+           * @param {number} sign
+           * @return {void}
+           */
+          sortByAngle: function (points, sign) {
+            points.sort(function (a, b) {
+              return (
+                typeof a.angle !== "undefined" && (b.angle - a.angle) * sign
+              );
+            });
+          },
+          /**
+           * Use a simple symbol from LegendSymbolMixin.
+           *
+           * @private
+           * @borrows Highcharts.LegendSymbolMixin.drawRectangle as Highcharts.seriesTypes.pie#drawLegendSymbol
+           */
+          drawLegendSymbol: LegendSymbolMixin.drawRectangle,
+          /**
+           * Use the getCenter method from drawLegendSymbol.
+           *
+           * @private
+           * @borrows Highcharts.CenteredSeriesMixin.getCenter as Highcharts.seriesTypes.pie#getCenter
+           */
+          getCenter: CenteredSeriesMixin.getCenter,
+          /**
+           * Pies don't have point marker symbols.
+           *
+           * @deprecated
+           * @private
+           * @function Highcharts.seriesTypes.pie#getSymbol
+           */
+          getSymbol: noop,
+          /**
+           * @private
+           * @type {null}
+           */
+          drawGraph: null,
+        },
+        /**
+         * @lends seriesTypes.pie.prototype.pointClass.prototype
+         */
+        {
+          /**
+           * Initialize the pie slice
+           *
+           * @private
+           * @function Highcharts.seriesTypes.pie#pointClass#init
+           * @return {Highcharts.Point}
+           */
+          init: function () {
+            Point.prototype.init.apply(this, arguments);
+            var point = this,
+              toggleSlice;
+            point.name = pick(point.name, "Slice");
+            // add event listener for select
+            toggleSlice = function (e) {
+              point.slice(e.type === "select");
+            };
+            addEvent(point, "select", toggleSlice);
+            addEvent(point, "unselect", toggleSlice);
+            return point;
+          },
+          /**
+           * Negative points are not valid (#1530, #3623, #5322)
+           *
+           * @private
+           * @function Highcharts.seriesTypes.pie#pointClass#isValid
+           * @return {boolean}
+           */
+          isValid: function () {
+            return isNumber(this.y) && this.y >= 0;
+          },
+          /**
+           * Toggle the visibility of the pie slice
+           *
+           * @private
+           * @function Highcharts.seriesTypes.pie#pointClass#setVisible
+           * @param {boolean} vis
+           *        Whether to show the slice or not. If undefined, the visibility
+           *        is toggled.
+           * @param {boolean} [redraw=false]
+           * @return {void}
+           */
+          setVisible: function (vis, redraw) {
+            var point = this,
+              series = point.series,
+              chart = series.chart,
+              ignoreHiddenPoint = series.options.ignoreHiddenPoint;
+            redraw = pick(redraw, ignoreHiddenPoint);
+            if (vis !== point.visible) {
+              // If called without an argument, toggle visibility
+              point.visible =
+                point.options.visible =
+                vis =
+                  typeof vis === "undefined" ? !point.visible : vis;
+              // update userOptions.data
+              series.options.data[series.data.indexOf(point)] = point.options;
+              // Show and hide associated elements. This is performed
+              // regardless of redraw or not, because chart.redraw only
+              // handles full series.
+              ["graphic", "dataLabel", "connector", "shadowGroup"].forEach(
+                function (key) {
+                  if (point[key]) {
+                    point[key][vis ? "show" : "hide"](true);
+                  }
+                }
+              );
+              if (point.legendItem) {
+                chart.legend.colorizeItem(point, vis);
+              }
+              // #4170, hide halo after hiding point
+              if (!vis && point.state === "hover") {
+                point.setState("");
+              }
+              // Handle ignore hidden slices
+              if (ignoreHiddenPoint) {
+                series.isDirty = true;
+              }
+              if (redraw) {
+                chart.redraw();
+              }
+            }
+          },
+          /**
+           * Set or toggle whether the slice is cut out from the pie
+           *
+           * @private
+           * @function Highcharts.seriesTypes.pie#pointClass#slice
+           * @param {boolean} sliced
+           *        When undefined, the slice state is toggled.
+           * @param {boolean} redraw
+           *        Whether to redraw the chart. True by default.
+           * @param {boolean|Partial<Highcharts.AnimationOptionsObject>}
+           *        Animation options.
+           * @return {void}
+           */
+          slice: function (sliced, redraw, animation) {
+            var point = this,
+              series = point.series,
+              chart = series.chart;
+            setAnimation(animation, chart);
+            // redraw is true by default
+            redraw = pick(redraw, true);
+            /**
+             * Pie series only. Whether to display a slice offset from the
+             * center.
+             * @name Highcharts.Point#sliced
+             * @type {boolean|undefined}
+             */
+            // if called without an argument, toggle
+            point.sliced =
+              point.options.sliced =
+              sliced =
+                defined(sliced) ? sliced : !point.sliced;
+            // update userOptions.data
+            series.options.data[series.data.indexOf(point)] = point.options;
+            if (point.graphic) {
+              point.graphic.animate(this.getTranslate());
+            }
+            if (point.shadowGroup) {
+              point.shadowGroup.animate(this.getTranslate());
+            }
+          },
+          /**
+           * @private
+           * @function Highcharts.seriesTypes.pie#pointClass#getTranslate
+           * @return {Highcharts.TranslationAttributes}
+           */
+          getTranslate: function () {
+            return this.sliced
+              ? this.slicedTranslation
+              : {
+                  translateX: 0,
+                  translateY: 0,
+                };
+          },
+          /**
+           * @private
+           * @function Highcharts.seriesTypes.pie#pointClass#haloPath
+           * @param {number} size
+           * @return {Highcharts.SVGPathArray}
+           */
+          haloPath: function (size) {
+            var shapeArgs = this.shapeArgs;
+            return this.sliced || !this.visible
+              ? []
+              : this.series.chart.renderer.symbols.arc(
+                  shapeArgs.x,
+                  shapeArgs.y,
+                  shapeArgs.r + size,
+                  shapeArgs.r + size,
+                  {
+                    // Substract 1px to ensure the background is not bleeding
+                    // through between the halo and the slice (#7495).
+                    innerR: shapeArgs.r - 1,
+                    start: shapeArgs.start,
+                    end: shapeArgs.end,
+                  }
+                );
+          },
+          connectorShapes: {
+            // only one available before v7.0.0
+            fixedOffset: function (labelPosition, connectorPosition, options) {
+              var breakAt = connectorPosition.breakAt,
+                touchingSliceAt = connectorPosition.touchingSliceAt,
+                lineSegment = options.softConnector
+                  ? [
+                      "C",
+                      // 1st control point (of the curve)
+                      labelPosition.x +
+                        // 5 gives the connector a little horizontal bend
+                        (labelPosition.alignment === "left" ? -5 : 5),
+                      labelPosition.y,
+                      2 * breakAt.x - touchingSliceAt.x,
+                      2 * breakAt.y - touchingSliceAt.y,
+                      breakAt.x,
+                      breakAt.y, //
+                    ]
+                  : ["L", breakAt.x, breakAt.y];
+              // assemble the path
+              return [
+                ["M", labelPosition.x, labelPosition.y],
+                lineSegment,
+                ["L", touchingSliceAt.x, touchingSliceAt.y],
+              ];
             },
-            /**
-             * @private
-             * @borrows Highcharts.TrackerMixin.drawTrackerGraph as Highcharts.Series#drawTracker
-             */
-            drawTracker: TrackerMixin.drawTrackerGraph
+            straight: function (labelPosition, connectorPosition) {
+              var touchingSliceAt = connectorPosition.touchingSliceAt;
+              // direct line to the slice
+              return [
+                ["M", labelPosition.x, labelPosition.y],
+                ["L", touchingSliceAt.x, touchingSliceAt.y],
+              ];
+            },
+            crookedLine: function (labelPosition, connectorPosition, options) {
+              var touchingSliceAt = connectorPosition.touchingSliceAt,
+                series = this.series,
+                pieCenterX = series.center[0],
+                plotWidth = series.chart.plotWidth,
+                plotLeft = series.chart.plotLeft,
+                alignment = labelPosition.alignment,
+                radius = this.shapeArgs.r,
+                crookDistance = relativeLength(
+                  // % to fraction
+                  options.crookDistance,
+                  1
+                ),
+                crookX =
+                  alignment === "left"
+                    ? pieCenterX +
+                      radius +
+                      (plotWidth + plotLeft - pieCenterX - radius) *
+                        (1 - crookDistance)
+                    : plotLeft + (pieCenterX - radius) * crookDistance,
+                segmentWithCrook = ["L", crookX, labelPosition.y],
+                useCrook = true;
+              // crookedLine formula doesn't make sense if the path overlaps
+              // the label - use straight line instead in that case
+              if (
+                alignment === "left"
+                  ? crookX > labelPosition.x || crookX < touchingSliceAt.x
+                  : crookX < labelPosition.x || crookX > touchingSliceAt.x
+              ) {
+                useCrook = false;
+              }
+              // assemble the path
+              var path = [["M", labelPosition.x, labelPosition.y]];
+              if (useCrook) {
+                path.push(segmentWithCrook);
+              }
+              path.push(["L", touchingSliceAt.x, touchingSliceAt.y]);
+              return path;
+            },
+          },
+          /**
+           * Extendable method for getting the path of the connector between the
+           * data label and the pie slice.
+           */
+          getConnectorPath: function () {
+            var labelPosition = this.labelPosition,
+              options = this.series.options.dataLabels,
+              connectorShape = options.connectorShape,
+              predefinedShapes = this.connectorShapes;
+            // find out whether to use the predefined shape
+            if (predefinedShapes[connectorShape]) {
+              connectorShape = predefinedShapes[connectorShape];
+            }
+            return connectorShape.call(
+              this,
+              {
+                // pass simplified label position object for user's convenience
+                x: labelPosition.final.x,
+                y: labelPosition.final.y,
+                alignment: labelPosition.alignment,
+              },
+              labelPosition.connectorPosition,
+              options
+            );
+          },
+        }
+        /* eslint-enable valid-jsdoc */
+      );
+      /**
+       * A `pie` series. If the [type](#series.pie.type) option is not specified,
+       * it is inherited from [chart.type](#chart.type).
+       *
+       * @extends   series,plotOptions.pie
+       * @excluding cropThreshold, dataParser, dataURL, stack, xAxis, yAxis,
+       *            dataSorting, step, boostThreshold, boostBlending
+       * @product   highcharts
+       * @apioption series.pie
+       */
+      /**
+       * An array of data points for the series. For the `pie` series type,
+       * points can be given in the following ways:
+       *
+       * 1. An array of numerical values. In this case, the numerical values will be
+       *    interpreted as `y` options. Example:
+       *    ```js
+       *    data: [0, 5, 3, 5]
+       *    ```
+       *
+       * 2. An array of objects with named values. The following snippet shows only a
+       *    few settings, see the complete options set below. If the total number of
+       *    data points exceeds the series'
+       *    [turboThreshold](#series.pie.turboThreshold),
+       *    this option is not available.
+       *    ```js
+       *    data: [{
+       *        y: 1,
+       *        name: "Point2",
+       *        color: "#00FF00"
+       *    }, {
+       *        y: 7,
+       *        name: "Point1",
+       *        color: "#FF00FF"
+       *    }]
+       *    ```
+       *
+       * @sample {highcharts} highcharts/chart/reflow-true/
+       *         Numerical values
+       * @sample {highcharts} highcharts/series/data-array-of-arrays/
+       *         Arrays of numeric x and y
+       * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
+       *         Arrays of datetime x and y
+       * @sample {highcharts} highcharts/series/data-array-of-name-value/
+       *         Arrays of point.name and y
+       * @sample {highcharts} highcharts/series/data-array-of-objects/
+       *         Config objects
+       *
+       * @type      {Array<number|Array<string,(number|null)>|null|*>}
+       * @extends   series.line.data
+       * @excluding marker, x
+       * @product   highcharts
+       * @apioption series.pie.data
+       */
+      /**
+       * @type      {Highcharts.SeriesPieDataLabelsOptionsObject}
+       * @product   highcharts
+       * @apioption series.pie.data.dataLabels
+       */
+      /**
+       * The sequential index of the data point in the legend.
+       *
+       * @type      {number}
+       * @product   highcharts
+       * @apioption series.pie.data.legendIndex
+       */
+      /**
+       * Whether to display a slice offset from the center.
+       *
+       * @sample {highcharts} highcharts/point/sliced/
+       *         One sliced point
+       *
+       * @type      {boolean}
+       * @product   highcharts
+       * @apioption series.pie.data.sliced
+       */
+      /**
+       * @excluding legendItemClick
+       * @product   highcharts
+       * @apioption series.pie.events
+       */
+      (""); // placeholder for transpiled doclets above
+    }
+  );
+  _registerModule(
+    _modules,
+    "Core/Series/DataLabels.js",
+    [
+      _modules["Core/Animation/AnimationUtilities.js"],
+      _modules["Core/Globals.js"],
+      _modules["Core/Series/CartesianSeries.js"],
+      _modules["Core/Utilities.js"],
+    ],
+    function (A, H, CartesianSeries, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      var getDeferredAnimation = A.getDeferredAnimation;
+      var noop = H.noop,
+        seriesTypes = H.seriesTypes;
+      var arrayMax = U.arrayMax,
+        clamp = U.clamp,
+        defined = U.defined,
+        extend = U.extend,
+        fireEvent = U.fireEvent,
+        format = U.format,
+        isArray = U.isArray,
+        merge = U.merge,
+        objectEach = U.objectEach,
+        pick = U.pick,
+        relativeLength = U.relativeLength,
+        splat = U.splat,
+        stableSort = U.stableSort;
+      /**
+       * Callback JavaScript function to format the data label as a string. Note that
+       * if a `format` is defined, the format takes precedence and the formatter is
+       * ignored.
+       *
+       * @callback Highcharts.DataLabelsFormatterCallbackFunction
+       *
+       * @param {Highcharts.PointLabelObject} this
+       * Data label context to format
+       *
+       * @param {Highcharts.DataLabelsOptions} options
+       * [API options](/highcharts/plotOptions.series.dataLabels) of the data label
+       *
+       * @return {number|string|null|undefined}
+       * Formatted data label text
+       */
+      /**
+       * Values for handling data labels that flow outside the plot area.
+       *
+       * @typedef {"allow"|"justify"} Highcharts.DataLabelsOverflowValue
+       */
+      (""); // detach doclets above
+      /* eslint-disable valid-jsdoc */
+      /**
+       * General distribution algorithm for distributing labels of differing size
+       * along a confined length in two dimensions. The algorithm takes an array of
+       * objects containing a size, a target and a rank. It will place the labels as
+       * close as possible to their targets, skipping the lowest ranked labels if
+       * necessary.
+       *
+       * @private
+       * @function Highcharts.distribute
+       * @param {Highcharts.DataLabelsBoxArray} boxes
+       * @param {number} len
+       * @param {number} [maxDistance]
+       * @return {void}
+       */
+      H.distribute = function (boxes, len, maxDistance) {
+        var i,
+          overlapping = true,
+          origBoxes = boxes, // Original array will be altered with added .pos
+          restBoxes = [], // The outranked overshoot
+          box,
+          target,
+          total = 0,
+          reducedLen = origBoxes.reducedLen || len;
+        /**
+         * @private
+         */
+        function sortByTarget(a, b) {
+          return a.target - b.target;
+        }
+        // If the total size exceeds the len, remove those boxes with the lowest
+        // rank
+        i = boxes.length;
+        while (i--) {
+          total += boxes[i].size;
+        }
+        // Sort by rank, then slice away overshoot
+        if (total > reducedLen) {
+          stableSort(boxes, function (a, b) {
+            return (b.rank || 0) - (a.rank || 0);
+          });
+          i = 0;
+          total = 0;
+          while (total <= reducedLen) {
+            total += boxes[i].size;
+            i++;
+          }
+          restBoxes = boxes.splice(i - 1, boxes.length);
+        }
+        // Order by target
+        stableSort(boxes, sortByTarget);
+        // So far we have been mutating the original array. Now
+        // create a copy with target arrays
+        boxes = boxes.map(function (box) {
+          return {
+            size: box.size,
+            targets: [box.target],
+            align: pick(box.align, 0.5),
+          };
         });
-
-    });
-    _registerModule(_modules, 'Core/Responsive.js', [_modules['Core/Chart/Chart.js'], _modules['Core/Utilities.js']], function (Chart, U) {
-        /* *
-         *
-         *  (c) 2010-2020 Torstein Honsi
-         *
-         *  License: www.highcharts.com/license
-         *
-         *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+        while (overlapping) {
+          // Initial positions: target centered in box
+          i = boxes.length;
+          while (i--) {
+            box = boxes[i];
+            // Composite box, average of targets
+            target =
+              (Math.min.apply(0, box.targets) +
+                Math.max.apply(0, box.targets)) /
+              2;
+            box.pos = clamp(target - box.size * box.align, 0, len - box.size);
+          }
+          // Detect overlap and join boxes
+          i = boxes.length;
+          overlapping = false;
+          while (i--) {
+            // Overlap
+            if (i > 0 && boxes[i - 1].pos + boxes[i - 1].size > boxes[i].pos) {
+              // Add this size to the previous box
+              boxes[i - 1].size += boxes[i].size;
+              boxes[i - 1].targets = boxes[i - 1].targets.concat(
+                boxes[i].targets
+              );
+              boxes[i - 1].align = 0.5;
+              // Overlapping right, push left
+              if (boxes[i - 1].pos + boxes[i - 1].size > len) {
+                boxes[i - 1].pos = len - boxes[i - 1].size;
+              }
+              boxes.splice(i, 1); // Remove this item
+              overlapping = true;
+            }
+          }
+        }
+        // Add the rest (hidden boxes)
+        origBoxes.push.apply(origBoxes, restBoxes);
+        // Now the composite boxes are placed, we need to put the original boxes
+        // within them
+        i = 0;
+        boxes.some(function (box) {
+          var posInCompositeBox = 0;
+          if (
+            box.targets.some(function () {
+              origBoxes[i].pos = box.pos + posInCompositeBox;
+              // If the distance between the position and the target exceeds
+              // maxDistance, abort the loop and decrease the length in increments
+              // of 10% to recursively reduce the  number of visible boxes by
+              // rank. Once all boxes are within the maxDistance, we're good.
+              if (
+                typeof maxDistance !== "undefined" &&
+                Math.abs(origBoxes[i].pos - origBoxes[i].target) > maxDistance
+              ) {
+                // Reset the positions that are already set
+                origBoxes.slice(0, i + 1).forEach(function (box) {
+                  delete box.pos;
+                });
+                // Try with a smaller length
+                origBoxes.reducedLen =
+                  (origBoxes.reducedLen || len) - len * 0.1;
+                // Recurse
+                if (origBoxes.reducedLen > len * 0.1) {
+                  H.distribute(origBoxes, len, maxDistance);
+                }
+                // Exceeded maxDistance => abort
+                return true;
+              }
+              posInCompositeBox += origBoxes[i].size;
+              i++;
+            })
+          ) {
+            // Exceeded maxDistance => abort
+            return true;
+          }
+        });
+        // Add the rest (hidden) boxes and sort by target
+        stableSort(origBoxes, sortByTarget);
+      };
+      /**
+       * Draw the data labels
+       *
+       * @private
+       * @function Highcharts.Series#drawDataLabels
+       * @return {void}
+       * @fires Highcharts.Series#event:afterDrawDataLabels
+       */
+      CartesianSeries.prototype.drawDataLabels = function () {
+        var series = this,
+          chart = series.chart,
+          seriesOptions = series.options,
+          seriesDlOptions = seriesOptions.dataLabels,
+          points = series.points,
+          pointOptions,
+          hasRendered = series.hasRendered || 0,
+          dataLabelsGroup,
+          dataLabelAnim = seriesDlOptions.animation,
+          animationConfig = seriesDlOptions.defer
+            ? getDeferredAnimation(chart, dataLabelAnim, series)
+            : { defer: 0, duration: 0 },
+          renderer = chart.renderer;
+        /**
+         * Handle the dataLabels.filter option.
+         * @private
+         */
+        function applyFilter(point, options) {
+          var filter = options.filter,
+            op,
+            prop,
+            val;
+          if (filter) {
+            op = filter.operator;
+            prop = point[filter.property];
+            val = filter.value;
+            if (
+              (op === ">" && prop > val) ||
+              (op === "<" && prop < val) ||
+              (op === ">=" && prop >= val) ||
+              (op === "<=" && prop <= val) ||
+              (op === "==" && prop == val) || // eslint-disable-line eqeqeq
+              (op === "===" && prop === val)
+            ) {
+              return true;
+            }
+            return false;
+          }
+          return true;
+        }
+        /**
+         * Merge two objects that can be arrays. If one of them is an array, the
+         * other is merged into each element. If both are arrays, each element is
+         * merged by index. If neither are arrays, we use normal merge.
+         * @private
+         */
+        function mergeArrays(one, two) {
+          var res = [],
+            i;
+          if (isArray(one) && !isArray(two)) {
+            res = one.map(function (el) {
+              return merge(el, two);
+            });
+          } else if (isArray(two) && !isArray(one)) {
+            res = two.map(function (el) {
+              return merge(one, el);
+            });
+          } else if (!isArray(one) && !isArray(two)) {
+            res = merge(one, two);
+          } else {
+            i = Math.max(one.length, two.length);
+            while (i--) {
+              res[i] = merge(one[i], two[i]);
+            }
+          }
+          return res;
+        }
+        // Merge in plotOptions.dataLabels for series
+        seriesDlOptions = mergeArrays(
+          mergeArrays(
+            chart.options.plotOptions &&
+              chart.options.plotOptions.series &&
+              chart.options.plotOptions.series.dataLabels,
+            chart.options.plotOptions &&
+              chart.options.plotOptions[series.type] &&
+              chart.options.plotOptions[series.type].dataLabels
+          ),
+          seriesDlOptions
+        );
+        fireEvent(this, "drawDataLabels");
+        if (
+          isArray(seriesDlOptions) ||
+          seriesDlOptions.enabled ||
+          series._hasPointLabels
+        ) {
+          // Create a separate group for the data labels to avoid rotation
+          dataLabelsGroup = series.plotGroup(
+            "dataLabelsGroup",
+            "data-labels",
+            !hasRendered ? "hidden" : "inherit", // #5133, #10220
+            seriesDlOptions.zIndex || 6
+          );
+          dataLabelsGroup.attr({ opacity: +hasRendered }); // #3300
+          if (!hasRendered) {
+            var group = series.dataLabelsGroup;
+            if (group) {
+              if (series.visible) {
+                // #2597, #3023, #3024
+                dataLabelsGroup.show(true);
+              }
+              group[seriesOptions.animation ? "animate" : "attr"](
+                { opacity: 1 },
+                animationConfig
+              );
+            }
+          }
+          // Make the labels for each point
+          points.forEach(function (point) {
+            // Merge in series options for the point.
+            // @note dataLabelAttribs (like pointAttribs) would eradicate
+            // the need for dlOptions, and simplify the section below.
+            pointOptions = splat(
+              mergeArrays(
+                seriesDlOptions,
+                point.dlOptions || // dlOptions is used in treemaps
+                  (point.options && point.options.dataLabels)
+              )
+            );
+            // Handle each individual data label for this point
+            pointOptions.forEach(function (labelOptions, i) {
+              // Options for one datalabel
+              var labelEnabled =
+                  labelOptions.enabled &&
+                  // #2282, #4641, #7112, #10049
+                  (!point.isNull || point.dataLabelOnNull) &&
+                  applyFilter(point, labelOptions),
+                labelConfig,
+                formatString,
+                labelText,
+                style,
+                rotation,
+                attr,
+                dataLabel = point.dataLabels
+                  ? point.dataLabels[i]
+                  : point.dataLabel,
+                connector = point.connectors
+                  ? point.connectors[i]
+                  : point.connector,
+                labelDistance = pick(
+                  labelOptions.distance,
+                  point.labelDistance
+                ),
+                isNew = !dataLabel;
+              if (labelEnabled) {
+                // Create individual options structure that can be extended
+                // without affecting others
+                labelConfig = point.getLabelConfig();
+                formatString = pick(
+                  labelOptions[point.formatPrefix + "Format"],
+                  labelOptions.format
+                );
+                labelText = defined(formatString)
+                  ? format(formatString, labelConfig, chart)
+                  : (
+                      labelOptions[point.formatPrefix + "Formatter"] ||
+                      labelOptions.formatter
+                    ).call(labelConfig, labelOptions);
+                style = labelOptions.style;
+                rotation = labelOptions.rotation;
+                if (!chart.styledMode) {
+                  // Determine the color
+                  style.color = pick(
+                    labelOptions.color,
+                    style.color,
+                    series.color,
+                    "#000000"
+                  );
+                  // Get automated contrast color
+                  if (style.color === "contrast") {
+                    point.contrastColor = renderer.getContrast(
+                      point.color || series.color
+                    );
+                    style.color =
+                      (!defined(labelDistance) && labelOptions.inside) ||
+                      labelDistance < 0 ||
+                      !!seriesOptions.stacking
+                        ? point.contrastColor
+                        : "#000000";
+                  } else {
+                    delete point.contrastColor;
+                  }
+                  if (seriesOptions.cursor) {
+                    style.cursor = seriesOptions.cursor;
+                  }
+                }
+                attr = {
+                  r: labelOptions.borderRadius || 0,
+                  rotation: rotation,
+                  padding: labelOptions.padding,
+                  zIndex: 1,
+                };
+                if (!chart.styledMode) {
+                  attr.fill = labelOptions.backgroundColor;
+                  attr.stroke = labelOptions.borderColor;
+                  attr["stroke-width"] = labelOptions.borderWidth;
+                }
+                // Remove unused attributes (#947)
+                objectEach(attr, function (val, name) {
+                  if (typeof val === "undefined") {
+                    delete attr[name];
+                  }
+                });
+              }
+              // If the point is outside the plot area, destroy it. #678, #820
+              if (dataLabel && (!labelEnabled || !defined(labelText))) {
+                point.dataLabel = point.dataLabel && point.dataLabel.destroy();
+                if (point.dataLabels) {
+                  // Remove point.dataLabels if this was the last one
+                  if (point.dataLabels.length === 1) {
+                    delete point.dataLabels;
+                  } else {
+                    delete point.dataLabels[i];
+                  }
+                }
+                if (!i) {
+                  delete point.dataLabel;
+                }
+                if (connector) {
+                  point.connector = point.connector.destroy();
+                  if (point.connectors) {
+                    // Remove point.connectors if this was the last one
+                    if (point.connectors.length === 1) {
+                      delete point.connectors;
+                    } else {
+                      delete point.connectors[i];
+                    }
+                  }
+                }
+                // Individual labels are disabled if the are explicitly disabled
+                // in the point options, or if they fall outside the plot area.
+              } else if (labelEnabled && defined(labelText)) {
+                if (!dataLabel) {
+                  // Create new label element
+                  point.dataLabels = point.dataLabels || [];
+                  dataLabel = point.dataLabels[i] = rotation
+                    ? // Labels don't rotate, use text element
+                      renderer
+                        .text(labelText, 0, -9999, labelOptions.useHTML)
+                        .addClass("highcharts-data-label")
+                    : // We can use label
+                      renderer.label(
+                        labelText,
+                        0,
+                        -9999,
+                        labelOptions.shape,
+                        null,
+                        null,
+                        labelOptions.useHTML,
+                        null,
+                        "data-label"
+                      );
+                  // Store for backwards compatibility
+                  if (!i) {
+                    point.dataLabel = dataLabel;
+                  }
+                  dataLabel.addClass(
+                    " highcharts-data-label-color-" +
+                      point.colorIndex +
+                      " " +
+                      (labelOptions.className || "") + // #3398
+                      (labelOptions.useHTML ? " highcharts-tracker" : "")
+                  );
+                } else {
+                  // Use old element and just update text
+                  attr.text = labelText;
+                }
+                // Store data label options for later access
+                dataLabel.options = labelOptions;
+                dataLabel.attr(attr);
+                if (!chart.styledMode) {
+                  // Styles must be applied before add in order to read
+                  // text bounding box
+                  dataLabel.css(style).shadow(labelOptions.shadow);
+                }
+                if (!dataLabel.added) {
+                  dataLabel.add(dataLabelsGroup);
+                }
+                if (labelOptions.textPath && !labelOptions.useHTML) {
+                  dataLabel.setTextPath(
+                    (point.getDataLabelPath &&
+                      point.getDataLabelPath(dataLabel)) ||
+                      point.graphic,
+                    labelOptions.textPath
+                  );
+                  if (point.dataLabelPath && !labelOptions.textPath.enabled) {
+                    // clean the DOM
+                    point.dataLabelPath = point.dataLabelPath.destroy();
+                  }
+                }
+                // Now the data label is created and placed at 0,0, so we
+                // need to align it
+                series.alignDataLabel(
+                  point,
+                  dataLabel,
+                  labelOptions,
+                  null,
+                  isNew
+                );
+              }
+            });
+          });
+        }
+        fireEvent(this, "afterDrawDataLabels");
+      };
+      /**
+       * Align each individual data label.
+       *
+       * @private
+       * @function Highcharts.Series#alignDataLabel
+       * @param {Highcharts.Point} point
+       * @param {Highcharts.SVGElement} dataLabel
+       * @param {Highcharts.DataLabelsOptions} options
+       * @param {Highcharts.BBoxObject} alignTo
+       * @param {boolean} [isNew]
+       * @return {void}
+       */
+      CartesianSeries.prototype.alignDataLabel = function (
+        point,
+        dataLabel,
+        options,
+        alignTo,
+        isNew
+      ) {
+        var series = this,
+          chart = this.chart,
+          inverted = this.isCartesian && chart.inverted,
+          enabledDataSorting = this.enabledDataSorting,
+          plotX = pick(point.dlBox && point.dlBox.centerX, point.plotX, -9999),
+          plotY = pick(point.plotY, -9999),
+          bBox = dataLabel.getBBox(),
+          baseline,
+          rotation = options.rotation,
+          normRotation,
+          negRotation,
+          align = options.align,
+          rotCorr, // rotation correction
+          isInsidePlot = chart.isInsidePlot(plotX, Math.round(plotY), inverted),
+          // Math.round for rounding errors (#2683), alignTo to allow column
+          // labels (#2700)
+          alignAttr, // the final position;
+          justify =
+            pick(options.overflow, enabledDataSorting ? "none" : "justify") ===
+            "justify",
+          visible =
+            this.visible &&
+            point.visible !== false &&
+            (point.series.forceDL ||
+              (enabledDataSorting && !justify) ||
+              isInsidePlot ||
+              // If the data label is inside the align box, it is enough
+              // that parts of the align box is inside the plot area
+              // (#12370)
+              (options.inside &&
+                alignTo &&
+                chart.isInsidePlot(
+                  plotX,
+                  inverted ? alignTo.x + 1 : alignTo.y + alignTo.height - 1,
+                  inverted
+                ))),
+          setStartPos = function (alignOptions) {
+            if (enabledDataSorting && series.xAxis && !justify) {
+              series.setDataLabelStartPos(
+                point,
+                dataLabel,
+                isNew,
+                isInsidePlot,
+                alignOptions
+              );
+            }
+          };
+        if (visible) {
+          baseline = chart.renderer.fontMetrics(
+            chart.styledMode ? void 0 : options.style.fontSize,
+            dataLabel
+          ).b;
+          // The alignment box is a singular point
+          alignTo = extend(
+            {
+              x: inverted ? this.yAxis.len - plotY : plotX,
+              y: Math.round(inverted ? this.xAxis.len - plotX : plotY),
+              width: 0,
+              height: 0,
+            },
+            alignTo
+          );
+          // Add the text size for alignment calculation
+          extend(options, {
+            width: bBox.width,
+            height: bBox.height,
+          });
+          // Allow a hook for changing alignment in the last moment, then do the
+          // alignment
+          if (rotation) {
+            justify = false; // Not supported for rotated text
+            rotCorr = chart.renderer.rotCorr(baseline, rotation); // #3723
+            alignAttr = {
+              x: alignTo.x + (options.x || 0) + alignTo.width / 2 + rotCorr.x,
+              y:
+                alignTo.y +
+                (options.y || 0) +
+                { top: 0, middle: 0.5, bottom: 1 }[options.verticalAlign] *
+                  alignTo.height,
+            };
+            setStartPos(alignAttr); // data sorting
+            dataLabel[isNew ? "attr" : "animate"](alignAttr).attr({
+              align: align,
+            });
+            // Compensate for the rotated label sticking out on the sides
+            normRotation = (rotation + 720) % 360;
+            negRotation = normRotation > 180 && normRotation < 360;
+            if (align === "left") {
+              alignAttr.y -= negRotation ? bBox.height : 0;
+            } else if (align === "center") {
+              alignAttr.x -= bBox.width / 2;
+              alignAttr.y -= bBox.height / 2;
+            } else if (align === "right") {
+              alignAttr.x -= bBox.width;
+              alignAttr.y -= negRotation ? 0 : bBox.height;
+            }
+            dataLabel.placed = true;
+            dataLabel.alignAttr = alignAttr;
+          } else {
+            setStartPos(alignTo); // data sorting
+            dataLabel.align(options, null, alignTo);
+            alignAttr = dataLabel.alignAttr;
+          }
+          // Handle justify or crop
+          if (justify && alignTo.height >= 0) {
+            // #8830
+            this.justifyDataLabel(
+              dataLabel,
+              options,
+              alignAttr,
+              bBox,
+              alignTo,
+              isNew
+            );
+            // Now check that the data label is within the plot area
+          } else if (pick(options.crop, true)) {
+            visible =
+              chart.isInsidePlot(alignAttr.x, alignAttr.y) &&
+              chart.isInsidePlot(
+                alignAttr.x + bBox.width,
+                alignAttr.y + bBox.height
+              );
+          }
+          // When we're using a shape, make it possible with a connector or an
+          // arrow pointing to thie point
+          if (options.shape && !rotation) {
+            dataLabel[isNew ? "attr" : "animate"]({
+              anchorX: inverted ? chart.plotWidth - point.plotY : point.plotX,
+              anchorY: inverted ? chart.plotHeight - point.plotX : point.plotY,
+            });
+          }
+        }
+        // To use alignAttr property in hideOverlappingLabels
+        if (isNew && enabledDataSorting) {
+          dataLabel.placed = false;
+        }
+        // Show or hide based on the final aligned position
+        if (!visible && (!enabledDataSorting || justify)) {
+          dataLabel.hide(true);
+          dataLabel.placed = false; // don't animate back in
+        }
+      };
+      /**
+       * Set starting position for data label sorting animation.
+       *
+       * @private
+       * @function Highcharts.Series#setDataLabelStartPos
+       * @param {Highcharts.SVGElement} dataLabel
+       * @param {Highcharts.ColumnPoint} point
+       * @param {boolean | undefined} [isNew]
+       * @param {boolean} [isInside]
+       * @param {Highcharts.AlignObject} [alignOptions]
+       *
+       * @return {void}
+       */
+      CartesianSeries.prototype.setDataLabelStartPos = function (
+        point,
+        dataLabel,
+        isNew,
+        isInside,
+        alignOptions
+      ) {
+        var chart = this.chart,
+          inverted = chart.inverted,
+          xAxis = this.xAxis,
+          reversed = xAxis.reversed,
+          labelCenter = inverted ? dataLabel.height / 2 : dataLabel.width / 2,
+          pointWidth = point.pointWidth,
+          halfWidth = pointWidth ? pointWidth / 2 : 0,
+          startXPos,
+          startYPos;
+        startXPos = inverted
+          ? alignOptions.x
+          : reversed
+          ? -labelCenter - halfWidth
+          : xAxis.width - labelCenter + halfWidth;
+        startYPos = inverted
+          ? reversed
+            ? this.yAxis.height - labelCenter + halfWidth
+            : -labelCenter - halfWidth
+          : alignOptions.y;
+        dataLabel.startXPos = startXPos;
+        dataLabel.startYPos = startYPos;
+        // We need to handle visibility in case of sorting point outside plot area
+        if (!isInside) {
+          dataLabel
+            .attr({ opacity: 1 })
+            .animate({ opacity: 0 }, void 0, dataLabel.hide);
+        } else if (dataLabel.visibility === "hidden") {
+          dataLabel.show();
+          dataLabel.attr({ opacity: 0 }).animate({ opacity: 1 });
+        }
+        // Save start position on first render, but do not change position
+        if (!chart.hasRendered) {
+          return;
+        }
+        // Set start position
+        if (isNew) {
+          dataLabel.attr({ x: dataLabel.startXPos, y: dataLabel.startYPos });
+        }
+        dataLabel.placed = true;
+      };
+      /**
+       * If data labels fall partly outside the plot area, align them back in, in a
+       * way that doesn't hide the point.
+       *
+       * @private
+       * @function Highcharts.Series#justifyDataLabel
+       * @param {Highcharts.SVGElement} dataLabel
+       * @param {Highcharts.DataLabelsOptions} options
+       * @param {Highcharts.SVGAttributes} alignAttr
+       * @param {Highcharts.BBoxObject} bBox
+       * @param {Highcharts.BBoxObject} [alignTo]
+       * @param {boolean} [isNew]
+       * @return {boolean|undefined}
+       */
+      CartesianSeries.prototype.justifyDataLabel = function (
+        dataLabel,
+        options,
+        alignAttr,
+        bBox,
+        alignTo,
+        isNew
+      ) {
+        var chart = this.chart,
+          align = options.align,
+          verticalAlign = options.verticalAlign,
+          off,
+          justified,
+          padding = dataLabel.box ? 0 : dataLabel.padding || 0;
+        var _a = options.x,
+          x = _a === void 0 ? 0 : _a,
+          _b = options.y,
+          y = _b === void 0 ? 0 : _b;
+        // Off left
+        off = alignAttr.x + padding;
+        if (off < 0) {
+          if (align === "right" && x >= 0) {
+            options.align = "left";
+            options.inside = true;
+          } else {
+            x -= off;
+          }
+          justified = true;
+        }
+        // Off right
+        off = alignAttr.x + bBox.width - padding;
+        if (off > chart.plotWidth) {
+          if (align === "left" && x <= 0) {
+            options.align = "right";
+            options.inside = true;
+          } else {
+            x += chart.plotWidth - off;
+          }
+          justified = true;
+        }
+        // Off top
+        off = alignAttr.y + padding;
+        if (off < 0) {
+          if (verticalAlign === "bottom" && y >= 0) {
+            options.verticalAlign = "top";
+            options.inside = true;
+          } else {
+            y -= off;
+          }
+          justified = true;
+        }
+        // Off bottom
+        off = alignAttr.y + bBox.height - padding;
+        if (off > chart.plotHeight) {
+          if (verticalAlign === "top" && y <= 0) {
+            options.verticalAlign = "bottom";
+            options.inside = true;
+          } else {
+            y += chart.plotHeight - off;
+          }
+          justified = true;
+        }
+        if (justified) {
+          options.x = x;
+          options.y = y;
+          dataLabel.placed = !isNew;
+          dataLabel.align(options, void 0, alignTo);
+        }
+        return justified;
+      };
+      if (seriesTypes.pie) {
+        seriesTypes.pie.prototype.dataLabelPositioners = {
+          // Based on the value computed in Highcharts' distribute algorithm.
+          radialDistributionY: function (point) {
+            return point.top + point.distributeBox.pos;
+          },
+          // get the x - use the natural x position for labels near the
+          // top and bottom, to prevent the top and botton slice
+          // connectors from touching each other on either side
+          // Based on the value computed in Highcharts' distribute algorithm.
+          radialDistributionX: function (series, point, y, naturalY) {
+            return series.getX(
+              y < point.top + 2 || y > point.bottom - 2 ? naturalY : y,
+              point.half,
+              point
+            );
+          },
+          // dataLabels.distance determines the x position of the label
+          justify: function (point, radius, seriesCenter) {
+            return (
+              seriesCenter[0] +
+              (point.half ? -1 : 1) * (radius + point.labelDistance)
+            );
+          },
+          // Left edges of the left-half labels touch the left edge of the plot
+          // area. Right edges of the right-half labels touch the right edge of
+          // the plot area.
+          alignToPlotEdges: function (dataLabel, half, plotWidth, plotLeft) {
+            var dataLabelWidth = dataLabel.getBBox().width;
+            return half
+              ? dataLabelWidth + plotLeft
+              : plotWidth - dataLabelWidth - plotLeft;
+          },
+          // Connectors of each side end in the same x position. Labels are
+          // aligned to them. Left edge of the widest left-half label touches the
+          // left edge of the plot area. Right edge of the widest right-half label
+          // touches the right edge of the plot area.
+          alignToConnectors: function (points, half, plotWidth, plotLeft) {
+            var maxDataLabelWidth = 0,
+              dataLabelWidth;
+            // find widest data label
+            points.forEach(function (point) {
+              dataLabelWidth = point.dataLabel.getBBox().width;
+              if (dataLabelWidth > maxDataLabelWidth) {
+                maxDataLabelWidth = dataLabelWidth;
+              }
+            });
+            return half
+              ? maxDataLabelWidth + plotLeft
+              : plotWidth - maxDataLabelWidth - plotLeft;
+          },
+        };
+        /**
+         * Override the base drawDataLabels method by pie specific functionality
          *
-         * */
-        var find = U.find,
-            isArray = U.isArray,
-            isObject = U.isObject,
-            merge = U.merge,
-            objectEach = U.objectEach,
-            pick = U.pick,
-            splat = U.splat,
-            uniqueKey = U.uniqueKey;
+         * @private
+         * @function Highcharts.seriesTypes.pie#drawDataLabels
+         * @return {void}
+         */
+        seriesTypes.pie.prototype.drawDataLabels = function () {
+          var series = this,
+            data = series.data,
+            point,
+            chart = series.chart,
+            options = series.options.dataLabels || {},
+            connectorPadding = options.connectorPadding,
+            connectorWidth,
+            plotWidth = chart.plotWidth,
+            plotHeight = chart.plotHeight,
+            plotLeft = chart.plotLeft,
+            maxWidth = Math.round(chart.chartWidth / 3),
+            connector,
+            seriesCenter = series.center,
+            radius = seriesCenter[2] / 2,
+            centerY = seriesCenter[1],
+            dataLabel,
+            dataLabelWidth,
+            // labelPos,
+            labelPosition,
+            labelHeight,
+            // divide the points into right and left halves for anti collision
+            halves = [
+              [],
+              [], // left
+            ],
+            x,
+            y,
+            visibility,
+            j,
+            overflow = [0, 0, 0, 0], // top, right, bottom, left
+            dataLabelPositioners = series.dataLabelPositioners,
+            pointDataLabelsOptions;
+          // get out if not enabled
+          if (
+            !series.visible ||
+            (!options.enabled && !series._hasPointLabels)
+          ) {
+            return;
+          }
+          // Reset all labels that have been shortened
+          data.forEach(function (point) {
+            if (point.dataLabel && point.visible && point.dataLabel.shortened) {
+              point.dataLabel
+                .attr({
+                  width: "auto",
+                })
+                .css({
+                  width: "auto",
+                  textOverflow: "clip",
+                });
+              point.dataLabel.shortened = false;
+            }
+          });
+          // run parent method
+          CartesianSeries.prototype.drawDataLabels.apply(series);
+          data.forEach(function (point) {
+            if (point.dataLabel) {
+              if (point.visible) {
+                // #407, #2510
+                // Arrange points for detection collision
+                halves[point.half].push(point);
+                // Reset positions (#4905)
+                point.dataLabel._pos = null;
+                // Avoid long labels squeezing the pie size too far down
+                if (
+                  !defined(options.style.width) &&
+                  !defined(
+                    point.options.dataLabels &&
+                      point.options.dataLabels.style &&
+                      point.options.dataLabels.style.width
+                  )
+                ) {
+                  if (point.dataLabel.getBBox().width > maxWidth) {
+                    point.dataLabel.css({
+                      // Use a fraction of the maxWidth to avoid
+                      // wrapping close to the end of the string.
+                      width: Math.round(maxWidth * 0.7) + "px",
+                    });
+                    point.dataLabel.shortened = true;
+                  }
+                }
+              } else {
+                point.dataLabel = point.dataLabel.destroy();
+                // Workaround to make pies destroy multiple datalabels
+                // correctly. This logic needs rewriting to support multiple
+                // datalabels fully.
+                if (point.dataLabels && point.dataLabels.length === 1) {
+                  delete point.dataLabels;
+                }
+              }
+            }
+          });
+          /* Loop over the points in each half, starting from the top and bottom
+           * of the pie to detect overlapping labels.
+           */
+          halves.forEach(function (points, i) {
+            var top,
+              bottom,
+              length = points.length,
+              positions = [],
+              naturalY,
+              sideOverflow,
+              size,
+              distributionLength;
+            if (!length) {
+              return;
+            }
+            // Sort by angle
+            series.sortByAngle(points, i - 0.5);
+            // Only do anti-collision when we have dataLabels outside the pie
+            // and have connectors. (#856)
+            if (series.maxLabelDistance > 0) {
+              top = Math.max(0, centerY - radius - series.maxLabelDistance);
+              bottom = Math.min(
+                centerY + radius + series.maxLabelDistance,
+                chart.plotHeight
+              );
+              points.forEach(function (point) {
+                // check if specific points' label is outside the pie
+                if (point.labelDistance > 0 && point.dataLabel) {
+                  // point.top depends on point.labelDistance value
+                  // Used for calculation of y value in getX method
+                  point.top = Math.max(
+                    0,
+                    centerY - radius - point.labelDistance
+                  );
+                  point.bottom = Math.min(
+                    centerY + radius + point.labelDistance,
+                    chart.plotHeight
+                  );
+                  size = point.dataLabel.getBBox().height || 21;
+                  // point.positionsIndex is needed for getting index of
+                  // parameter related to specific point inside positions
+                  // array - not every point is in positions array.
+                  point.distributeBox = {
+                    target:
+                      point.labelPosition.natural.y - point.top + size / 2,
+                    size: size,
+                    rank: point.y,
+                  };
+                  positions.push(point.distributeBox);
+                }
+              });
+              distributionLength = bottom + size - top;
+              H.distribute(
+                positions,
+                distributionLength,
+                distributionLength / 5
+              );
+            }
+            // Now the used slots are sorted, fill them up sequentially
+            for (j = 0; j < length; j++) {
+              point = points[j];
+              // labelPos = point.labelPos;
+              labelPosition = point.labelPosition;
+              dataLabel = point.dataLabel;
+              visibility = point.visible === false ? "hidden" : "inherit";
+              naturalY = labelPosition.natural.y;
+              y = naturalY;
+              if (positions && defined(point.distributeBox)) {
+                if (typeof point.distributeBox.pos === "undefined") {
+                  visibility = "hidden";
+                } else {
+                  labelHeight = point.distributeBox.size;
+                  // Find label's y position
+                  y = dataLabelPositioners.radialDistributionY(point);
+                }
+              }
+              // It is needed to delete point.positionIndex for
+              // dynamically added points etc.
+              delete point.positionIndex; // @todo unused
+              // Find label's x position
+              // justify is undocumented in the API - preserve support for it
+              if (options.justify) {
+                x = dataLabelPositioners.justify(point, radius, seriesCenter);
+              } else {
+                switch (options.alignTo) {
+                  case "connectors":
+                    x = dataLabelPositioners.alignToConnectors(
+                      points,
+                      i,
+                      plotWidth,
+                      plotLeft
+                    );
+                    break;
+                  case "plotEdges":
+                    x = dataLabelPositioners.alignToPlotEdges(
+                      dataLabel,
+                      i,
+                      plotWidth,
+                      plotLeft
+                    );
+                    break;
+                  default:
+                    x = dataLabelPositioners.radialDistributionX(
+                      series,
+                      point,
+                      y,
+                      naturalY
+                    );
+                }
+              }
+              // Record the placement and visibility
+              dataLabel._attr = {
+                visibility: visibility,
+                align: labelPosition.alignment,
+              };
+              pointDataLabelsOptions = point.options.dataLabels || {};
+              dataLabel._pos = {
+                x:
+                  x +
+                  pick(pointDataLabelsOptions.x, options.x) + // (#12985)
+                  ({
+                    left: connectorPadding,
+                    right: -connectorPadding,
+                  }[labelPosition.alignment] || 0),
+                // 10 is for the baseline (label vs text)
+                y:
+                  y +
+                  pick(pointDataLabelsOptions.y, options.y) - // (#12985)
+                  10,
+              };
+              // labelPos.x = x;
+              // labelPos.y = y;
+              labelPosition.final.x = x;
+              labelPosition.final.y = y;
+              // Detect overflowing data labels
+              if (pick(options.crop, true)) {
+                dataLabelWidth = dataLabel.getBBox().width;
+                sideOverflow = null;
+                // Overflow left
+                if (
+                  x - dataLabelWidth < connectorPadding &&
+                  i === 1 // left half
+                ) {
+                  sideOverflow = Math.round(
+                    dataLabelWidth - x + connectorPadding
+                  );
+                  overflow[3] = Math.max(sideOverflow, overflow[3]);
+                  // Overflow right
+                } else if (
+                  x + dataLabelWidth > plotWidth - connectorPadding &&
+                  i === 0 // right half
+                ) {
+                  sideOverflow = Math.round(
+                    x + dataLabelWidth - plotWidth + connectorPadding
+                  );
+                  overflow[1] = Math.max(sideOverflow, overflow[1]);
+                }
+                // Overflow top
+                if (y - labelHeight / 2 < 0) {
+                  overflow[0] = Math.max(
+                    Math.round(-y + labelHeight / 2),
+                    overflow[0]
+                  );
+                  // Overflow left
+                } else if (y + labelHeight / 2 > plotHeight) {
+                  overflow[2] = Math.max(
+                    Math.round(y + labelHeight / 2 - plotHeight),
+                    overflow[2]
+                  );
+                }
+                dataLabel.sideOverflow = sideOverflow;
+              }
+            } // for each point
+          }); // for each half
+          // Do not apply the final placement and draw the connectors until we
+          // have verified that labels are not spilling over.
+          if (
+            arrayMax(overflow) === 0 ||
+            this.verifyDataLabelOverflow(overflow)
+          ) {
+            // Place the labels in the final position
+            this.placeDataLabels();
+            this.points.forEach(function (point) {
+              // #8864: every connector can have individual options
+              pointDataLabelsOptions = merge(options, point.options.dataLabels);
+              connectorWidth = pick(pointDataLabelsOptions.connectorWidth, 1);
+              // Draw the connector
+              if (connectorWidth) {
+                var isNew;
+                connector = point.connector;
+                dataLabel = point.dataLabel;
+                if (
+                  dataLabel &&
+                  dataLabel._pos &&
+                  point.visible &&
+                  point.labelDistance > 0
+                ) {
+                  visibility = dataLabel._attr.visibility;
+                  isNew = !connector;
+                  if (isNew) {
+                    point.connector = connector = chart.renderer
+                      .path()
+                      .addClass(
+                        "highcharts-data-label-connector " +
+                          " highcharts-color-" +
+                          point.colorIndex +
+                          (point.className ? " " + point.className : "")
+                      )
+                      .add(series.dataLabelsGroup);
+                    if (!chart.styledMode) {
+                      connector.attr({
+                        "stroke-width": connectorWidth,
+                        stroke:
+                          pointDataLabelsOptions.connectorColor ||
+                          point.color ||
+                          "#666666",
+                      });
+                    }
+                  }
+                  connector[isNew ? "attr" : "animate"]({
+                    d: point.getConnectorPath(),
+                  });
+                  connector.attr("visibility", visibility);
+                } else if (connector) {
+                  point.connector = connector.destroy();
+                }
+              }
+            });
+          }
+        };
         /**
-         * A callback function to gain complete control on when the responsive rule
-         * applies.
+         * Extendable method for getting the path of the connector between the data
+         * label and the pie slice.
          *
-         * @callback Highcharts.ResponsiveCallbackFunction
+         * @private
+         * @function Highcharts.seriesTypes.pie#connectorPath
          *
-         * @param {Highcharts.Chart} this
-         *        Chart context.
+         * @param {*} labelPos
          *
-         * @return {boolean}
-         *         Return `true` if it applies.
+         * @return {Highcharts.SVGPathArray}
          */
+        // TODO: depracated - remove it
+        /*
+            seriesTypes.pie.prototype.connectorPath = function (labelPos) {
+                var x = labelPos.x,
+                        y = labelPos.y;
+                return pick(this.options.dataLabels.softConnector, true) ? [
+                    'M',
+                    // end of the string at the label
+                    x + (labelPos[6] === 'left' ? 5 : -5), y,
+                    'C',
+                    x, y, // first break, next to the label
+                    2 * labelPos[2] - labelPos[4], 2 * labelPos[3] - labelPos[5],
+                    labelPos[2], labelPos[3], // second break
+                    'L',
+                    labelPos[4], labelPos[5] // base
+                ] : [
+                    'M',
+                    // end of the string at the label
+                    x + (labelPos[6] === 'left' ? 5 : -5), y,
+                    'L',
+                    labelPos[2], labelPos[3], // second break
+                    'L',
+                    labelPos[4], labelPos[5] // base
+                ];
+            };
+            */
         /**
-         * Allows setting a set of rules to apply for different screen or chart
-         * sizes. Each rule specifies additional chart options.
+         * Perform the final placement of the data labels after we have verified
+         * that they fall within the plot area.
          *
-         * @sample {highstock} stock/demo/responsive/
-         *         Stock chart
-         * @sample highcharts/responsive/axis/
-         *         Axis
-         * @sample highcharts/responsive/legend/
-         *         Legend
-         * @sample highcharts/responsive/classname/
-         *         Class name
-         *
-         * @since     5.0.0
-         * @apioption responsive
+         * @private
+         * @function Highcharts.seriesTypes.pie#placeDataLabels
+         * @return {void}
          */
+        seriesTypes.pie.prototype.placeDataLabels = function () {
+          this.points.forEach(function (point) {
+            var dataLabel = point.dataLabel,
+              _pos;
+            if (dataLabel && point.visible) {
+              _pos = dataLabel._pos;
+              if (_pos) {
+                // Shorten data labels with ellipsis if they still overflow
+                // after the pie has reached minSize (#223).
+                if (dataLabel.sideOverflow) {
+                  dataLabel._attr.width = Math.max(
+                    dataLabel.getBBox().width - dataLabel.sideOverflow,
+                    0
+                  );
+                  dataLabel.css({
+                    width: dataLabel._attr.width + "px",
+                    textOverflow:
+                      (this.options.dataLabels.style || {}).textOverflow ||
+                      "ellipsis",
+                  });
+                  dataLabel.shortened = true;
+                }
+                dataLabel.attr(dataLabel._attr);
+                dataLabel[dataLabel.moved ? "animate" : "attr"](_pos);
+                dataLabel.moved = true;
+              } else if (dataLabel) {
+                dataLabel.attr({ y: -9999 });
+              }
+            }
+            // Clear for update
+            delete point.distributeBox;
+          }, this);
+        };
+        seriesTypes.pie.prototype.alignDataLabel = noop;
         /**
-         * A set of rules for responsive settings. The rules are executed from
-         * the top down.
+         * Verify whether the data labels are allowed to draw, or we should run more
+         * translation and data label positioning to keep them inside the plot area.
+         * Returns true when data labels are ready to draw.
          *
-         * @sample {highcharts} highcharts/responsive/axis/
-         *         Axis changes
-         * @sample {highstock} highcharts/responsive/axis/
-         *         Axis changes
-         * @sample {highmaps} highcharts/responsive/axis/
-         *         Axis changes
-         *
-         * @type      {Array<*>}
-         * @since     5.0.0
-         * @apioption responsive.rules
-         */
-        /**
-         * A full set of chart options to apply as overrides to the general
-         * chart options. The chart options are applied when the given rule
-         * is active.
-         *
-         * A special case is configuration objects that take arrays, for example
-         * [xAxis](#xAxis), [yAxis](#yAxis) or [series](#series). For these
-         * collections, an `id` option is used to map the new option set to
-         * an existing object. If an existing object of the same id is not found,
-         * the item of the same indexupdated. So for example, setting `chartOptions`
-         * with two series items without an `id`, will cause the existing chart's
-         * two series to be updated with respective options.
-         *
-         * @sample {highstock} stock/demo/responsive/
-         *         Stock chart
-         * @sample highcharts/responsive/axis/
-         *         Axis
-         * @sample highcharts/responsive/legend/
-         *         Legend
-         * @sample highcharts/responsive/classname/
-         *         Class name
-         *
-         * @type      {Highcharts.Options}
-         * @since     5.0.0
-         * @apioption responsive.rules.chartOptions
+         * @private
+         * @function Highcharts.seriesTypes.pie#verifyDataLabelOverflow
+         * @param {Array<number>} overflow
+         * @return {boolean}
          */
+        seriesTypes.pie.prototype.verifyDataLabelOverflow = function (
+          overflow
+        ) {
+          var center = this.center,
+            options = this.options,
+            centerOption = options.center,
+            minSize = options.minSize || 80,
+            newSize = minSize,
+            // If a size is set, return true and don't try to shrink the pie
+            // to fit the labels.
+            ret = options.size !== null;
+          if (!ret) {
+            // Handle horizontal size and center
+            if (centerOption[0] !== null) {
+              // Fixed center
+              newSize = Math.max(
+                center[2] - Math.max(overflow[1], overflow[3]),
+                minSize
+              );
+            } else {
+              // Auto center
+              newSize = Math.max(
+                // horizontal overflow
+                center[2] - overflow[1] - overflow[3],
+                minSize
+              );
+              // horizontal center
+              center[0] += (overflow[3] - overflow[1]) / 2;
+            }
+            // Handle vertical size and center
+            if (centerOption[1] !== null) {
+              // Fixed center
+              newSize = clamp(
+                newSize,
+                minSize,
+                center[2] - Math.max(overflow[0], overflow[2])
+              );
+            } else {
+              // Auto center
+              newSize = clamp(
+                newSize,
+                minSize,
+                // vertical overflow
+                center[2] - overflow[0] - overflow[2]
+              );
+              // vertical center
+              center[1] += (overflow[0] - overflow[2]) / 2;
+            }
+            // If the size must be decreased, we need to run translate and
+            // drawDataLabels again
+            if (newSize < center[2]) {
+              center[2] = newSize;
+              center[3] = Math.min(
+                // #3632
+                relativeLength(options.innerSize || 0, newSize),
+                newSize
+              );
+              this.translate(center);
+              if (this.drawDataLabels) {
+                this.drawDataLabels();
+              }
+              // Else, return true to indicate that the pie and its labels is
+              // within the plot area
+            } else {
+              ret = true;
+            }
+          }
+          return ret;
+        };
+      }
+      if (seriesTypes.column) {
         /**
-         * Under which conditions the rule applies.
+         * Override the basic data label alignment by adjusting for the position of
+         * the column.
          *
-         * @since     5.0.0
-         * @apioption responsive.rules.condition
+         * @private
+         * @function Highcharts.seriesTypes.column#alignDataLabel
+         * @param {Highcharts.Point} point
+         * @param {Highcharts.SVGElement} dataLabel
+         * @param {Highcharts.DataLabelsOptions} options
+         * @param {Highcharts.BBoxObject} alignTo
+         * @param {boolean} [isNew]
+         * @return {void}
          */
-        /**
-         * A callback function to gain complete control on when the responsive
-         * rule applies. Return `true` if it applies. This opens for checking
-         * against other metrics than the chart size, for example the document
-         * size or other elements.
+        seriesTypes.column.prototype.alignDataLabel = function (
+          point,
+          dataLabel,
+          options,
+          alignTo,
+          isNew
+        ) {
+          var inverted = this.chart.inverted,
+            series = point.series,
+            // data label box for alignment
+            dlBox = point.dlBox || point.shapeArgs,
+            below = pick(
+              point.below, // range series
+              point.plotY > pick(this.translatedThreshold, series.yAxis.len)
+            ),
+            // draw it inside the box?
+            inside = pick(options.inside, !!this.options.stacking),
+            overshoot;
+          // Align to the column itself, or the top of it
+          if (dlBox) {
+            // Area range uses this method but not alignTo
+            alignTo = merge(dlBox);
+            if (alignTo.y < 0) {
+              alignTo.height += alignTo.y;
+              alignTo.y = 0;
+            }
+            // If parts of the box overshoots outside the plot area, modify the
+            // box to center the label inside
+            overshoot = alignTo.y + alignTo.height - series.yAxis.len;
+            if (overshoot > 0 && overshoot < alignTo.height) {
+              alignTo.height -= overshoot;
+            }
+            if (inverted) {
+              alignTo = {
+                x: series.yAxis.len - alignTo.y - alignTo.height,
+                y: series.xAxis.len - alignTo.x - alignTo.width,
+                width: alignTo.height,
+                height: alignTo.width,
+              };
+            }
+            // Compute the alignment box
+            if (!inside) {
+              if (inverted) {
+                alignTo.x += below ? 0 : alignTo.width;
+                alignTo.width = 0;
+              } else {
+                alignTo.y += below ? alignTo.height : 0;
+                alignTo.height = 0;
+              }
+            }
+          }
+          // When alignment is undefined (typically columns and bars), display the
+          // individual point below or above the point depending on the threshold
+          options.align = pick(
+            options.align,
+            !inverted || inside ? "center" : below ? "right" : "left"
+          );
+          options.verticalAlign = pick(
+            options.verticalAlign,
+            inverted || inside ? "middle" : below ? "top" : "bottom"
+          );
+          // Call the parent method
+          CartesianSeries.prototype.alignDataLabel.call(
+            this,
+            point,
+            dataLabel,
+            options,
+            alignTo,
+            isNew
+          );
+          // If label was justified and we have contrast, set it:
+          if (options.inside && point.contrastColor) {
+            dataLabel.css({
+              color: point.contrastColor,
+            });
+          }
+        };
+      }
+    }
+  );
+  _registerModule(
+    _modules,
+    "Extensions/OverlappingDataLabels.js",
+    [_modules["Core/Chart/Chart.js"], _modules["Core/Utilities.js"]],
+    function (Chart, U) {
+      /* *
+       *
+       *  Highcharts module to hide overlapping data labels.
+       *  This module is included in Highcharts.
+       *
+       *  (c) 2009-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      var addEvent = U.addEvent,
+        fireEvent = U.fireEvent,
+        isArray = U.isArray,
+        isNumber = U.isNumber,
+        objectEach = U.objectEach,
+        pick = U.pick;
+      /**
+       * Internal type
+       * @private
+       */
+      /* eslint-disable no-invalid-this */
+      // Collect potensial overlapping data labels. Stack labels probably don't need
+      // to be considered because they are usually accompanied by data labels that lie
+      // inside the columns.
+      addEvent(Chart, "render", function collectAndHide() {
+        var labels = [];
+        // Consider external label collectors
+        (this.labelCollectors || []).forEach(function (collector) {
+          labels = labels.concat(collector());
+        });
+        (this.yAxis || []).forEach(function (yAxis) {
+          if (
+            yAxis.stacking &&
+            yAxis.options.stackLabels &&
+            !yAxis.options.stackLabels.allowOverlap
+          ) {
+            objectEach(yAxis.stacking.stacks, function (stack) {
+              objectEach(stack, function (stackItem) {
+                labels.push(stackItem.label);
+              });
+            });
+          }
+        });
+        (this.series || []).forEach(function (series) {
+          var dlOptions = series.options.dataLabels;
+          if (
+            series.visible &&
+            !(dlOptions.enabled === false && !series._hasPointLabels)
+          ) {
+            // #3866
+            (series.nodes || series.points).forEach(function (point) {
+              if (point.visible) {
+                var dataLabels = isArray(point.dataLabels)
+                  ? point.dataLabels
+                  : point.dataLabel
+                  ? [point.dataLabel]
+                  : [];
+                dataLabels.forEach(function (label) {
+                  var options = label.options;
+                  label.labelrank = pick(
+                    options.labelrank,
+                    point.labelrank,
+                    point.shapeArgs && point.shapeArgs.height
+                  ); // #4118
+                  if (!options.allowOverlap) {
+                    labels.push(label);
+                  }
+                });
+              }
+            });
+          }
+        });
+        this.hideOverlappingLabels(labels);
+      });
+      /**
+       * Hide overlapping labels. Labels are moved and faded in and out on zoom to
+       * provide a smooth visual imression.
+       *
+       * @private
+       * @function Highcharts.Chart#hideOverlappingLabels
+       * @param {Array<Highcharts.SVGElement>} labels
+       * Rendered data labels
+       * @requires modules/overlapping-datalabels
+       */
+      Chart.prototype.hideOverlappingLabels = function (labels) {
+        var chart = this,
+          len = labels.length,
+          ren = chart.renderer,
+          label,
+          i,
+          j,
+          label1,
+          label2,
+          box1,
+          box2,
+          isLabelAffected = false,
+          isIntersectRect = function (box1, box2) {
+            return !(
+              box2.x >= box1.x + box1.width ||
+              box2.x + box2.width <= box1.x ||
+              box2.y >= box1.y + box1.height ||
+              box2.y + box2.height <= box1.y
+            );
+          },
+          // Get the box with its position inside the chart, as opposed to getBBox
+          // that only reports the position relative to the parent.
+          getAbsoluteBox = function (label) {
+            var pos,
+              parent,
+              bBox,
+              // Substract the padding if no background or border (#4333)
+              padding = label.box ? 0 : label.padding || 0,
+              lineHeightCorrection = 0,
+              xOffset = 0,
+              boxWidth,
+              alignValue;
+            if (label && (!label.alignAttr || label.placed)) {
+              pos = label.alignAttr || {
+                x: label.attr("x"),
+                y: label.attr("y"),
+              };
+              parent = label.parentGroup;
+              // Get width and height if pure text nodes (stack labels)
+              if (!label.width) {
+                bBox = label.getBBox();
+                label.width = bBox.width;
+                label.height = bBox.height;
+                // Labels positions are computed from top left corner, so
+                // we need to substract the text height from text nodes too.
+                lineHeightCorrection = ren.fontMetrics(null, label.element).h;
+              }
+              boxWidth = label.width - 2 * padding;
+              alignValue = {
+                left: "0",
+                center: "0.5",
+                right: "1",
+              }[label.alignValue];
+              if (alignValue) {
+                xOffset = +alignValue * boxWidth;
+              } else if (
+                isNumber(label.x) &&
+                Math.round(label.x) !== label.translateX
+              ) {
+                xOffset = label.x - label.translateX;
+              }
+              return {
+                x: pos.x + (parent.translateX || 0) + padding - (xOffset || 0),
+                y:
+                  pos.y +
+                  (parent.translateY || 0) +
+                  padding -
+                  lineHeightCorrection,
+                width: label.width - 2 * padding,
+                height: label.height - 2 * padding,
+              };
+            }
+          };
+        for (i = 0; i < len; i++) {
+          label = labels[i];
+          if (label) {
+            // Mark with initial opacity
+            label.oldOpacity = label.opacity;
+            label.newOpacity = 1;
+            label.absoluteBox = getAbsoluteBox(label);
+          }
+        }
+        // Prevent a situation in a gradually rising slope, that each label will
+        // hide the previous one because the previous one always has lower rank.
+        labels.sort(function (a, b) {
+          return (b.labelrank || 0) - (a.labelrank || 0);
+        });
+        // Detect overlapping labels
+        for (i = 0; i < len; i++) {
+          label1 = labels[i];
+          box1 = label1 && label1.absoluteBox;
+          for (j = i + 1; j < len; ++j) {
+            label2 = labels[j];
+            box2 = label2 && label2.absoluteBox;
+            if (
+              box1 &&
+              box2 &&
+              label1 !== label2 && // #6465, polar chart with connectEnds
+              label1.newOpacity !== 0 &&
+              label2.newOpacity !== 0
+            ) {
+              if (isIntersectRect(box1, box2)) {
+                (label1.labelrank < label2.labelrank
+                  ? label1
+                  : label2
+                ).newOpacity = 0;
+              }
+            }
+          }
+        }
+        // Hide or show
+        labels.forEach(function (label) {
+          var complete, newOpacity;
+          if (label) {
+            newOpacity = label.newOpacity;
+            if (label.oldOpacity !== newOpacity) {
+              // Make sure the label is completely hidden to avoid catching
+              // clicks (#4362)
+              if (label.alignAttr && label.placed) {
+                // data labels
+                label[newOpacity ? "removeClass" : "addClass"](
+                  "highcharts-data-label-hidden"
+                );
+                complete = function () {
+                  if (!chart.styledMode) {
+                    label.css({ pointerEvents: newOpacity ? "auto" : "none" });
+                  }
+                  label.visibility = newOpacity ? "inherit" : "hidden";
+                };
+                isLabelAffected = true;
+                // Animate or set the opacity
+                label.alignAttr.opacity = newOpacity;
+                label[label.isOld ? "animate" : "attr"](
+                  label.alignAttr,
+                  null,
+                  complete
+                );
+                fireEvent(chart, "afterHideOverlappingLabel");
+              } else {
+                // other labels, tick labels
+                label.attr({
+                  opacity: newOpacity,
+                });
+              }
+            }
+            label.isOld = true;
+          }
+        });
+        if (isLabelAffected) {
+          fireEvent(chart, "afterHideAllOverlappingLabels");
+        }
+      };
+    }
+  );
+  _registerModule(
+    _modules,
+    "Core/Interaction.js",
+    [
+      _modules["Core/Series/Series.js"],
+      _modules["Core/Chart/Chart.js"],
+      _modules["Core/Globals.js"],
+      _modules["Core/Legend.js"],
+      _modules["Series/LineSeries.js"],
+      _modules["Core/Options.js"],
+      _modules["Core/Series/Point.js"],
+      _modules["Core/Utilities.js"],
+    ],
+    function (BaseSeries, Chart, H, Legend, LineSeries, O, Point, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      var seriesTypes = BaseSeries.seriesTypes;
+      var hasTouch = H.hasTouch,
+        svg = H.svg;
+      var defaultOptions = O.defaultOptions;
+      var addEvent = U.addEvent,
+        createElement = U.createElement,
+        css = U.css,
+        defined = U.defined,
+        extend = U.extend,
+        fireEvent = U.fireEvent,
+        isArray = U.isArray,
+        isFunction = U.isFunction,
+        isNumber = U.isNumber,
+        isObject = U.isObject,
+        merge = U.merge,
+        objectEach = U.objectEach,
+        pick = U.pick;
+      /**
+       * @interface Highcharts.PointEventsOptionsObject
+       */ /**
+       * Fires when the point is selected either programmatically or following a click
+       * on the point. One parameter, `event`, is passed to the function. Returning
+       * `false` cancels the operation.
+       * @name Highcharts.PointEventsOptionsObject#select
+       * @type {Highcharts.PointSelectCallbackFunction|undefined}
+       */ /**
+       * Fires when the point is unselected either programmatically or following a
+       * click on the point. One parameter, `event`, is passed to the function.
+       * Returning `false` cancels the operation.
+       * @name Highcharts.PointEventsOptionsObject#unselect
+       * @type {Highcharts.PointUnselectCallbackFunction|undefined}
+       */
+      /**
+       * Information about the select/unselect event.
+       *
+       * @interface Highcharts.PointInteractionEventObject
+       * @extends global.Event
+       */ /**
+       * @name Highcharts.PointInteractionEventObject#accumulate
+       * @type {boolean}
+       */
+      /**
+       * Gets fired when the point is selected either programmatically or following a
+       * click on the point.
+       *
+       * @callback Highcharts.PointSelectCallbackFunction
+       *
+       * @param {Highcharts.Point} this
+       *        Point where the event occured.
+       *
+       * @param {Highcharts.PointInteractionEventObject} event
+       *        Event that occured.
+       */
+      /**
+       * Fires when the point is unselected either programmatically or following a
+       * click on the point.
+       *
+       * @callback Highcharts.PointUnselectCallbackFunction
+       *
+       * @param {Highcharts.Point} this
+       *        Point where the event occured.
+       *
+       * @param {Highcharts.PointInteractionEventObject} event
+       *        Event that occured.
+       */
+      (""); // detach doclets above
+      /* eslint-disable valid-jsdoc */
+      /**
+       * TrackerMixin for points and graphs.
+       *
+       * @private
+       * @mixin Highcharts.TrackerMixin
+       */
+      var TrackerMixin = (H.TrackerMixin = {
+        /**
+         * Draw the tracker for a point.
          *
-         * @type      {Highcharts.ResponsiveCallbackFunction}
-         * @since     5.0.0
-         * @context   Highcharts.Chart
-         * @apioption responsive.rules.condition.callback
+         * @private
+         * @function Highcharts.TrackerMixin.drawTrackerPoint
+         * @param {Highcharts.Series} this
+         * @fires Highcharts.Series#event:afterDrawTracker
          */
+        drawTrackerPoint: function () {
+          var series = this,
+            chart = series.chart,
+            pointer = chart.pointer,
+            onMouseOver = function (e) {
+              var point = pointer.getPointFromEvent(e);
+              // undefined on graph in scatterchart
+              if (typeof point !== "undefined") {
+                pointer.isDirectTouch = true;
+                point.onMouseOver(e);
+              }
+            },
+            dataLabels;
+          // Add reference to the point
+          series.points.forEach(function (point) {
+            dataLabels = isArray(point.dataLabels)
+              ? point.dataLabels
+              : point.dataLabel
+              ? [point.dataLabel]
+              : [];
+            if (point.graphic) {
+              point.graphic.element.point = point;
+            }
+            dataLabels.forEach(function (dataLabel) {
+              if (dataLabel.div) {
+                dataLabel.div.point = point;
+              } else {
+                dataLabel.element.point = point;
+              }
+            });
+          });
+          // Add the event listeners, we need to do this only once
+          if (!series._hasTracking) {
+            series.trackerGroups.forEach(function (key) {
+              if (series[key]) {
+                // we don't always have dataLabelsGroup
+                series[key]
+                  .addClass("highcharts-tracker")
+                  .on("mouseover", onMouseOver)
+                  .on("mouseout", function (e) {
+                    pointer.onTrackerMouseOut(e);
+                  });
+                if (hasTouch) {
+                  series[key].on("touchstart", onMouseOver);
+                }
+                if (!chart.styledMode && series.options.cursor) {
+                  series[key].css(css).css({ cursor: series.options.cursor });
+                }
+              }
+            });
+            series._hasTracking = true;
+          }
+          fireEvent(this, "afterDrawTracker");
+        },
         /**
-         * The responsive rule applies if the chart height is less than this.
+         * Draw the tracker object that sits above all data labels and markers to
+         * track mouse events on the graph or points. For the line type charts
+         * the tracker uses the same graphPath, but with a greater stroke width
+         * for better control.
          *
-         * @type      {number}
-         * @since     5.0.0
-         * @apioption responsive.rules.condition.maxHeight
-         */
+         * @private
+         * @function Highcharts.TrackerMixin.drawTrackerGraph
+         * @param {Highcharts.Series} this
+         * @fires Highcharts.Series#event:afterDrawTracker
+         */
+        drawTrackerGraph: function () {
+          var series = this,
+            options = series.options,
+            trackByArea = options.trackByArea,
+            trackerPath = [].concat(
+              trackByArea ? series.areaPath : series.graphPath
+            ),
+            // trackerPathLength = trackerPath.length,
+            chart = series.chart,
+            pointer = chart.pointer,
+            renderer = chart.renderer,
+            snap = chart.options.tooltip.snap,
+            tracker = series.tracker,
+            i,
+            onMouseOver = function (e) {
+              if (chart.hoverSeries !== series) {
+                series.onMouseOver();
+              }
+            },
+            /*
+             * Empirical lowest possible opacities for TRACKER_FILL for an
+             * element to stay invisible but clickable
+             * IE6: 0.002
+             * IE7: 0.002
+             * IE8: 0.002
+             * IE9: 0.00000000001 (unlimited)
+             * IE10: 0.0001 (exporting only)
+             * FF: 0.00000000001 (unlimited)
+             * Chrome: 0.000001
+             * Safari: 0.000001
+             * Opera: 0.00000000001 (unlimited)
+             */
+            TRACKER_FILL = "rgba(192,192,192," + (svg ? 0.0001 : 0.002) + ")";
+          // Draw the tracker
+          if (tracker) {
+            tracker.attr({ d: trackerPath });
+          } else if (series.graph) {
+            // create
+            series.tracker = renderer
+              .path(trackerPath)
+              .attr({
+                visibility: series.visible ? "visible" : "hidden",
+                zIndex: 2,
+              })
+              .addClass(
+                trackByArea
+                  ? "highcharts-tracker-area"
+                  : "highcharts-tracker-line"
+              )
+              .add(series.group);
+            if (!chart.styledMode) {
+              series.tracker.attr({
+                "stroke-linecap": "round",
+                "stroke-linejoin": "round",
+                stroke: TRACKER_FILL,
+                fill: trackByArea ? TRACKER_FILL : "none",
+                "stroke-width":
+                  series.graph.strokeWidth() + (trackByArea ? 0 : 2 * snap),
+              });
+            }
+            // The tracker is added to the series group, which is clipped, but
+            // is covered by the marker group. So the marker group also needs to
+            // capture events.
+            [series.tracker, series.markerGroup].forEach(function (tracker) {
+              tracker
+                .addClass("highcharts-tracker")
+                .on("mouseover", onMouseOver)
+                .on("mouseout", function (e) {
+                  pointer.onTrackerMouseOut(e);
+                });
+              if (options.cursor && !chart.styledMode) {
+                tracker.css({ cursor: options.cursor });
+              }
+              if (hasTouch) {
+                tracker.on("touchstart", onMouseOver);
+              }
+            });
+          }
+          fireEvent(this, "afterDrawTracker");
+        },
+      });
+      /* End TrackerMixin */
+      // Add tracking event listener to the series group, so the point graphics
+      // themselves act as trackers
+      if (seriesTypes.column) {
         /**
-         * The responsive rule applies if the chart width is less than this.
-         *
-         * @sample highcharts/responsive/axis/
-         *         Max width is 500
-         *
-         * @type      {number}
-         * @since     5.0.0
-         * @apioption responsive.rules.condition.maxWidth
+         * @private
+         * @borrows Highcharts.TrackerMixin.drawTrackerPoint as Highcharts.seriesTypes.column#drawTracker
          */
+        seriesTypes.column.prototype.drawTracker =
+          TrackerMixin.drawTrackerPoint;
+      }
+      if (seriesTypes.pie) {
         /**
-         * The responsive rule applies if the chart height is greater than this.
-         *
-         * @type      {number}
-         * @default   0
-         * @since     5.0.0
-         * @apioption responsive.rules.condition.minHeight
+         * @private
+         * @borrows Highcharts.TrackerMixin.drawTrackerPoint as Highcharts.seriesTypes.pie#drawTracker
          */
+        seriesTypes.pie.prototype.drawTracker = TrackerMixin.drawTrackerPoint;
+      }
+      if (seriesTypes.scatter) {
         /**
-         * The responsive rule applies if the chart width is greater than this.
-         *
-         * @type      {number}
-         * @default   0
-         * @since     5.0.0
-         * @apioption responsive.rules.condition.minWidth
+         * @private
+         * @borrows Highcharts.TrackerMixin.drawTrackerPoint as Highcharts.seriesTypes.scatter#drawTracker
          */
-        /* eslint-disable no-invalid-this, valid-jsdoc */
+        seriesTypes.scatter.prototype.drawTracker =
+          TrackerMixin.drawTrackerPoint;
+      }
+      // Extend Legend for item events.
+      extend(Legend.prototype, {
         /**
-         * Update the chart based on the current chart/document size and options for
-         * responsiveness.
-         *
          * @private
-         * @function Highcharts.Chart#setResponsive
-         * @param  {boolean} [redraw=true]
-         * @param  {boolean} [reset=false]
-         * Reset by un-applying all rules. Chart.update resets all rules before applying
-         * updated options.
-         */
-        Chart.prototype.setResponsive = function (redraw, reset) {
-            var options = this.options.responsive,
-                ruleIds = [],
-                currentResponsive = this.currentResponsive,
-                currentRuleIds,
-                undoOptions;
-            if (!reset && options && options.rules) {
-                options.rules.forEach(function (rule) {
-                    if (typeof rule._id === 'undefined') {
-                        rule._id = uniqueKey();
-                    }
-                    this.matchResponsiveRule(rule, ruleIds /* , redraw */);
-                }, this);
-            }
-            // Merge matching rules
-            var mergedOptions = merge.apply(0,
-                ruleIds.map(function (ruleId) {
-                    return find(options.rules,
-                function (rule) {
-                        return rule._id === ruleId;
-                }).chartOptions;
-            }));
-            mergedOptions.isResponsiveOptions = true;
-            // Stringified key for the rules that currently apply.
-            ruleIds = (ruleIds.toString() || void 0);
-            currentRuleIds = currentResponsive && currentResponsive.ruleIds;
-            // Changes in what rules apply
-            if (ruleIds !== currentRuleIds) {
-                // Undo previous rules. Before we apply a new set of rules, we need to
-                // roll back completely to base options (#6291).
-                if (currentResponsive) {
-                    this.update(currentResponsive.undoOptions, redraw, true);
-                }
-                if (ruleIds) {
-                    // Get undo-options for matching rules
-                    undoOptions = this.currentOptions(mergedOptions);
-                    undoOptions.isResponsiveOptions = true;
-                    this.currentResponsive = {
-                        ruleIds: ruleIds,
-                        mergedOptions: mergedOptions,
-                        undoOptions: undoOptions
+         * @function Highcharts.Legend#setItemEvents
+         * @param {Highcharts.BubbleLegend|Point|Highcharts.Series} item
+         * @param {Highcharts.SVGElement} legendItem
+         * @param {boolean} [useHTML=false]
+         * @fires Highcharts.Point#event:legendItemClick
+         * @fires Highcharts.Series#event:legendItemClick
+         */
+        setItemEvents: function (item, legendItem, useHTML) {
+          var legend = this,
+            boxWrapper = legend.chart.renderer.boxWrapper,
+            isPoint = item instanceof Point,
+            activeClass =
+              "highcharts-legend-" + (isPoint ? "point" : "series") + "-active",
+            styledMode = legend.chart.styledMode,
+            // When `useHTML`, the symbol is rendered in other group, so
+            // we need to apply events listeners to both places
+            legendItems = useHTML
+              ? [legendItem, item.legendSymbol]
+              : [item.legendGroup];
+          // Set the events on the item group, or in case of useHTML, the item
+          // itself (#1249)
+          legendItems.forEach(function (element) {
+            if (element) {
+              element
+                .on("mouseover", function () {
+                  if (item.visible) {
+                    legend.allItems.forEach(function (inactiveItem) {
+                      if (item !== inactiveItem) {
+                        inactiveItem.setState("inactive", !isPoint);
+                      }
+                    });
+                  }
+                  item.setState("hover");
+                  // A CSS class to dim or hide other than the hovered
+                  // series.
+                  // Works only if hovered series is visible (#10071).
+                  if (item.visible) {
+                    boxWrapper.addClass(activeClass);
+                  }
+                  if (!styledMode) {
+                    legendItem.css(legend.options.itemHoverStyle);
+                  }
+                })
+                .on("mouseout", function () {
+                  if (!legend.chart.styledMode) {
+                    legendItem.css(
+                      merge(
+                        item.visible ? legend.itemStyle : legend.itemHiddenStyle
+                      )
+                    );
+                  }
+                  legend.allItems.forEach(function (inactiveItem) {
+                    if (item !== inactiveItem) {
+                      inactiveItem.setState("", !isPoint);
+                    }
+                  });
+                  // A CSS class to dim or hide other than the hovered
+                  // series.
+                  boxWrapper.removeClass(activeClass);
+                  item.setState();
+                })
+                .on("click", function (event) {
+                  var strLegendItemClick = "legendItemClick",
+                    fnLegendItemClick = function () {
+                      if (item.setVisible) {
+                        item.setVisible();
+                      }
+                      // Reset inactive state
+                      legend.allItems.forEach(function (inactiveItem) {
+                        if (item !== inactiveItem) {
+                          inactiveItem.setState(
+                            item.visible ? "inactive" : "",
+                            !isPoint
+                          );
+                        }
+                      });
                     };
-                    this.update(mergedOptions, redraw, true);
-                }
-                else {
-                    this.currentResponsive = void 0;
-                }
-            }
-        };
-        /**
-         * Handle a single responsiveness rule.
-         *
-         * @private
-         * @function Highcharts.Chart#matchResponsiveRule
-         * @param {Highcharts.ResponsiveRulesOptions} rule
-         * @param {Array<string>} matches
-         */
-        Chart.prototype.matchResponsiveRule = function (rule, matches) {
-            var condition = rule.condition,
-                fn = condition.callback || function () {
-                    return (this.chartWidth <= pick(condition.maxWidth,
-                Number.MAX_VALUE) &&
-                        this.chartHeight <=
-                            pick(condition.maxHeight,
-                Number.MAX_VALUE) &&
-                        this.chartWidth >= pick(condition.minWidth, 0) &&
-                        this.chartHeight >= pick(condition.minHeight, 0));
-            };
-            if (fn.call(this)) {
-                matches.push(rule._id);
+                  // A CSS class to dim or hide other than the hovered
+                  // series. Event handling in iOS causes the activeClass
+                  // to be added prior to click in some cases (#7418).
+                  boxWrapper.removeClass(activeClass);
+                  // Pass over the click/touch event. #4.
+                  event = {
+                    browserEvent: event,
+                  };
+                  // click the name or symbol
+                  if (item.firePointEvent) {
+                    // point
+                    item.firePointEvent(
+                      strLegendItemClick,
+                      event,
+                      fnLegendItemClick
+                    );
+                  } else {
+                    fireEvent(
+                      item,
+                      strLegendItemClick,
+                      event,
+                      fnLegendItemClick
+                    );
+                  }
+                });
             }
-        };
+          });
+        },
         /**
-         * Get the current values for a given set of options. Used before we update
-         * the chart with a new responsiveness rule.
-         *
-         * @todo Restore axis options (by id?). The matching of items in collections
-         * bears resemblance to the oneToOne matching in Chart.update. Probably we can
-         * refactor out that matching and reuse it in both functions.
-         *
          * @private
-         * @function Highcharts.Chart#currentOptions
-         * @param {Highcharts.Options} options
-         * @return {Highcharts.Options}
-         */
-        Chart.prototype.currentOptions = function (options) {
+         * @function Highcharts.Legend#createCheckboxForItem
+         * @param {Highcharts.BubbleLegend|Point|Highcharts.Series} item
+         * @fires Highcharts.Series#event:checkboxClick
+         */
+        createCheckboxForItem: function (item) {
+          var legend = this;
+          item.checkbox = createElement(
+            "input",
+            {
+              type: "checkbox",
+              className: "highcharts-legend-checkbox",
+              checked: item.selected,
+              defaultChecked: item.selected, // required by IE7
+            },
+            legend.options.itemCheckboxStyle,
+            legend.chart.container
+          );
+          addEvent(item.checkbox, "click", function (event) {
+            var target = event.target;
+            fireEvent(
+              item.series || item,
+              "checkboxClick",
+              {
+                checked: target.checked,
+                item: item,
+              },
+              function () {
+                item.select();
+              }
+            );
+          });
+        },
+      });
+      // Extend the Chart object with interaction
+      extend(
+        Chart.prototype,
+        /** @lends Chart.prototype */ {
+          /**
+           * Display the zoom button, so users can reset zoom to the default view
+           * settings.
+           *
+           * @function Highcharts.Chart#showResetZoom
+           *
+           * @fires Highcharts.Chart#event:afterShowResetZoom
+           * @fires Highcharts.Chart#event:beforeShowResetZoom
+           */
+          showResetZoom: function () {
             var chart = this,
-                ret = {};
+              lang = defaultOptions.lang,
+              btnOptions = chart.options.chart.resetZoomButton,
+              theme = btnOptions.theme,
+              states = theme.states,
+              alignTo =
+                btnOptions.relativeTo === "chart" ||
+                btnOptions.relativeTo === "spaceBox"
+                  ? null
+                  : "plotBox";
             /**
-             * Recurse over a set of options and its current values,
-             * and store the current values in the ret object.
+             * @private
              */
-            function getCurrent(options, curr, ret, depth) {
-                var i;
-                objectEach(options, function (val, key) {
-                    if (!depth &&
-                        chart.collectionsWithUpdate.indexOf(key) > -1) {
-                        val = splat(val);
-                        ret[key] = [];
-                        // Iterate over collections like series, xAxis or yAxis and map
-                        // the items by index.
-                        for (i = 0; i < Math.max(val.length, curr[key].length); i++) {
-                            // Item exists in current data (#6347)
-                            if (curr[key][i]) {
-                                // If the item is missing from the new data, we need to
-                                // save the whole config structure. Like when
-                                // responsively updating from a dual axis layout to a
-                                // single axis and back (#13544).
-                                if (val[i] === void 0) {
-                                    ret[key][i] = curr[key][i];
-                                    // Otherwise, proceed
-                                }
-                                else {
-                                    ret[key][i] = {};
-                                    getCurrent(val[i], curr[key][i], ret[key][i], depth + 1);
-                                }
-                            }
-                        }
-                    }
-                    else if (isObject(val)) {
-                        ret[key] = isArray(val) ? [] : {};
-                        getCurrent(val, curr[key] || {}, ret[key], depth + 1);
-                    }
-                    else if (typeof curr[key] === 'undefined') { // #10286
-                        ret[key] = null;
-                    }
-                    else {
-                        ret[key] = curr[key];
-                    }
+            function zoomOut() {
+              chart.zoomOut();
+            }
+            fireEvent(this, "beforeShowResetZoom", null, function () {
+              chart.resetZoomButton = chart.renderer
+                .button(
+                  lang.resetZoom,
+                  null,
+                  null,
+                  zoomOut,
+                  theme,
+                  states && states.hover
+                )
+                .attr({
+                  align: btnOptions.position.align,
+                  title: lang.resetZoomTitle,
+                })
+                .addClass("highcharts-reset-zoom")
+                .add()
+                .align(btnOptions.position, false, alignTo);
+            });
+            fireEvent(this, "afterShowResetZoom");
+          },
+          /**
+           * Zoom the chart out after a user has zoomed in. See also
+           * [Axis.setExtremes](/class-reference/Highcharts.Axis#setExtremes).
+           *
+           * @function Highcharts.Chart#zoomOut
+           *
+           * @fires Highcharts.Chart#event:selection
+           */
+          zoomOut: function () {
+            fireEvent(this, "selection", { resetSelection: true }, this.zoom);
+          },
+          /**
+           * Zoom into a given portion of the chart given by axis coordinates.
+           *
+           * @private
+           * @function Highcharts.Chart#zoom
+           * @param {Highcharts.SelectEventObject} event
+           */
+          zoom: function (event) {
+            var chart = this,
+              hasZoomed,
+              pointer = chart.pointer,
+              displayButton = false,
+              mouseDownPos = chart.inverted
+                ? pointer.mouseDownX
+                : pointer.mouseDownY,
+              resetZoomButton;
+            // If zoom is called with no arguments, reset the axes
+            if (!event || event.resetSelection) {
+              chart.axes.forEach(function (axis) {
+                hasZoomed = axis.zoom();
+              });
+              pointer.initiated = false; // #6804
+            } else {
+              // else, zoom in on all axes
+              event.xAxis.concat(event.yAxis).forEach(function (axisData) {
+                var axis = axisData.axis,
+                  axisStartPos = chart.inverted ? axis.left : axis.top,
+                  axisEndPos = chart.inverted
+                    ? axisStartPos + axis.width
+                    : axisStartPos + axis.height,
+                  isXAxis = axis.isXAxis,
+                  isWithinPane = false;
+                // Check if zoomed area is within the pane (#1289).
+                // In case of multiple panes only one pane should be zoomed.
+                if (
+                  (!isXAxis &&
+                    mouseDownPos >= axisStartPos &&
+                    mouseDownPos <= axisEndPos) ||
+                  isXAxis ||
+                  !defined(mouseDownPos)
+                ) {
+                  isWithinPane = true;
+                }
+                // don't zoom more than minRange
+                if (pointer[isXAxis ? "zoomX" : "zoomY"] && isWithinPane) {
+                  hasZoomed = axis.zoom(axisData.min, axisData.max);
+                  if (axis.displayBtn) {
+                    displayButton = true;
+                  }
+                }
+              });
+            }
+            // Show or hide the Reset zoom button
+            resetZoomButton = chart.resetZoomButton;
+            if (displayButton && !resetZoomButton) {
+              chart.showResetZoom();
+            } else if (!displayButton && isObject(resetZoomButton)) {
+              chart.resetZoomButton = resetZoomButton.destroy();
+            }
+            // Redraw
+            if (hasZoomed) {
+              chart.redraw(
+                pick(
+                  chart.options.chart.animation,
+                  event && event.animation,
+                  chart.pointCount < 100
+                )
+              );
+            }
+          },
+          /**
+           * Pan the chart by dragging the mouse across the pane. This function is
+           * called on mouse move, and the distance to pan is computed from chartX
+           * compared to the first chartX position in the dragging operation.
+           *
+           * @private
+           * @function Highcharts.Chart#pan
+           * @param {Highcharts.PointerEventObject} e
+           * @param {string} panning
+           */
+          pan: function (e, panning) {
+            var chart = this,
+              hoverPoints = chart.hoverPoints,
+              panningOptions,
+              chartOptions = chart.options.chart,
+              hasMapNavigation =
+                chart.options.mapNavigation &&
+                chart.options.mapNavigation.enabled,
+              doRedraw,
+              type;
+            if (typeof panning === "object") {
+              panningOptions = panning;
+            } else {
+              panningOptions = {
+                enabled: panning,
+                type: "x",
+              };
+            }
+            if (chartOptions && chartOptions.panning) {
+              chartOptions.panning = panningOptions;
+            }
+            type = panningOptions.type;
+            fireEvent(this, "pan", { originalEvent: e }, function () {
+              // remove active points for shared tooltip
+              if (hoverPoints) {
+                hoverPoints.forEach(function (point) {
+                  point.setState();
                 });
+              }
+              // panning axis mapping
+              var xy = [1]; // x
+              if (type === "xy") {
+                xy = [1, 0];
+              } else if (type === "y") {
+                xy = [0];
+              }
+              xy.forEach(function (isX) {
+                var axis = chart[isX ? "xAxis" : "yAxis"][0],
+                  horiz = axis.horiz,
+                  mousePos = e[horiz ? "chartX" : "chartY"],
+                  mouseDown = horiz ? "mouseDownX" : "mouseDownY",
+                  startPos = chart[mouseDown],
+                  halfPointRange = (axis.pointRange || 0) / 2,
+                  pointRangeDirection =
+                    (axis.reversed && !chart.inverted) ||
+                    (!axis.reversed && chart.inverted)
+                      ? -1
+                      : 1,
+                  extremes = axis.getExtremes(),
+                  panMin =
+                    axis.toValue(startPos - mousePos, true) +
+                    halfPointRange * pointRangeDirection,
+                  panMax =
+                    axis.toValue(startPos + axis.len - mousePos, true) -
+                    halfPointRange * pointRangeDirection,
+                  flipped = panMax < panMin,
+                  newMin = flipped ? panMax : panMin,
+                  newMax = flipped ? panMin : panMax,
+                  hasVerticalPanning = axis.hasVerticalPanning(),
+                  paddedMin,
+                  paddedMax,
+                  spill,
+                  panningState = axis.panningState;
+                // General calculations of panning state.
+                // This is related to using vertical panning. (#11315).
+                axis.series.forEach(function (series) {
+                  if (
+                    hasVerticalPanning &&
+                    !isX &&
+                    (!panningState || panningState.isDirty)
+                  ) {
+                    var processedData = series.getProcessedData(true),
+                      dataExtremes = series.getExtremes(
+                        processedData.yData,
+                        true
+                      );
+                    if (!panningState) {
+                      panningState = {
+                        startMin: Number.MAX_VALUE,
+                        startMax: -Number.MAX_VALUE,
+                      };
+                    }
+                    if (
+                      isNumber(dataExtremes.dataMin) &&
+                      isNumber(dataExtremes.dataMax)
+                    ) {
+                      panningState.startMin = Math.min(
+                        dataExtremes.dataMin,
+                        panningState.startMin
+                      );
+                      panningState.startMax = Math.max(
+                        dataExtremes.dataMax,
+                        panningState.startMax
+                      );
+                    }
+                  }
+                });
+                paddedMin = Math.min(
+                  pick(
+                    panningState === null || panningState === void 0
+                      ? void 0
+                      : panningState.startMin,
+                    extremes.dataMin
+                  ),
+                  halfPointRange
+                    ? extremes.min
+                    : axis.toValue(
+                        axis.toPixels(extremes.min) - axis.minPixelPadding
+                      )
+                );
+                paddedMax = Math.max(
+                  pick(
+                    panningState === null || panningState === void 0
+                      ? void 0
+                      : panningState.startMax,
+                    extremes.dataMax
+                  ),
+                  halfPointRange
+                    ? extremes.max
+                    : axis.toValue(
+                        axis.toPixels(extremes.max) + axis.minPixelPadding
+                      )
+                );
+                axis.panningState = panningState;
+                // It is not necessary to calculate extremes on ordinal axis,
+                // because they are already calculated, so we don't want to
+                // override them.
+                if (!axis.isOrdinal) {
+                  // If the new range spills over, either to the min or max,
+                  // adjust the new range.
+                  spill = paddedMin - newMin;
+                  if (spill > 0) {
+                    newMax += spill;
+                    newMin = paddedMin;
+                  }
+                  spill = newMax - paddedMax;
+                  if (spill > 0) {
+                    newMax = paddedMax;
+                    newMin -= spill;
+                  }
+                  // Set new extremes if they are actually new
+                  if (
+                    axis.series.length &&
+                    newMin !== extremes.min &&
+                    newMax !== extremes.max &&
+                    newMin >= paddedMin &&
+                    newMax <= paddedMax
+                  ) {
+                    axis.setExtremes(newMin, newMax, false, false, {
+                      trigger: "pan",
+                    });
+                    if (
+                      !chart.resetZoomButton &&
+                      !hasMapNavigation &&
+                      // Show reset zoom button only when both newMin and
+                      // newMax values are between padded axis range.
+                      newMin !== paddedMin &&
+                      newMax !== paddedMax &&
+                      type.match("y")
+                    ) {
+                      chart.showResetZoom();
+                      axis.displayBtn = false;
+                    }
+                    doRedraw = true;
+                  }
+                  // set new reference for next run:
+                  chart[mouseDown] = mousePos;
+                }
+              });
+              if (doRedraw) {
+                chart.redraw(false);
+              }
+              css(chart.container, { cursor: "move" });
+            });
+          },
+        }
+      );
+      // Extend the Point object with interaction
+      extend(
+        Point.prototype,
+        /** @lends Highcharts.Point.prototype */ {
+          /**
+           * Toggle the selection status of a point.
+           *
+           * @see Highcharts.Chart#getSelectedPoints
+           *
+           * @sample highcharts/members/point-select/
+           *         Select a point from a button
+           * @sample highcharts/chart/events-selection-points/
+           *         Select a range of points through a drag selection
+           * @sample maps/series/data-id/
+           *         Select a point in Highmaps
+           *
+           * @function Highcharts.Point#select
+           *
+           * @param {boolean} [selected]
+           * When `true`, the point is selected. When `false`, the point is
+           * unselected. When `null` or `undefined`, the selection state is toggled.
+           *
+           * @param {boolean} [accumulate=false]
+           * When `true`, the selection is added to other selected points.
+           * When `false`, other selected points are deselected. Internally in
+           * Highcharts, when
+           * [allowPointSelect](https://api.highcharts.com/highcharts/plotOptions.series.allowPointSelect)
+           * is `true`, selected points are accumulated on Control, Shift or Cmd
+           * clicking the point.
+           *
+           * @fires Highcharts.Point#event:select
+           * @fires Highcharts.Point#event:unselect
+           */
+          select: function (selected, accumulate) {
+            var point = this,
+              series = point.series,
+              chart = series.chart;
+            selected = pick(selected, !point.selected);
+            this.selectedStaging = selected;
+            // fire the event with the default handler
+            point.firePointEvent(
+              selected ? "select" : "unselect",
+              { accumulate: accumulate },
+              function () {
+                /**
+                 * Whether the point is selected or not.
+                 *
+                 * @see Point#select
+                 * @see Chart#getSelectedPoints
+                 *
+                 * @name Highcharts.Point#selected
+                 * @type {boolean}
+                 */
+                point.selected = point.options.selected = selected;
+                series.options.data[series.data.indexOf(point)] = point.options;
+                point.setState(selected && "select");
+                // unselect all other points unless Ctrl or Cmd + click
+                if (!accumulate) {
+                  chart.getSelectedPoints().forEach(function (loopPoint) {
+                    var loopSeries = loopPoint.series;
+                    if (loopPoint.selected && loopPoint !== point) {
+                      loopPoint.selected = loopPoint.options.selected = false;
+                      loopSeries.options.data[
+                        loopSeries.data.indexOf(loopPoint)
+                      ] = loopPoint.options;
+                      // Programatically selecting a point should restore
+                      // normal state, but when click happened on other
+                      // point, set inactive state to match other points
+                      loopPoint.setState(
+                        chart.hoverPoints &&
+                          loopSeries.options.inactiveOtherPoints
+                          ? "inactive"
+                          : ""
+                      );
+                      loopPoint.firePointEvent("unselect");
+                    }
+                  });
+                }
+              }
+            );
+            delete this.selectedStaging;
+          },
+          /**
+           * Runs on mouse over the point. Called internally from mouse and touch
+           * events.
+           *
+           * @function Highcharts.Point#onMouseOver
+           *
+           * @param {Highcharts.PointerEventObject} [e]
+           *        The event arguments.
+           */
+          onMouseOver: function (e) {
+            var point = this,
+              series = point.series,
+              chart = series.chart,
+              pointer = chart.pointer;
+            e = e
+              ? pointer.normalize(e)
+              : // In cases where onMouseOver is called directly without an event
+                pointer.getChartCoordinatesFromPoint(point, chart.inverted);
+            pointer.runPointActions(e, point);
+          },
+          /**
+           * Runs on mouse out from the point. Called internally from mouse and touch
+           * events.
+           *
+           * @function Highcharts.Point#onMouseOut
+           * @fires Highcharts.Point#event:mouseOut
+           */
+          onMouseOut: function () {
+            var point = this,
+              chart = point.series.chart;
+            point.firePointEvent("mouseOut");
+            if (!point.series.options.inactiveOtherPoints) {
+              (chart.hoverPoints || []).forEach(function (p) {
+                p.setState();
+              });
             }
-            getCurrent(options, this.options, ret, 0);
-            return ret;
-        };
-
-    });
-    _registerModule(_modules, 'masters/highcharts.src.js', [_modules['Core/Globals.js']], function (Highcharts) {
-
-
-        return Highcharts;
-    });
-    _modules['masters/highcharts.src.js']._modules = _modules;
-    return _modules['masters/highcharts.src.js'];
-}));
\ No newline at end of file
+            chart.hoverPoints = chart.hoverPoint = null;
+          },
+          /**
+           * Import events from the series' and point's options. Only do it on
+           * demand, to save processing time on hovering.
+           *
+           * @private
+           * @function Highcharts.Point#importEvents
+           */
+          importEvents: function () {
+            if (!this.hasImportedEvents) {
+              var point = this,
+                options = merge(point.series.options.point, point.options),
+                events = options.events;
+              point.events = events;
+              objectEach(events, function (event, eventType) {
+                if (isFunction(event)) {
+                  addEvent(point, eventType, event);
+                }
+              });
+              this.hasImportedEvents = true;
+            }
+          },
+          /**
+           * Set the point's state.
+           *
+           * @function Highcharts.Point#setState
+           *
+           * @param {Highcharts.PointStateValue|""} [state]
+           *        The new state, can be one of `'hover'`, `'select'`, `'inactive'`,
+           *        or `''` (an empty string), `'normal'` or `undefined` to set to
+           *        normal state.
+           * @param {boolean} [move]
+           *        State for animation.
+           *
+           * @fires Highcharts.Point#event:afterSetState
+           */
+          setState: function (state, move) {
+            var point = this,
+              series = point.series,
+              previousState = point.state,
+              stateOptions = series.options.states[state || "normal"] || {},
+              markerOptions =
+                defaultOptions.plotOptions[series.type].marker &&
+                series.options.marker,
+              normalDisabled = markerOptions && markerOptions.enabled === false,
+              markerStateOptions =
+                (markerOptions &&
+                  markerOptions.states &&
+                  markerOptions.states[state || "normal"]) ||
+                {},
+              stateDisabled = markerStateOptions.enabled === false,
+              stateMarkerGraphic = series.stateMarkerGraphic,
+              pointMarker = point.marker || {},
+              chart = series.chart,
+              halo = series.halo,
+              haloOptions,
+              markerAttribs,
+              pointAttribs,
+              pointAttribsAnimation,
+              hasMarkers = markerOptions && series.markerAttribs,
+              newSymbol;
+            state = state || ""; // empty string
+            if (
+              // already has this state
+              (state === point.state && !move) ||
+              // selected points don't respond to hover
+              (point.selected && state !== "select") ||
+              // series' state options is disabled
+              stateOptions.enabled === false ||
+              // general point marker's state options is disabled
+              (state &&
+                (stateDisabled ||
+                  (normalDisabled && markerStateOptions.enabled === false))) ||
+              // individual point marker's state options is disabled
+              (state &&
+                pointMarker.states &&
+                pointMarker.states[state] &&
+                pointMarker.states[state].enabled === false) // #1610
+            ) {
+              return;
+            }
+            point.state = state;
+            if (hasMarkers) {
+              markerAttribs = series.markerAttribs(point, state);
+            }
+            // Apply hover styles to the existing point
+            if (point.graphic) {
+              if (previousState) {
+                point.graphic.removeClass("highcharts-point-" + previousState);
+              }
+              if (state) {
+                point.graphic.addClass("highcharts-point-" + state);
+              }
+              if (!chart.styledMode) {
+                pointAttribs = series.pointAttribs(point, state);
+                pointAttribsAnimation = pick(
+                  chart.options.chart.animation,
+                  stateOptions.animation
+                );
+                // Some inactive points (e.g. slices in pie) should apply
+                // oppacity also for it's labels
+                if (
+                  series.options.inactiveOtherPoints &&
+                  pointAttribs.opacity
+                ) {
+                  (point.dataLabels || []).forEach(function (label) {
+                    if (label) {
+                      label.animate(
+                        {
+                          opacity: pointAttribs.opacity,
+                        },
+                        pointAttribsAnimation
+                      );
+                    }
+                  });
+                  if (point.connector) {
+                    point.connector.animate(
+                      {
+                        opacity: pointAttribs.opacity,
+                      },
+                      pointAttribsAnimation
+                    );
+                  }
+                }
+                point.graphic.animate(pointAttribs, pointAttribsAnimation);
+              }
+              if (markerAttribs) {
+                point.graphic.animate(
+                  markerAttribs,
+                  pick(
+                    // Turn off globally:
+                    chart.options.chart.animation,
+                    markerStateOptions.animation,
+                    markerOptions.animation
+                  )
+                );
+              }
+              // Zooming in from a range with no markers to a range with markers
+              if (stateMarkerGraphic) {
+                stateMarkerGraphic.hide();
+              }
+            } else {
+              // if a graphic is not applied to each point in the normal state,
+              // create a shared graphic for the hover state
+              if (state && markerStateOptions) {
+                newSymbol = pointMarker.symbol || series.symbol;
+                // If the point has another symbol than the previous one, throw
+                // away the state marker graphic and force a new one (#1459)
+                if (
+                  stateMarkerGraphic &&
+                  stateMarkerGraphic.currentSymbol !== newSymbol
+                ) {
+                  stateMarkerGraphic = stateMarkerGraphic.destroy();
+                }
+                // Add a new state marker graphic
+                if (markerAttribs) {
+                  if (!stateMarkerGraphic) {
+                    if (newSymbol) {
+                      series.stateMarkerGraphic = stateMarkerGraphic =
+                        chart.renderer
+                          .symbol(
+                            newSymbol,
+                            markerAttribs.x,
+                            markerAttribs.y,
+                            markerAttribs.width,
+                            markerAttribs.height
+                          )
+                          .add(series.markerGroup);
+                      stateMarkerGraphic.currentSymbol = newSymbol;
+                    }
+                    // Move the existing graphic
+                  } else {
+                    stateMarkerGraphic[move ? "animate" : "attr"]({
+                      x: markerAttribs.x,
+                      y: markerAttribs.y,
+                    });
+                  }
+                }
+                if (!chart.styledMode && stateMarkerGraphic) {
+                  stateMarkerGraphic.attr(series.pointAttribs(point, state));
+                }
+              }
+              if (stateMarkerGraphic) {
+                stateMarkerGraphic[state && point.isInside ? "show" : "hide"](); // #2450
+                stateMarkerGraphic.element.point = point; // #4310
+              }
+            }
+            // Show me your halo
+            haloOptions = stateOptions.halo;
+            var markerGraphic = point.graphic || stateMarkerGraphic;
+            var markerVisibility =
+              (markerGraphic && markerGraphic.visibility) || "inherit";
+            if (
+              haloOptions &&
+              haloOptions.size &&
+              markerGraphic &&
+              markerVisibility !== "hidden" &&
+              !point.isCluster
+            ) {
+              if (!halo) {
+                series.halo = halo = chart.renderer
+                  .path()
+                  // #5818, #5903, #6705
+                  .add(markerGraphic.parentGroup);
+              }
+              halo.show()[move ? "animate" : "attr"]({
+                d: point.haloPath(haloOptions.size),
+              });
+              halo.attr({
+                class:
+                  "highcharts-halo highcharts-color-" +
+                  pick(point.colorIndex, series.colorIndex) +
+                  (point.className ? " " + point.className : ""),
+                visibility: markerVisibility,
+                zIndex: -1, // #4929, #8276
+              });
+              halo.point = point; // #6055
+              if (!chart.styledMode) {
+                halo.attr(
+                  extend(
+                    {
+                      fill: point.color || series.color,
+                      "fill-opacity": haloOptions.opacity,
+                    },
+                    haloOptions.attributes
+                  )
+                );
+              }
+            } else if (halo && halo.point && halo.point.haloPath) {
+              // Animate back to 0 on the current halo point (#6055)
+              halo.animate(
+                { d: halo.point.haloPath(0) },
+                null,
+                // Hide after unhovering. The `complete` callback runs in the
+                // halo's context (#7681).
+                halo.hide
+              );
+            }
+            fireEvent(point, "afterSetState");
+          },
+          /**
+           * Get the path definition for the halo, which is usually a shadow-like
+           * circle around the currently hovered point.
+           *
+           * @function Highcharts.Point#haloPath
+           *
+           * @param {number} size
+           *        The radius of the circular halo.
+           *
+           * @return {Highcharts.SVGPathArray}
+           *         The path definition.
+           */
+          haloPath: function (size) {
+            var series = this.series,
+              chart = series.chart;
+            return chart.renderer.symbols.circle(
+              Math.floor(this.plotX) - size,
+              this.plotY - size,
+              size * 2,
+              size * 2
+            );
+          },
+        }
+      );
+      // Extend the Series object with interaction
+      extend(
+        LineSeries.prototype,
+        /** @lends Highcharts.Series.prototype */ {
+          /**
+           * Runs on mouse over the series graphical items.
+           *
+           * @function Highcharts.Series#onMouseOver
+           * @fires Highcharts.Series#event:mouseOver
+           */
+          onMouseOver: function () {
+            var series = this,
+              chart = series.chart,
+              hoverSeries = chart.hoverSeries,
+              pointer = chart.pointer;
+            pointer.setHoverChartIndex();
+            // set normal state to previous series
+            if (hoverSeries && hoverSeries !== series) {
+              hoverSeries.onMouseOut();
+            }
+            // trigger the event, but to save processing time,
+            // only if defined
+            if (series.options.events.mouseOver) {
+              fireEvent(series, "mouseOver");
+            }
+            // hover this
+            series.setState("hover");
+            /**
+             * Contains the original hovered series.
+             *
+             * @name Highcharts.Chart#hoverSeries
+             * @type {Highcharts.Series|null}
+             */
+            chart.hoverSeries = series;
+          },
+          /**
+           * Runs on mouse out of the series graphical items.
+           *
+           * @function Highcharts.Series#onMouseOut
+           *
+           * @fires Highcharts.Series#event:mouseOut
+           */
+          onMouseOut: function () {
+            // trigger the event only if listeners exist
+            var series = this,
+              options = series.options,
+              chart = series.chart,
+              tooltip = chart.tooltip,
+              hoverPoint = chart.hoverPoint;
+            // #182, set to null before the mouseOut event fires
+            chart.hoverSeries = null;
+            // trigger mouse out on the point, which must be in this series
+            if (hoverPoint) {
+              hoverPoint.onMouseOut();
+            }
+            // fire the mouse out event
+            if (series && options.events.mouseOut) {
+              fireEvent(series, "mouseOut");
+            }
+            // hide the tooltip
+            if (
+              tooltip &&
+              !series.stickyTracking &&
+              (!tooltip.shared || series.noSharedTooltip)
+            ) {
+              tooltip.hide();
+            }
+            // Reset all inactive states
+            chart.series.forEach(function (s) {
+              s.setState("", true);
+            });
+          },
+          /**
+           * Set the state of the series. Called internally on mouse interaction
+           * operations, but it can also be called directly to visually
+           * highlight a series.
+           *
+           * @function Highcharts.Series#setState
+           *
+           * @param {Highcharts.SeriesStateValue|""} [state]
+           *        The new state, can be either `'hover'`, `'inactive'`, `'select'`,
+           *        or `''` (an empty string), `'normal'` or `undefined` to set to
+           *        normal state.
+           * @param {boolean} [inherit]
+           *        Determines if state should be inherited by points too.
+           */
+          setState: function (state, inherit) {
+            var series = this,
+              options = series.options,
+              graph = series.graph,
+              inactiveOtherPoints = options.inactiveOtherPoints,
+              stateOptions = options.states,
+              lineWidth = options.lineWidth,
+              opacity = options.opacity,
+              // By default a quick animation to hover/inactive,
+              // slower to un-hover
+              stateAnimation = pick(
+                stateOptions[state || "normal"] &&
+                  stateOptions[state || "normal"].animation,
+                series.chart.options.chart.animation
+              ),
+              attribs,
+              i = 0;
+            state = state || "";
+            if (series.state !== state) {
+              // Toggle class names
+              [
+                series.group,
+                series.markerGroup,
+                series.dataLabelsGroup,
+              ].forEach(function (group) {
+                if (group) {
+                  // Old state
+                  if (series.state) {
+                    group.removeClass("highcharts-series-" + series.state);
+                  }
+                  // New state
+                  if (state) {
+                    group.addClass("highcharts-series-" + state);
+                  }
+                }
+              });
+              series.state = state;
+              if (!series.chart.styledMode) {
+                if (
+                  stateOptions[state] &&
+                  stateOptions[state].enabled === false
+                ) {
+                  return;
+                }
+                if (state) {
+                  lineWidth =
+                    stateOptions[state].lineWidth ||
+                    lineWidth + (stateOptions[state].lineWidthPlus || 0); // #4035
+                  opacity = pick(stateOptions[state].opacity, opacity);
+                }
+                if (graph && !graph.dashstyle) {
+                  attribs = {
+                    "stroke-width": lineWidth,
+                  };
+                  // Animate the graph stroke-width.
+                  graph.animate(attribs, stateAnimation);
+                  while (series["zone-graph-" + i]) {
+                    series["zone-graph-" + i].attr(attribs);
+                    i = i + 1;
+                  }
+                }
+                // For some types (pie, networkgraph, sankey) opacity is
+                // resolved on a point level
+                if (!inactiveOtherPoints) {
+                  [
+                    series.group,
+                    series.markerGroup,
+                    series.dataLabelsGroup,
+                    series.labelBySeries,
+                  ].forEach(function (group) {
+                    if (group) {
+                      group.animate(
+                        {
+                          opacity: opacity,
+                        },
+                        stateAnimation
+                      );
+                    }
+                  });
+                }
+              }
+            }
+            // Don't loop over points on a series that doesn't apply inactive state
+            // to siblings markers (e.g. line, column)
+            if (inherit && inactiveOtherPoints && series.points) {
+              series.setAllPointsToState(state);
+            }
+          },
+          /**
+           * Set the state for all points in the series.
+           *
+           * @function Highcharts.Series#setAllPointsToState
+           *
+           * @private
+           *
+           * @param {string} [state]
+           *        Can be either `hover` or undefined to set to normal state.
+           */
+          setAllPointsToState: function (state) {
+            this.points.forEach(function (point) {
+              if (point.setState) {
+                point.setState(state);
+              }
+            });
+          },
+          /**
+           * Show or hide the series.
+           *
+           * @function Highcharts.Series#setVisible
+           *
+           * @param {boolean} [visible]
+           * True to show the series, false to hide. If undefined, the visibility is
+           * toggled.
+           *
+           * @param {boolean} [redraw=true]
+           * Whether to redraw the chart after the series is altered. If doing more
+           * operations on the chart, it is a good idea to set redraw to false and
+           * call {@link Chart#redraw|chart.redraw()} after.
+           *
+           * @fires Highcharts.Series#event:hide
+           * @fires Highcharts.Series#event:show
+           */
+          setVisible: function (vis, redraw) {
+            var series = this,
+              chart = series.chart,
+              legendItem = series.legendItem,
+              showOrHide,
+              ignoreHiddenSeries = chart.options.chart.ignoreHiddenSeries,
+              oldVisibility = series.visible;
+            // if called without an argument, toggle visibility
+            series.visible =
+              vis =
+              series.options.visible =
+              series.userOptions.visible =
+                typeof vis === "undefined" ? !oldVisibility : vis; // #5618
+            showOrHide = vis ? "show" : "hide";
+            // show or hide elements
+            [
+              "group",
+              "dataLabelsGroup",
+              "markerGroup",
+              "tracker",
+              "tt",
+            ].forEach(function (key) {
+              if (series[key]) {
+                series[key][showOrHide]();
+              }
+            });
+            // hide tooltip (#1361)
+            if (
+              chart.hoverSeries === series ||
+              (chart.hoverPoint && chart.hoverPoint.series) === series
+            ) {
+              series.onMouseOut();
+            }
+            if (legendItem) {
+              chart.legend.colorizeItem(series, vis);
+            }
+            // rescale or adapt to resized chart
+            series.isDirty = true;
+            // in a stack, all other series are affected
+            if (series.options.stacking) {
+              chart.series.forEach(function (otherSeries) {
+                if (otherSeries.options.stacking && otherSeries.visible) {
+                  otherSeries.isDirty = true;
+                }
+              });
+            }
+            // show or hide linked series
+            series.linkedSeries.forEach(function (otherSeries) {
+              otherSeries.setVisible(vis, false);
+            });
+            if (ignoreHiddenSeries) {
+              chart.isDirtyBox = true;
+            }
+            fireEvent(series, showOrHide);
+            if (redraw !== false) {
+              chart.redraw();
+            }
+          },
+          /**
+           * Show the series if hidden.
+           *
+           * @sample highcharts/members/series-hide/
+           *         Toggle visibility from a button
+           *
+           * @function Highcharts.Series#show
+           * @fires Highcharts.Series#event:show
+           */
+          show: function () {
+            this.setVisible(true);
+          },
+          /**
+           * Hide the series if visible. If the
+           * [chart.ignoreHiddenSeries](https://api.highcharts.com/highcharts/chart.ignoreHiddenSeries)
+           * option is true, the chart is redrawn without this series.
+           *
+           * @sample highcharts/members/series-hide/
+           *         Toggle visibility from a button
+           *
+           * @function Highcharts.Series#hide
+           * @fires Highcharts.Series#event:hide
+           */
+          hide: function () {
+            this.setVisible(false);
+          },
+          /**
+           * Select or unselect the series. This means its
+           * {@link Highcharts.Series.selected|selected}
+           * property is set, the checkbox in the legend is toggled and when selected,
+           * the series is returned by the {@link Highcharts.Chart#getSelectedSeries}
+           * function.
+           *
+           * @sample highcharts/members/series-select/
+           *         Select a series from a button
+           *
+           * @function Highcharts.Series#select
+           *
+           * @param {boolean} [selected]
+           * True to select the series, false to unselect. If undefined, the selection
+           * state is toggled.
+           *
+           * @fires Highcharts.Series#event:select
+           * @fires Highcharts.Series#event:unselect
+           */
+          select: function (selected) {
+            var series = this;
+            series.selected =
+              selected =
+              this.options.selected =
+                typeof selected === "undefined" ? !series.selected : selected;
+            if (series.checkbox) {
+              series.checkbox.checked = selected;
+            }
+            fireEvent(series, selected ? "select" : "unselect");
+          },
+          /**
+           * @private
+           * @borrows Highcharts.TrackerMixin.drawTrackerGraph as Highcharts.Series#drawTracker
+           */
+          drawTracker: TrackerMixin.drawTrackerGraph,
+        }
+      );
+    }
+  );
+  _registerModule(
+    _modules,
+    "Core/Responsive.js",
+    [_modules["Core/Chart/Chart.js"], _modules["Core/Utilities.js"]],
+    function (Chart, U) {
+      /* *
+       *
+       *  (c) 2010-2020 Torstein Honsi
+       *
+       *  License: www.highcharts.com/license
+       *
+       *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
+       *
+       * */
+      var find = U.find,
+        isArray = U.isArray,
+        isObject = U.isObject,
+        merge = U.merge,
+        objectEach = U.objectEach,
+        pick = U.pick,
+        splat = U.splat,
+        uniqueKey = U.uniqueKey;
+      /**
+       * A callback function to gain complete control on when the responsive rule
+       * applies.
+       *
+       * @callback Highcharts.ResponsiveCallbackFunction
+       *
+       * @param {Highcharts.Chart} this
+       *        Chart context.
+       *
+       * @return {boolean}
+       *         Return `true` if it applies.
+       */
+      /**
+       * Allows setting a set of rules to apply for different screen or chart
+       * sizes. Each rule specifies additional chart options.
+       *
+       * @sample {highstock} stock/demo/responsive/
+       *         Stock chart
+       * @sample highcharts/responsive/axis/
+       *         Axis
+       * @sample highcharts/responsive/legend/
+       *         Legend
+       * @sample highcharts/responsive/classname/
+       *         Class name
+       *
+       * @since     5.0.0
+       * @apioption responsive
+       */
+      /**
+       * A set of rules for responsive settings. The rules are executed from
+       * the top down.
+       *
+       * @sample {highcharts} highcharts/responsive/axis/
+       *         Axis changes
+       * @sample {highstock} highcharts/responsive/axis/
+       *         Axis changes
+       * @sample {highmaps} highcharts/responsive/axis/
+       *         Axis changes
+       *
+       * @type      {Array<*>}
+       * @since     5.0.0
+       * @apioption responsive.rules
+       */
+      /**
+       * A full set of chart options to apply as overrides to the general
+       * chart options. The chart options are applied when the given rule
+       * is active.
+       *
+       * A special case is configuration objects that take arrays, for example
+       * [xAxis](#xAxis), [yAxis](#yAxis) or [series](#series). For these
+       * collections, an `id` option is used to map the new option set to
+       * an existing object. If an existing object of the same id is not found,
+       * the item of the same indexupdated. So for example, setting `chartOptions`
+       * with two series items without an `id`, will cause the existing chart's
+       * two series to be updated with respective options.
+       *
+       * @sample {highstock} stock/demo/responsive/
+       *         Stock chart
+       * @sample highcharts/responsive/axis/
+       *         Axis
+       * @sample highcharts/responsive/legend/
+       *         Legend
+       * @sample highcharts/responsive/classname/
+       *         Class name
+       *
+       * @type      {Highcharts.Options}
+       * @since     5.0.0
+       * @apioption responsive.rules.chartOptions
+       */
+      /**
+       * Under which conditions the rule applies.
+       *
+       * @since     5.0.0
+       * @apioption responsive.rules.condition
+       */
+      /**
+       * A callback function to gain complete control on when the responsive
+       * rule applies. Return `true` if it applies. This opens for checking
+       * against other metrics than the chart size, for example the document
+       * size or other elements.
+       *
+       * @type      {Highcharts.ResponsiveCallbackFunction}
+       * @since     5.0.0
+       * @context   Highcharts.Chart
+       * @apioption responsive.rules.condition.callback
+       */
+      /**
+       * The responsive rule applies if the chart height is less than this.
+       *
+       * @type      {number}
+       * @since     5.0.0
+       * @apioption responsive.rules.condition.maxHeight
+       */
+      /**
+       * The responsive rule applies if the chart width is less than this.
+       *
+       * @sample highcharts/responsive/axis/
+       *         Max width is 500
+       *
+       * @type      {number}
+       * @since     5.0.0
+       * @apioption responsive.rules.condition.maxWidth
+       */
+      /**
+       * The responsive rule applies if the chart height is greater than this.
+       *
+       * @type      {number}
+       * @default   0
+       * @since     5.0.0
+       * @apioption responsive.rules.condition.minHeight
+       */
+      /**
+       * The responsive rule applies if the chart width is greater than this.
+       *
+       * @type      {number}
+       * @default   0
+       * @since     5.0.0
+       * @apioption responsive.rules.condition.minWidth
+       */
+      /* eslint-disable no-invalid-this, valid-jsdoc */
+      /**
+       * Update the chart based on the current chart/document size and options for
+       * responsiveness.
+       *
+       * @private
+       * @function Highcharts.Chart#setResponsive
+       * @param  {boolean} [redraw=true]
+       * @param  {boolean} [reset=false]
+       * Reset by un-applying all rules. Chart.update resets all rules before applying
+       * updated options.
+       */
+      Chart.prototype.setResponsive = function (redraw, reset) {
+        var options = this.options.responsive,
+          ruleIds = [],
+          currentResponsive = this.currentResponsive,
+          currentRuleIds,
+          undoOptions;
+        if (!reset && options && options.rules) {
+          options.rules.forEach(function (rule) {
+            if (typeof rule._id === "undefined") {
+              rule._id = uniqueKey();
+            }
+            this.matchResponsiveRule(rule, ruleIds /* , redraw */);
+          }, this);
+        }
+        // Merge matching rules
+        var mergedOptions = merge.apply(
+          0,
+          ruleIds.map(function (ruleId) {
+            return find(options.rules, function (rule) {
+              return rule._id === ruleId;
+            }).chartOptions;
+          })
+        );
+        mergedOptions.isResponsiveOptions = true;
+        // Stringified key for the rules that currently apply.
+        ruleIds = ruleIds.toString() || void 0;
+        currentRuleIds = currentResponsive && currentResponsive.ruleIds;
+        // Changes in what rules apply
+        if (ruleIds !== currentRuleIds) {
+          // Undo previous rules. Before we apply a new set of rules, we need to
+          // roll back completely to base options (#6291).
+          if (currentResponsive) {
+            this.update(currentResponsive.undoOptions, redraw, true);
+          }
+          if (ruleIds) {
+            // Get undo-options for matching rules
+            undoOptions = this.currentOptions(mergedOptions);
+            undoOptions.isResponsiveOptions = true;
+            this.currentResponsive = {
+              ruleIds: ruleIds,
+              mergedOptions: mergedOptions,
+              undoOptions: undoOptions,
+            };
+            this.update(mergedOptions, redraw, true);
+          } else {
+            this.currentResponsive = void 0;
+          }
+        }
+      };
+      /**
+       * Handle a single responsiveness rule.
+       *
+       * @private
+       * @function Highcharts.Chart#matchResponsiveRule
+       * @param {Highcharts.ResponsiveRulesOptions} rule
+       * @param {Array<string>} matches
+       */
+      Chart.prototype.matchResponsiveRule = function (rule, matches) {
+        var condition = rule.condition,
+          fn =
+            condition.callback ||
+            function () {
+              return (
+                this.chartWidth <= pick(condition.maxWidth, Number.MAX_VALUE) &&
+                this.chartHeight <=
+                  pick(condition.maxHeight, Number.MAX_VALUE) &&
+                this.chartWidth >= pick(condition.minWidth, 0) &&
+                this.chartHeight >= pick(condition.minHeight, 0)
+              );
+            };
+        if (fn.call(this)) {
+          matches.push(rule._id);
+        }
+      };
+      /**
+       * Get the current values for a given set of options. Used before we update
+       * the chart with a new responsiveness rule.
+       *
+       * @todo Restore axis options (by id?). The matching of items in collections
+       * bears resemblance to the oneToOne matching in Chart.update. Probably we can
+       * refactor out that matching and reuse it in both functions.
+       *
+       * @private
+       * @function Highcharts.Chart#currentOptions
+       * @param {Highcharts.Options} options
+       * @return {Highcharts.Options}
+       */
+      Chart.prototype.currentOptions = function (options) {
+        var chart = this,
+          ret = {};
+        /**
+         * Recurse over a set of options and its current values,
+         * and store the current values in the ret object.
+         */
+        function getCurrent(options, curr, ret, depth) {
+          var i;
+          objectEach(options, function (val, key) {
+            if (!depth && chart.collectionsWithUpdate.indexOf(key) > -1) {
+              val = splat(val);
+              ret[key] = [];
+              // Iterate over collections like series, xAxis or yAxis and map
+              // the items by index.
+              for (i = 0; i < Math.max(val.length, curr[key].length); i++) {
+                // Item exists in current data (#6347)
+                if (curr[key][i]) {
+                  // If the item is missing from the new data, we need to
+                  // save the whole config structure. Like when
+                  // responsively updating from a dual axis layout to a
+                  // single axis and back (#13544).
+                  if (val[i] === void 0) {
+                    ret[key][i] = curr[key][i];
+                    // Otherwise, proceed
+                  } else {
+                    ret[key][i] = {};
+                    getCurrent(val[i], curr[key][i], ret[key][i], depth + 1);
+                  }
+                }
+              }
+            } else if (isObject(val)) {
+              ret[key] = isArray(val) ? [] : {};
+              getCurrent(val, curr[key] || {}, ret[key], depth + 1);
+            } else if (typeof curr[key] === "undefined") {
+              // #10286
+              ret[key] = null;
+            } else {
+              ret[key] = curr[key];
+            }
+          });
+        }
+        getCurrent(options, this.options, ret, 0);
+        return ret;
+      };
+    }
+  );
+  _registerModule(
+    _modules,
+    "masters/highcharts.src.js",
+    [_modules["Core/Globals.js"]],
+    function (Highcharts) {
+      return Highcharts;
+    }
+  );
+  _modules["masters/highcharts.src.js"]._modules = _modules;
+  return _modules["masters/highcharts.src.js"];
+});
diff --git a/notemyprogress/lang/en/local_notemyprogress.php b/notemyprogress/lang/en/local_notemyprogress.php
index 23a84b33ac66017a05d991c771b69f267c44262e..fb06870c7d449aa95a06139b3c3ac401cb847132 100644
--- a/notemyprogress/lang/en/local_notemyprogress.php
+++ b/notemyprogress/lang/en/local_notemyprogress.php
@@ -715,9 +715,10 @@ $string['fml_settings_bddname_description'] = 'This parameter designates the nam
 $string['fml_settings_bddname_default'] = 'Empty';
 
 /* Gamification */
-$string['studentRanking1']="¿Quieres aparecer en el ranking ? ";
-$string['studentRanking2']="/!\ Te verán todos los inscritos en este curso que hayan aceptado. Aceptar es definitivo: ";
-$string['studentRanking3']="Acceptar";
+$string['EnableGame']="Disable/Enable :";
+$string['studentRanking1']="Do you want to appear in the Ranking Board ?";
+$string['studentRanking2']=" /!\ All the registered in this course having accepted you will see. Accepting is final:";
+$string['studentRanking3']="Accept";
 $string['gamification_denied'] = 'gamification has been desactivated by your teacher';
 $string['tg_colon'] = '{$a->a}: {$a->b}';
 $string['tg_section_title'] = 'Course gamification settings';
@@ -751,7 +752,7 @@ $string['tg_section_settings_appearance_title'] = 'Title';
 $string['tg_section_settings_levels'] = 'Level settings';
 $string['tg_section_settings_levels_quantity'] = 'Levels';
 $string['tg_section_settings_levels_base_points'] = 'Base Points';
-$string['tg_section_settings_levels_calculated'] = 'Calculated';
+$string['tg_section_settings_levels_calculated'] = 'Automatic';
 $string['tg_section_settings_levels_manually'] = 'Manually';
 $string['tg_section_settings_levels_name'] = 'Name';
 $string['tg_section_settings_levels_required'] = 'Points required';
@@ -759,6 +760,8 @@ $string['tg_section_settings_rules'] = 'Rules setting';
 $string['tg_section_settings_add_rule'] = 'Add new rule';
 $string['tg_section_settings_earn'] = 'For this event win:';
 $string['tg_section_settings_select_event'] = 'Select an event';
+$string['gm_Chart_Title']='Spreading chart';
+$string['gm_Chart_Y']='Students';
 
 $string['tg_timenow'] = 'Just now';
 $string['tg_timeseconds'] = '{$a}s ago';
@@ -778,3 +781,9 @@ $string['fml_api_invalid_transaction'] = 'The request is incorrect';
 $string['fml_api_invalid_profile'] = 'You cannot do this action, your profile is incorrect';
 $string['fml_api_save_successful'] = 'The data has been successfully saved on the server';
 $string['fml_api_cancel_action'] = 'You have canceled the action';
+$string['overview']='Overview : ';
+$string['game_point_error']='Points are required';
+$string['game_event_error']='Event is required';
+$string['game_name_error']='Name required';
+
+
diff --git a/notemyprogress/lang/es/local_notemyprogress.php b/notemyprogress/lang/es/local_notemyprogress.php
index 48b7d7c101a7f47f52512271899e26eb4334bca8..2269b8bc9dfe1ef99949cd7f8648d6a82fac248e 100644
--- a/notemyprogress/lang/es/local_notemyprogress.php
+++ b/notemyprogress/lang/es/local_notemyprogress.php
@@ -715,68 +715,73 @@ $string['fml_settings_bddname_label'] = 'Nombre de la base de datos';
 $string['fml_settings_bddname_description'] = 'Este parámetro designa el nombre de la base de datos MongoDB en la que se guardará la información.';
 $string['fml_settings_bddname_default'] = 'Vacío';
 /* Gamification */
-$string['studentRanking1']="Do you want to appear in the Ranking Board ?";
-$string['studentRanking2']=" /!\ All the registered in this course having accepted you will see. Accepting is final:";
-$string['studentRanking3']="Accept";
-$string['gamification_denied'] = 'gamification has been desactivated by your teacher';
+$string['EnableGame']="Desactivar/Activar :";
+$string['studentRanking1']="¿Quieres aparecer en el ranking ? ";
+$string['studentRanking2']="/!\ Te verán todos los inscritos en este curso que hayan aceptado. Aceptar es definitivo: ";
+$string['studentRanking3']="Acceptar";
+$string['gamification_denied'] = 'La gamificación ha sido desactivada por su maestro';
 $string['tg_colon'] = '{$a->a}: {$a->b}';
-$string['tg_section_title'] = 'Course gamification settings';
-$string['tg_section_help_title'] = 'Course gamification settings';
-$string['tg_section_help_description'] = 'You can give the option of gamification to the students of the course.';
-$string['tg_save_warning_title'] = "Are you sure you want to save the changes?";
-$string['tg_save_warning_content'] = "If you change the settings for the gamification when the course has already started, data may be lost...";
-$string['tg_confirm_ok'] = "Save";
-$string['tg_confirm_cancel'] = "Cancel";
-$string['tg_save'] = "Save configuration";
-$string['tg_section_preview'] = 'Preview';
-$string['tg_section_experience'] = 'Experience points';
-$string['tg_section_information'] = 'Information';
-$string['tg_section_ranking'] = 'Ranking/Report';
-$string['tg_section_settings'] = 'Settings';
-
-$string['tg_section_points'] = 'points';
-$string['tg_section_description'] = 'Description';
-$string['tg_section_no_description'] = 'No description';
-$string['tg_section_no_name'] = 'No name';
-
-$string['tg_section_preview_next_level'] = 'to the next level';
-$string['tg_section_ranking_ranking_text'] = 'Ranking';
-$string['tg_section_ranking_level'] = 'Level';
-$string['tg_section_ranking_student'] = 'Student';
+$string['tg_section_title'] = 'Configuración de gamificación del curso';
+$string['tg_section_help_title'] = 'Configuración de gamificación del curso';
+$string['tg_section_help_description'] = 'Puede dar la opción de gamificación a los estudiantes del curso.';
+$string['tg_save_warning_title'] = "¿Estás seguro de que quieres guardar los cambios?";
+$string['tg_save_warning_content'] = "Si cambia la configuración de la gamificación cuando el curso ya ha comenzado, los datos pueden perderse ...";
+$string['tg_confirm_ok'] = "Guardar";
+$string['tg_confirm_cancel'] = "Cancelar";
+$string['tg_save'] = "Guardar configuración";
+$string['tg_section_preview'] = 'Avance';
+$string['tg_section_experience'] = 'Puntos de experiencia';
+$string['tg_section_information'] = 'Información';
+$string['tg_section_ranking'] = 'Clasificación/informe';
+$string['tg_section_settings'] = 'Ajustes';
+
+$string['tg_section_points'] = 'puntos';
+$string['tg_section_description'] = 'Descripción';
+$string['tg_section_no_description'] = 'Sin descripción';
+$string['tg_section_no_name'] = 'Sin nombre';
+
+$string['tg_section_preview_next_level'] = 'al siguiente nivel';
+$string['tg_section_ranking_ranking_text'] = 'Clasificación';
+$string['tg_section_ranking_level'] = 'Nivel';
+$string['tg_section_ranking_student'] = 'Alumna';
 $string['tg_section_ranking_total'] = 'Total';
-$string['tg_section_ranking_progress'] = 'Progress %';
-
-$string['tg_section_settings_appearance'] = 'Appearance';
-$string['tg_section_settings_appearance_title'] = 'Title';
-$string['tg_section_settings_levels'] = 'Level settings';
-$string['tg_section_settings_levels_quantity'] = 'Levels';
-$string['tg_section_settings_levels_base_points'] = 'Base Points';
-$string['tg_section_settings_levels_calculated'] = 'Calculated';
-$string['tg_section_settings_levels_manually'] = 'Manually';
-$string['tg_section_settings_levels_name'] = 'Name';
-$string['tg_section_settings_levels_required'] = 'Points required';
-$string['tg_section_settings_rules'] = 'Rules setting';
-$string['tg_section_settings_add_rule'] = 'Add new rule';
-$string['tg_section_settings_earn'] = 'For this event win:';
-$string['tg_section_settings_select_event'] = 'Select an event';
-
-$string['tg_timenow'] = 'Just now';
-$string['tg_timeseconds'] = '{$a}s ago';
-$string['tg_timeminutes'] = '{$a}m ago';
-$string['tg_timehours'] = '{$a}h ago';
-$string['tg_timedays'] = '{$a}d ago';
-$string['tg_timeweeks'] = '{$a}w ago';
+$string['tg_section_ranking_progress'] = 'Progreso %';
+
+$string['tg_section_settings_appearance'] = 'Apariencia';
+$string['tg_section_settings_appearance_title'] = 'Título';
+$string['tg_section_settings_levels'] = 'Configuración de nivel';
+$string['tg_section_settings_levels_quantity'] = 'Nivel';
+$string['tg_section_settings_levels_base_points'] = 'Puntos base';
+$string['tg_section_settings_levels_calculated'] = 'automático';
+$string['tg_section_settings_levels_manually'] = 'A mano';
+$string['tg_section_settings_levels_name'] = 'Nombre';
+$string['tg_section_settings_levels_required'] = 'Se requieren puntos';
+$string['tg_section_settings_rules'] = 'Establecimiento de reglas';
+$string['tg_section_settings_add_rule'] = 'Agregar nueva regla';
+$string['tg_section_settings_earn'] = 'Para este evento, gane:';
+$string['tg_section_settings_select_event'] = 'Seleccione un evento';
+$string['gm_Chart_Title']='Tabla de esparcimiento';
+$string['gm_Chart_Y']='Alumno';
+
+$string['tg_timenow'] = 'Justo ahora';
+$string['tg_timeseconds'] = '{$a}s atrás';
+$string['tg_timeminutes'] = '{$a}m atrás';
+$string['tg_timehours'] = '{$a}h atrás';
+$string['tg_timedays'] = '{$a}d atrás';
+$string['tg_timeweeks'] = '{$a}w atrás';
 $string['tg_timewithinayearformat'] = '%b %e';
 $string['tg_timeolderyearformat'] = '%b %Y';
 
 /* General Errors */
-$string['fml_api_error_network'] = "An error has occurred in communication with the server.";
-$string['fml_api_invalid_data'] = 'Incorrect data';
-$string['fml_api_json_decode_error'] = 'Error Decoding sent data';
-$string['fml_api_invalid_token_error'] = 'The token sent in the transaction is invalid, please refresh the page';
-$string['fml_api_invalid_transaction'] = 'The request is incorrect';
-$string['fml_api_invalid_profile'] = 'You cannot do this action, your profile is incorrect';
-$string['fml_api_save_successful'] = 'The data has been successfully saved on the server';
-$string['fml_api_cancel_action'] = 'You have canceled the action';
-
-
+$string['fml_api_error_network'] = "Se ha producido un error en la comunicación con el servidor.";
+$string['fml_api_invalid_data'] = 'Datos Incorrectos';
+$string['fml_api_json_decode_error'] = 'Error en decodificación de datos enviados';
+$string['fml_api_invalid_token_error'] = 'El token enviado en la transacción no es válido, actualice la página';
+$string['fml_api_invalid_transaction'] = 'La solicitud es incorrecta';
+$string['fml_api_invalid_profile'] = 'No puedes hacer esta acción, tu perfil es incorrecto';
+$string['fml_api_save_successful'] = 'Los datos se han guardado correctamente en el servidor';
+$string['fml_api_cancel_action'] = 'Has cancelado la acción';
+$string['overview']='Visión de conjunto : ';
+$string['game_point_error']='Los puntos son requeridos';
+$string['game_event_error']='El evento es requerido';
+$string['game_name_error']='Se requiere el nombre';
diff --git a/notemyprogress/lang/fr/local_notemyprogress.php b/notemyprogress/lang/fr/local_notemyprogress.php
index 1e23153d967686d30b4bfac08934d68f79628535..e1430c57874519e1e1d4624de6789f5d4fd860c1 100644
--- a/notemyprogress/lang/fr/local_notemyprogress.php
+++ b/notemyprogress/lang/fr/local_notemyprogress.php
@@ -720,66 +720,73 @@ $string['fml_settings_bddname_label'] = 'Nom de la base de données';
 $string['fml_settings_bddname_description'] = 'Ce paramètre désigne le nom de la base de données MongoDB dans laquelle vont être enregistrées les informations.';
 
 /* Gamification */
+$string['EnableGame']="Désactiver/Activer :";
 $string['studentRanking1']="Voulez vous apparaitre dans le ranking board ? ";
-$string['studentRanking2']= "/!\ tout les inscrits à ce cours ayant accepté vous verrons) accepter est définitif:";
+$string['studentRanking2']= "/!\ Tout les inscrits à ce cours ayant accepté vous verrons. Accepter est définitif:";
 $string['studentRanking3']="Accepter";
-$string['gamification_denied'] = 'gamification has been desactivated by your teacher';
+$string['gamification_denied'] = 'La gamification a été désactivée par votre professeur';
 $string['tg_colon'] = '{$a->a}: {$a->b}';
-$string['tg_section_title'] = 'Course gamification settings';
-$string['tg_section_help_title'] = 'Course gamification settings';
-$string['tg_section_help_description'] = 'You can give the option of gamification to the students of the course.';
-$string['tg_save_warning_title'] = "Are you sure you want to save the changes?";
-$string['tg_save_warning_content'] = "If you change the settings for the gamification when the course has already started, data may be lost...";
-$string['tg_confirm_ok'] = "Save";
-$string['tg_confirm_cancel'] = "Cancel";
-$string['tg_save'] = "Save configuration";
+$string['tg_section_title'] = 'Gamification :';
+$string['tg_section_help_title'] = 'Paramètres de gamification des cours';
+$string['tg_section_help_description'] = 'Vous pouvez donner la possibilité de gamification aux étudiants du cours.';
+$string['tg_save_warning_title'] = "Êtes-vous sûr de vouloir enregistrer les modifications?";
+$string['tg_save_warning_content'] = "Si vous modifiez les paramètres de la gamification au début du cours, les données peuvent être perdues ...";
+$string['tg_confirm_ok'] = "Sauver";
+$string['tg_confirm_cancel'] = "Annuler";
+$string['tg_save'] = "Enregistrer la configuration";
 $string['tg_section_preview'] = 'Point de vue étudiant';
-$string['tg_section_experience'] = 'Experience points';
+$string['tg_section_experience'] = 'Points d\'experience';
 $string['tg_section_information'] = 'Information';
-$string['tg_section_ranking'] = 'Ranking/Report';
-$string['tg_section_settings'] = 'Settings';
+$string['tg_section_ranking'] = 'Classement / rapport';
+$string['tg_section_settings'] = 'Réglages';
 
 $string['tg_section_points'] = 'points';
 $string['tg_section_description'] = 'Description';
-$string['tg_section_no_description'] = 'No description';
-$string['tg_section_no_name'] = 'No name';
+$string['tg_section_no_description'] = 'Pas de description';
+$string['tg_section_no_name'] = 'Sans nom';
 
-$string['tg_section_preview_next_level'] = 'to the next level';
-$string['tg_section_ranking_ranking_text'] = 'Ranking';
-$string['tg_section_ranking_level'] = 'Level';
-$string['tg_section_ranking_student'] = 'Student';
+$string['tg_section_preview_next_level'] = 'au niveau supérieur';
+$string['tg_section_ranking_ranking_text'] = 'Classement';
+$string['tg_section_ranking_level'] = 'Niveau';
+$string['tg_section_ranking_student'] = 'Élève';
 $string['tg_section_ranking_total'] = 'Total';
-$string['tg_section_ranking_progress'] = 'Progress %';
-
-$string['tg_section_settings_appearance'] = 'Appearance';
-$string['tg_section_settings_appearance_title'] = 'Title';
-$string['tg_section_settings_levels'] = 'Level settings';
-$string['tg_section_settings_levels_quantity'] = 'Levels';
-$string['tg_section_settings_levels_base_points'] = 'Base Points';
-$string['tg_section_settings_levels_calculated'] = 'Calculated';
-$string['tg_section_settings_levels_manually'] = 'Manually';
-$string['tg_section_settings_levels_name'] = 'Name';
-$string['tg_section_settings_levels_required'] = 'Points required';
-$string['tg_section_settings_rules'] = 'Rules setting';
-$string['tg_section_settings_add_rule'] = 'Add new rule';
-$string['tg_section_settings_earn'] = 'For this event win:';
-$string['tg_section_settings_select_event'] = 'Select an event';
-
-$string['tg_timenow'] = 'Just now';
-$string['tg_timeseconds'] = '{$a}s ago';
-$string['tg_timeminutes'] = '{$a}m ago';
-$string['tg_timehours'] = '{$a}h ago';
-$string['tg_timedays'] = '{$a}d ago';
-$string['tg_timeweeks'] = '{$a}w ago';
+$string['tg_section_ranking_progress'] ='Progréssion %';
+
+$string['tg_section_settings_appearance'] = 'Apparence';
+$string['tg_section_settings_appearance_title'] = 'Titre';
+$string['tg_section_settings_levels'] = 'Paramètres de niveau';
+$string['tg_section_settings_levels_quantity'] = 'Niveaux';
+$string['tg_section_settings_levels_base_points'] = 'Points de base';
+$string['tg_section_settings_levels_calculated'] = 'Automatique';
+$string['tg_section_settings_levels_manually'] = 'Manuellement';
+$string['tg_section_settings_levels_name'] = 'Nom';
+$string['tg_section_settings_levels_required'] = 'Points requis';
+$string['tg_section_settings_rules'] = 'Liste des régles';
+$string['tg_section_settings_add_rule'] = 'Nouvelle règle';
+$string['tg_section_settings_earn'] = 'Pour cet événement, victoire:';
+$string['tg_section_settings_select_event'] = 'Sélectionnez un événement';
+$string['gm_Chart_Title']='Graphique de répartion';
+$string['gm_Chart_Y']='Etudiants';
+
+$string['tg_timenow'] = 'Juste maintenant';
+$string['tg_timeseconds'] = 'il y a {$a}s ';
+$string['tg_timeminutes'] = 'il y a {$a}m ';
+$string['tg_timehours'] = 'il y a {$a}h ';
+$string['tg_timedays'] = 'il y a {$a}d ';
+$string['tg_timeweeks'] = 'il y a {$a}w ';
 $string['tg_timewithinayearformat'] = '%b %e';
 $string['tg_timeolderyearformat'] = '%b %Y';
 
 /* General Errors */
-$string['fml_api_error_network'] = "An error has occurred in communication with the server.";
-$string['fml_api_invalid_data'] = 'Incorrect data';
-$string['fml_api_json_decode_error'] = 'Error Decoding sent data';
-$string['fml_api_invalid_token_error'] = 'The token sent in the transaction is invalid, please refresh the page';
-$string['fml_api_invalid_transaction'] = 'The request is incorrect';
-$string['fml_api_invalid_profile'] = 'You cannot do this action, your profile is incorrect';
-$string['fml_api_save_successful'] = 'The data has been successfully saved on the server';
-$string['fml_api_cancel_action'] = 'You have canceled the action';
+$string['fml_api_error_network'] = "Une erreur s'est produite dans la communication avec le serveur.";
+$string['fml_api_invalid_data'] = 'Données incorrectes';
+$string['fml_api_json_decode_error'] = 'Décodage d erreur de données envoyées';
+$string['fml_api_invalid_token_error'] = 'Le jeton envoyé dans la transaction n\'est pas valide, veuillez actualiser la page';
+$string['fml_api_invalid_transaction'] = 'La demande est incorrecte';
+$string['fml_api_invalid_profile'] = 'Vous ne pouvez pas faire cette action, votre profil est incorrect';
+$string['fml_api_save_successful'] = 'Les données ont été enregistrées avec succès sur le serveur';
+$string['fml_api_cancel_action'] = 'Vous avez annulé l\'action';
+$string['overview']='Vue d\'ensemble : ';
+$string['game_point_error']='Veuillez saisir les points';
+$string['game_event_error']='Veuillez saisir l\'évènement';
+$string['game_name_error']='Le nom est requis';
\ No newline at end of file
diff --git a/notemyprogress/locallib.php b/notemyprogress/locallib.php
index d329f48140b9d09945b09b2d69c1809992c11c43..5e207f8df4b71f357b68219ecf43d7d58bfbaeea 100644
--- a/notemyprogress/locallib.php
+++ b/notemyprogress/locallib.php
@@ -185,16 +185,18 @@ function local_notemyprogress_validate_token($token){
         local_notemyprogress_ajax_response(null, $message, false, 403);
     }
     function local_notemyprogress_save_gamification_config($courseid, $userid, $rules, $levels, $settings, $url,$enable){
-        //    \local_notemyprogress\logs::create(
-        //        "setgamification",
-        //        "configweeks",
-        //        "saved",
-        //        "weeks_settings",
-        //        $url,
-        //        4,
-        //        $userid,
-        //        $courseid
-        //    );
+            // \local_notemyprogress\logs::create(
+            //     "setgamification",
+            //     "configweeks",
+            //     "saved",
+            //     "weeks_settings",
+            //     $url,
+            //     4,
+            //     $userid,
+            //     $courseid
+            // );
+            $logs = new \local_notemyprogress\logs($courseid, $userid);
+            $logs->addLogsNMP("Saved", "section", "CONFIGURATION_GAMIFICATION", "configuration_gamification", $url, "GamificationSaved");
         
             $configLevels = new \local_notemyprogress\configgamification($courseid, $userid);
             $configLevels->save_levels($levels, $settings, $rules);
diff --git a/notemyprogress/pix/rankImage.jpg b/notemyprogress/pix/rankImage.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..d76465c8405a7cbe5825e39e070d0709e5d4b493
Binary files /dev/null and b/notemyprogress/pix/rankImage.jpg differ
diff --git a/notemyprogress/student_gamification.php b/notemyprogress/student_gamification.php
index 78307ad3d2e2f7bdc6a85b7d193a22719659115a..0ebb905fc2ae58fef0871d6bb6171302f16129ea 100644
--- a/notemyprogress/student_gamification.php
+++ b/notemyprogress/student_gamification.php
@@ -75,15 +75,17 @@ $content = [
         'studentRanking1'=>get_string("studentRanking1","local_notemyprogress"),
         'studentRanking2'=>get_string("studentRanking2","local_notemyprogress"),
         'studentRanking3'=>get_string("studentRanking3","local_notemyprogress"),
+        'overview'=>get_string("overview","local_notemyprogress"),
     ],
     'levels_data' => $configgamification->get_levels_data(),
     'indicators' => $es->get_user_info(),
-    'ranking' => $es->get_ranking(),
+    'ranking' => $es->get_ranking(1),
     
 ];
 
 $templatecontext = [
-    'image' => $OUTPUT->image_url('badge', 'local_notemyprogress')
+    'image' => $OUTPUT->image_url('badge', 'local_notemyprogress'),
+    'rankImage' => $OUTPUT->image_url('rankImage', 'local_notemyprogress')
 ];
 
 $maxTimeSql = "SELECT MAX(timecreated) as maximum from {notemyprogress_gamification} where courseid=? ";
diff --git a/notemyprogress/templates/gamification.mustache b/notemyprogress/templates/gamification.mustache
index 0b750072fdf2c086949f029245db1528e26264b1..c40a8ac215b5265c43df7a50cc3a46dba30f9185 100644
--- a/notemyprogress/templates/gamification.mustache
+++ b/notemyprogress/templates/gamification.mustache
@@ -5,250 +5,253 @@
                     :exitbutton="strings.exitbutton"
                     :helpcontents="get_help_content()"
                     :token="token"
-                    @open_help_section_modal="openHelpSectionModalEvent"
-        >
+                    @open_help_section_modal="openHelpSectionModalEvent">
         </pageheader>
         <template>
-            <!-- Server message -->
-            <v-row class="justify-center" v-if="notifications.length > 0">
-                <v-col cols="8">
-                    <v-alert v-for="(value, index, key) in notifications" :key="key"
-                             :type="value.type" border="left" class="text-center" dense text dismissible>
-                        <span v-text="value.message"></span>
-                    </v-alert>
-                </v-col>
-            </v-row>
-            <v-row>
-                <v-card 
-                    class="align-center text-center flex"
-                    height="100"
-                    >
-                    <h4>Disable / Enable : <h4>
-                    <v-switch
-                        :input-value="false"
-                        v-model ="swDisableEnable"
-                        inset
-                        color="red darken-3"
-                        class="pt-800 px-800 justify-center"
-                        @Change = disableEnable(swDisableEnable);
-                    ></v-switch>
-                </v-card>
-            <v-row>
-            <v-card
-            width = '100%'>
-                <v-row>
-                    <v-col>
-                        <v-tabs v-model="tab" background-color="transparent">
-                            <v-tab v-text="strings.settings_level"></v-tab>
-                            <v-tab v-text="strings.preview"></v-tab>
-                            <v-tab v-text="strings.settings"></v-tab>
-                        </v-tabs>
-                        <v-tabs-items v-model="tab">
-                            <v-tab-item> <!-- Level and settings  -->
-                                <v-row class="pt-8 px-8 justify-center">
-                                    <v-row>
-                                    <v-col cols="6" sm="4" md="3" lg="5">
-                                        <v-text-field
-                                                type="number"
-                                                readonly
-                                                :label="strings.quantity"
-                                                v-model="levelsData.length"
-                                                append-outer-icon="mdi-plus-circle"
-                                                prepend-icon="mdi-minus-circle"
-                                                @click:append-outer="addLevel()"
-                                                @click:prepend="removeLevel()"
-                                        ></v-text-field>
-                                    </v-col>
-                                    <v-col cols="6" sm="4" md="3" lg="2">
-                                        <v-text-field :label="strings.base_points" v-model="pointsBase" type="number">
-                                        </v-text-field>
-                                    </v-col>
-                                    <v-col cols="12" sm="4" md="4" lg="3">
-                                        <v-btn-toggle v-model="setPointsOption" tile group>
-                                            <v-btn value="calculated" v-text="strings.calculated"></v-btn>
-                                            <v-btn value="manually" v-text="strings.manually"></v-btn>
-                                        </v-btn-toggle>
-                                    </v-col>
-                                </v-row>
-                                </v-row>
-                                <v-row class="pb-5 px-8">
-                                    <v-row v-for="(level, index) in levelsData" :key="level.lvl" cols="12" sm="6" md="4" lg="3">
-                                        <v-card class="pt-5 align-center text-center">
-                                            <v-col :content="level.lvl" bottom offset-x="20" offset-y="20">
-                                                <v-avatar size="100">
-                                                    <v-img src="{{{image}}}"></v-img>
-                                                </v-avatar>
-                                            </v-col>
-                                            <v-card-text class="text--primary text-center">
-                                                <v-text-field :label="strings.name" :rules="[v => !!v || 'Name is required']" required v-model="level.nam" type="text">
-                                                </v-text-field>
-                                                <v-text-field :label="strings.description" v-model="level.des" type="text">
-                                                </v-text-field>
-                                                <v-text-field :disabled="setPointsOption === 'calculated'" :label="strings.levels_required" v-model="calculatePoints(index)" type="number">
-                                                </v-text-field>
-                                            </v-card-text>
-                                        </v-card>
+            <v-container pa-8>
+                <!-- Server message -->
+                <v-row class="justify-center" v-if="notifications.length > 0">
+                    <v-col cols="8">
+                        <v-alert v-for="(value, index, key) in notifications" 
+                                 :type="value.type" 
+                                 class="text-center" dense text dismissible>
+                            <span v-text="value.message"></span>
+                        </v-alert>
+                    </v-col>
+                </v-row>
+                        <v-card 
+                            class="align-center text-center flex"
+                            height="100"
+                            elevation ="1">
+                            <h4 v-text="strings.enable"><h4>
+                            <v-switch
+                                v-model ="swDisableEnable"
+                                inset
+                                color="red darken-3"
+                                class="pt-800 px-800 justify-center"
+                                @Change = disableEnable(swDisableEnable);
+                            ></v-switch>
+                        </v-card>
+                    <v-row>
+                        <v-col>
+                            <v-tabs v-model="tab" background-color="transparent">
+                                <v-tab v-text="strings.settings_level"></v-tab>
+                                <v-tab v-text="strings.preview"></v-tab>
+                                <v-tab v-text="strings.settings"></v-tab>
+                            </v-tabs>
+                            <v-tabs-items v-model="tab">
+                                <v-tab-item> <!-- Level and settings  -->
+                                    <v-row class="pt-8 px-8 justify-center">
+                                        <v-row>
+                                        <v-col cols="6" sm="4" md="3" lg="5">
+                                            <v-text-field
+                                                    type="number"
+                                                    readonly
+                                                    :label="strings.quantity"
+                                                    v-model="levelsData.length"
+                                                    append-outer-icon="mdi-plus-circle"
+                                                    prepend-icon="mdi-minus-circle"
+                                                    @click:append-outer="addLevel()"
+                                                    @click:prepend="removeLevel()"
+                                            ></v-text-field>
+                                        </v-col>
+                                        <v-col cols="6" sm="4" md="3" lg="2">
+                                            <v-text-field :label="strings.base_points" v-model="pointsBase" type="number">
+                                            </v-text-field>
+                                        </v-col>
+                                        <v-col cols="12" sm="4" md="4" lg="3">
+                                            <v-btn-toggle v-model="setPointsOption" tile group>
+                                                <v-btn value="calculated" v-text="strings.calculated"></v-btn>
+                                                <v-btn value="manually" v-text="strings.manually"></v-btn>
+                                            </v-btn-toggle>
+                                        </v-col>
+                                    </v-row>
+                                    </v-row>
+                                    <v-row class="pb-5 px-8">
+                                        <v-row v-for="(level, index) in levelsData" cols="12" sm="6" md="4" lg="3">
+                                            <v-card class="pt-5 align-center text-center">
+                                                <v-col :content="level.lvl" bottom offset-x="20" offset-y="20">
+                                                    <v-avatar size="100">
+                                                        <v-img src="{{{image}}}"></v-img>
+                                                    </v-avatar>
+                                                </v-col>
+                                                <v-card-text class="text--primary text-center">
+                                                    <v-text-field :label="strings.name" :rules="[v => !!v || strings.nameError]" required v-model="level.nam" type="text">
+                                                    </v-text-field>
+                                                    <v-text-field :label="strings.description" v-model="level.des" type="text">
+                                                    </v-text-field>
+                                                    <v-text-field :disabled="setPointsOption === 'calculated'" :label="strings.levels_required" v-model="calculatePoints(index)" type="number">
+                                                    </v-text-field>
+                                                </v-card-text>
+                                            </v-card>
+                                        </v-row>
+                                    </v-row>
+                                    <v-row class="pb-10 justify-center">
+                                            <v-btn @click="save_changes('levelsEdit')" v-text="strings.save" class="white--text" color="#118AB2"></v-btn>
+                                    </v-row>
+                                </v-tab-item>
+                                <v-tab-item> <!-- Student preview tab -->
+                                    <v-row class="justify-center">
+                                        <v-col cols="12" sm="11" md="7" lg="6" class="d-flex py-10">
+                                            <v-card class="align-center text-center flex">
+                                                <h4 class="py-5" v-text="settings.tit"></h4>
+                                                <p v-if="levelsData[0].nam" v-text="levelsData[0].nam"></p>
+                                                <v-badge
+                                                        :content="levelsData[0].lvl"
+                                                        bottom
+                                                        offset-x="20"
+                                                        offset-y="20"
+                                                >
+                                                    <v-avatar size="100">
+                                                        <v-img src="{{{image}}}"></v-img>
+                                                    </v-avatar>
+                                                </v-badge>
+                                                <v-card-text class="py-5">
+                                                    <small class="d-inline" v-text="levelsData[1].points"></small>
+                                                    <sup>xp</sup>
+                                                    <small v-text="strings.to_next_level"></small>
+                                                    <v-progress-linear
+                                                            color="#118AB2"
+                                                            :value="0"
+                                                            height="8"
+                                                    >
+                                                    </v-progress-linear>
+                                                    <p v-if="levelsData[0].des" class="pt-5" v-text="levelsData[0].des"></p>
+                                                    <h3 :class="[ !levelsData[0].des ? 'pt-5' : 'pt-0']"
+                                                        v-text="levelsData[0].points +' '+strings.points"></h3>
+                                                </v-card-text>
+                                                <v-card-actions>
+                                                    <p class="py-0 px-2" v-text="settings.des"></p>
+                                                </v-card-actions>
+                                            </v-card>
+                                        </v-col>
+                                    </v-row> <!-- Change the preview -->
+                                    <v-row class="pt-5 px-8 justify-center">
+                                        <v-col cols="12" md="12">
+                                            <h4 v-text="strings.appearance"></h4>
+                                        </v-col>
+                                        <v-col cols="12" md="12" class="">
+                                            <v-row class="justify-center">
+                                                <v-col cols="12" xs="10" md="6">
+                                                    <v-text-field :label="strings.appearance_title" v-model="settings.tit"></v-text-field>
+                                                </v-col>
+                                            </v-row>
+                                            <v-row class="justify-center">
+                                                <v-col cols="12" xs="10" md="6">
+                                                    <v-textarea :label="strings.description" auto-grow v-model="settings.des"></v-textarea>
+                                                </v-col>
+                                            </v-row>
+                                        </v-col>
+                                    </v-row>
+                                    <v-row class="pb-10 justify-center">
+                                        <v-btn @click="save_changes('studentSideEdit')" v-text="strings.save" class="white--text" color="#118AB2"></v-btn>
+                                    </v-row>
+                                </v-tab-item>
+                                <v-tab-item>
+                                    <v-row class="pt-5 px-8 justify-center justify-sm-space-between ">
+                                        <v-col cols="12" sm="6" md="5" lg="5">
+                                            <h4 v-text="strings.rules"></h4>
+                                        </v-col>
+                                        <v-col cols="6" sm="5" md="4" lg="4">
+                                            <v-btn
+                                                    block v-text="strings.add_rule"
+                                                    @click="addRule()"
+                                                    class="white--text"
+                                                    color="#118AB2">
+                                            </v-btn>
+                                        </v-col>
+                                    </v-row>
+                                    <v-row class="pt-5 pb-5 px-8">
+                                        <v-col v-for="(rule, index) in rulesData" cols="12" md="12">
+                                            <v-card class="align-center text-center">
+                                                <v-card-text class="text--primary text-center">
+                                                    <v-row class="align-center justify-space-around">
+                                                        <v-col cols="12" sm="4" md="3">
+                                                            <v-text-field
+                                                                    v-model="rule.points"
+                                                                    :label="strings.earn"
+                                                                    :rules="[v => !!v || strings.pointError]"
+                                                                    :suffix="strings.points"
+                                                                    type="number">
+                                                            </v-text-field>
+                                                        </v-col>
+                                                        <v-col cols="12" sm="6" md="7">
+                                                            <v-select
+                                                                    v-model="rule.rule"
+                                                                    attach
+                                                                    :menu-props="{ top: true, offsetY: true }"
+                                                                    :items="events"
+                                                                    item-text='name'
+                                                                    item-value='event'
+                                                                    :label="strings.select_event"
+                                                                    :rules="[v => !!v || strings.eventError]"
+                                                                    required>
+                                                            </v-select>
+                                                        </v-col>
+                                                        <v-col cols="12" sm="2" md="1">
+                                                            <v-btn :disabled="rulesData.length < 3" icon @click="removeRule(index)">
+                                                                <v-icon>mdi-delete</v-icon>
+                                                            </v-btn>
+                                                        </v-col>
+                                                    </v-row>
+                                                </v-card-text>
+                                            </v-card>
+                                        </v-col>
+
+                                    </v-row>
+                                    <v-row class="pb-10 justify-center">
+                                        <v-btn @click="save_changes('rulesEdit')" v-text="strings.save" class="white--text" color="#118AB2"></v-btn>
                                     </v-row>
-                                </v-row>
-                                <v-row class="pb-10 justify-center">
-                                        <v-btn @click="save_changes" v-text="strings.save" class="white--text" color="#118AB2"></v-btn>
-                                </v-row>
-                            </v-tab-item>
-                            <v-tab-item> <!-- Student preview tab -->
-                                <v-row class="justify-center">
-                                    <v-col cols="12" sm="11" md="7" lg="6" class="d-flex py-10">
-                                        <v-card class="align-center text-center flex">
-                                            <h4 class="py-5" v-text="settings.tit"></h4>
-                                            <p v-if="levelsData[0].nam" v-text="levelsData[0].nam"></p>
+                                </v-tab-item>
+                            </v-tabs-items>
+                        </v-col>
+
+                        <v-col>
+                            <v-row class="py-5 px-8">
+                                <v-col cols="12" md="12">
+                                    <v-data-table
+                                            :headers="table_headers()"
+                                            :items="ranking"
+                                            item-key="id"
+                                            :items-per-page="7"
+                                    >
+                                        <template v-slot:item.level="{ item }">
                                             <v-badge
-                                                    :content="levelsData[0].lvl"
-                                                    bottom
-                                                    offset-x="20"
-                                                    offset-y="20"
+                                                    inline
+                                                    bordered
+                                                    :content="item.level"
                                             >
-                                                <v-avatar size="100">
-                                                    <v-img src="{{{image}}}"></v-img>
+                                                <v-avatar size="30">
+                                                    <img src="{{{image}}}">
                                                 </v-avatar>
                                             </v-badge>
-                                            <v-card-text class="py-5">
-                                                <small class="d-inline" v-text="levelsData[1].points"></small>
-                                                <sup>xp</sup>
-                                                <small v-text="strings.to_next_level"></small>
-                                                <v-progress-linear
-                                                        color="#118AB2"
-                                                        :value="0"
-                                                        height="8"
-                                                >
-                                                </v-progress-linear>
-                                                <p v-if="levelsData[0].des" class="pt-5" v-text="levelsData[0].des"></p>
-                                                <h3 :class="[ !levelsData[0].des ? 'pt-5' : 'pt-0']"
-                                                    v-text="levelsData[0].points +' '+strings.points"></h3>
-                                            </v-card-text>
-                                            <v-card-actions>
-                                                <p class="py-0 px-2" v-text="settings.des"></p>
-                                            </v-card-actions>
-                                        </v-card>
-                                    </v-col>
-                                </v-row> <!-- Change the preview -->
-                                <v-row class="pt-5 px-8 justify-center">
-                                    <v-col cols="12" md="12">
-                                        <h4 v-text="strings.appearance"></h4>
-                                    </v-col>
-                                    <v-col cols="12" md="12" class="">
-                                        <v-row class="justify-center">
-                                            <v-col cols="12" xs="10" md="6">
-                                                <v-text-field :label="strings.appearance_title" v-model="settings.tit"></v-text-field>
-                                            </v-col>
-                                        </v-row>
-                                        <v-row class="justify-center">
-                                            <v-col cols="12" xs="10" md="6">
-                                                <v-textarea :label="strings.description" auto-grow v-model="settings.des"></v-textarea>
-                                            </v-col>
-                                        </v-row>
-                                    </v-col>
-                                </v-row>
-                                <v-row class="pb-10 justify-center">
-                                    <v-btn @click="save_changes" v-text="strings.save" class="white--text" color="#118AB2"></v-btn>
-                                </v-row>
-                            </v-tab-item>
-                            <v-tab-item>
-                                <v-row class="pt-5 px-8 justify-center justify-sm-space-between ">
-                                    <v-col cols="12" sm="6" md="5" lg="5">
-                                        <h4 v-text="strings.rules"></h4>
-                                    </v-col>
-                                    <v-col cols="6" sm="5" md="4" lg="4">
-                                        <v-btn
-                                                block v-text="strings.add_rule"
-                                                @click="addRule()"
-                                                class="white--text"
-                                                color="#118AB2">
-                                        </v-btn>
-                                    </v-col>
-                                </v-row>
-                                <v-row class="pt-5 pb-5 px-8">
-                                    <v-col v-for="(rule, index) in rulesData" :key="rule" cols="12" md="12">
-                                        <v-card class="align-center text-center">
-                                            <v-card-text class="text--primary text-center">
-                                                <v-row class="align-center justify-space-around">
-                                                    <v-col cols="12" sm="4" md="3">
-                                                        <v-text-field
-                                                                v-model="rule.points"
-                                                                :label="strings.earn"
-                                                                :rules="[v => !!v || 'Los puntos son requeridos']"
-                                                                :suffix="strings.points"
-                                                                type="number">
-                                                        </v-text-field>
-                                                    </v-col>
-                                                    <v-col cols="12" sm="6" md="7">
-                                                        <v-select
-                                                                v-model="rule.rule"
-                                                                attach
-                                                                :menu-props="{ top: true, offsetY: true }"
-                                                                :items="events"
-                                                                item-text='name'
-                                                                item-value='event'
-                                                                :label="strings.select_event"
-                                                                :rules="[v => !!v || 'El evento es requerido']"
-                                                                required>
-                                                        </v-select>
-                                                    </v-col>
-                                                    <v-col cols="12" sm="2" md="1">
-                                                        <v-btn :disabled="rulesData.length < 3" icon @click="removeRule(index)">
-                                                            <v-icon>mdi-delete</v-icon>
-                                                        </v-btn>
-                                                    </v-col>
-                                                </v-row>
-                                            </v-card-text>
-                                        </v-card>
-                                    </v-col>
-
-                                </v-row>
-                                <v-row class="pb-10 justify-center">
-                                    <v-btn @click="save_changes" v-text="strings.save" class="white--text" color="#118AB2"></v-btn>
-                                </v-row>
-                            </v-tab-item>
-                        </v-tabs-items>
-                    </v-col>
-
-                    <v-col>
-                        <v-row class="py-5 px-8">
-                            <v-col cols="12" md="12">
-                                <v-data-table
-                                        :headers="table_headers()"
-                                        :items="ranking"
-                                        item-key="id"
-                                        :items-per-page="7"
-                                >
-                                    <template v-slot:item.level="{ item }">
-                                        <v-badge
-                                                inline
-                                                bordered
-                                                :content="item.level"
-                                        >
-                                            <v-avatar size="30">
-                                                <img src="{{{image}}}">
-                                            </v-avatar>
-                                        </v-badge>
-                                    </template>
-                                    <template v-slot:item.progress_percentage="{ item }">
-                                        <v-progress-linear
-                                                color="#118AB2"
-                                                :value="item.progress_percentage"
-                                                height="8"
-                                        >
-                                        </v-progress-linear>
-                                    </template>
-                                    <template v-slot:item.total="{ item }">
-                                        <p class="d-inline" v-text="item.total"></p>
-                                        <sup>xp</sup>
-                                    </template>
-                                </v-data-table>
-                            </v-col>
-                        </v-row>
-                        
-                    </v-col>
-                 </v-row>
-            </v-card>
+                                        </template>
+                                        <template v-slot:item.progress_percentage="{ item }">
+                                            <v-progress-linear
+                                                    color="#118AB2"
+                                                    :value="item.progress_percentage"
+                                                    height="8"
+                                            >
+                                            </v-progress-linear>
+                                        </template>
+                                        <template v-slot:item.total="{ item }">
+                                            <p class="d-inline" v-text="item.total"></p>
+                                            <sup>xp</sup>
+                                        </template>
+                                    </v-data-table>
+                                </v-col>
+                            </v-row>
+                            <v-row>
+                                <chart
+                                    :container="'week_resourcess'"
+                                    :chart="chart_spread()"
+                                    :lang="strings.chart"
+                                ></chart>
+                            </v-row>
+                        </v-col>
+                     </v-row>
+                
+               </v-container> 
         </template>
     </v-main>
 </v-app>
\ No newline at end of file
diff --git a/notemyprogress/templates/student_gamification.mustache b/notemyprogress/templates/student_gamification.mustache
index de5c49cac4441119be99981f0cd49b4954c4260b..e464216de1cc646ed7a5d23197bbb90db37e66a2 100644
--- a/notemyprogress/templates/student_gamification.mustache
+++ b/notemyprogress/templates/student_gamification.mustache
@@ -10,7 +10,7 @@
         <template>
             <v-card>
                 <v-row>
-                    <v-col cols=12 lg="7">
+                    <v-col cols=12 lg="6">
                         <v-row class="justify-center">
                             <v-col cols="12" sm="11" md="7" lg="6" class="d-flex py-10">
                                 <v-card class="align-center text-center flex">
@@ -38,7 +38,7 @@
                                         <p v-if="levelInfo.des" class="pt-5" v-text="levelInfo.des"></p>
                                         <h3 :class="[ !levelInfo.des ? 'pt-5' : 'pt-0']"
                                             v-text="indicators.points +' '+strings.points"></h3>
-                                        <v-row class="justify-center text-left" v-for="action in activity" :key="action">
+                                        <v-row class="justify-center text-left" v-for="action in activity" >
                                             <v-col cols="5">
                                                 <small v-text="action.description"></small>
                                             </v-col>
@@ -49,7 +49,6 @@
                                                 <small v-text="action.points + ' '+strings.points"></small>
                                             </v-col>
                                         </v-row>
-                                        <small v-text="rankable"></small>
                                     </v-card-text>
                                     <v-card-actions>
                                         <p class="py-0 px-2" v-text="settings.des"></p>
@@ -57,8 +56,32 @@
                                 </v-card>
                             </v-col>
                         </v-row>
+                        <v-col>
+                            <h4 v-text=strings.overview></h4>
+                            <v-row class="py-5 px-8">
+                                <v-col v-for="(level, index) in levelsData" cols="12" sm="6" md="3" class="d-flex">
+                                    <v-card class="pt-5 align-center text-center flex">
+                                        <v-badge
+                                                :content="level.lvl"
+                                                bottom
+                                                offset-x="20"
+                                                offset-y="20"
+                                        >
+                                            <v-avatar size="100">
+                                                <v-img src="{{{image}}}"></v-img>
+                                            </v-avatar>
+                                        </v-badge>
+                                        <v-card-text class="text--primary text-center">
+                                            <h6 v-if="level.nam" v-text="level.nam"></h6>
+                                            <p v-if="level.des" class="pt-4 text-left" v-text="level.des"></p>
+                                            <p class="mb-0 pb-0" v-text="level.points+' '+strings.points"></p>
+                                        </v-card-text>
+                                    </v-card>
+                                </v-col>
+                            </v-row>
+                        </v-col>                                    
                     </v-col>
-                    <v-col cols=12 lg="5">
+                    <v-col cols=12 lg="6">
                         <v-row v-if="strings.rankable"class="py-5 px-8">
                             <v-col cols="12" md="12">
                                 <v-data-table
@@ -84,7 +107,6 @@
                                                 :value="item.progress_percentage"
                                                 height="8"
                                         >
-
                                         </v-progress-linear>
                                     </template>
                                     <template v-slot:item.total="{ item }">
@@ -92,20 +114,22 @@
                                         <sup>xp</sup>
                                     </template>
                                 </v-data-table>
+
+
+
                             </v-col>
                         </v-row>
                         <v-row v-else>
                             <v-card
                               class="mx-auto"
-                              max-width="100%"
+                              max-width="90%"
                               outlined
                             >
                               <v-list-item three-line>
                                 <v-list-item-content>
-                                  <v-list-item-title class="text-h5 mb-1">
-                                    <v-text v-text=strings.studentRanking1></v-text>
+                                  <v-list-item-title class="text-h5 mb-1" v-text=strings.studentRanking1>
                                   </v-list-item-title>
-                                  <v-list-item-subtitle><v-text v-text=strings.studentRanking2></v-text> </v-list-item-subtitle>
+                                  <v-list-item-subtitle v-text=strings.studentRanking2></v-list-item-subtitle>
                                 </v-list-item-content>
   
                                 <v-list-item-avatar
@@ -113,7 +137,7 @@
                                   size="80"
                                   color="red"
                                   
-                                ><v-img src="{{{image}}}"></v-img></v-list-item-avatar>
+                                ><v-img src="{{{rankImage}}}"></v-img></v-list-item-avatar>
                               </v-list-item>
   
                               <v-card-actions>
@@ -122,8 +146,8 @@
                                   rounded
                                   text
                                   @click=activateRanking()
+                                  v-text=strings.studentRanking3
                                 >
-                                  <v-text v-text=strings.studentRanking3></v-text>
                                 </v-btn>
                               </v-card-actions>
                             </v-card>
@@ -131,31 +155,7 @@
                     </v-col>
                 </v-row>
             </v-card>
-            <v-card>
-                 <v-col>
-                    <v-row class="py-5 px-8">
-                        <v-col v-for="(level, index) in levelsData" :key="level.level" cols="12" sm="6" md="3" class="d-flex">
-                            <v-card class="pt-5 align-center text-center flex">
-                                <v-badge
-                                        :content="level.lvl"
-                                        bottom
-                                        offset-x="20"
-                                        offset-y="20"
-                                >
-                                    <v-avatar size="100">
-                                        <v-img src="{{{image}}}"></v-img>
-                                    </v-avatar>
-                                </v-badge>
-                                <v-card-text class="text--primary text-center">
-                                    <h6 v-if="level.nam" v-text="level.nam"></h6>
-                                    <p v-if="level.des" class="pt-4 text-left" v-text="level.des"></p>
-                                    <p class="mb-0 pb-0" v-text="level.points+' '+strings.points"></p>
-                                </v-card-text>
-                            </v-card>
-                        </v-col>
-                    </v-row>
-                </v-col>
-            </v-card>
+            
         </template>
     </v-main>
 </v-app>
\ No newline at end of file