{"id":36191,"date":"2026-08-21T11:41:05","date_gmt":"2026-08-21T11:41:05","guid":{"rendered":"https:\/\/volatusaerospace.com\/?page_id=36191"},"modified":"2026-09-01T14:11:02","modified_gmt":"2026-09-01T14:11:02","slug":"topo-bathy-lidar-services","status":"publish","type":"page","link":"https:\/\/volatusaerospace.com\/fr-ca\/services\/technical-capabilities\/topo-bathy-lidar-services\/","title":{"rendered":"Reconnaissances lidar Topo-Bathy | Cartographie des terres et des eaux peu profondes"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"36191\" class=\"elementor elementor-36191\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-eb056c2 e-con-full dark-section e-flex e-con e-parent\" data-id=\"eb056c2\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t<div class=\"elementor-element elementor-element-227df96 elementor-icon-list--layout-inline elementor-list-item-link-full_width elementor-widget elementor-widget-icon-list\" data-id=\"227df96\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"icon-list.default\">\n\t\t\t\t\t\t\t<ul class=\"elementor-icon-list-items elementor-inline-items\">\n\t\t\t\t\t\t\t<li class=\"elementor-icon-list-item elementor-inline-item\">\n\t\t\t\t\t\t\t\t\t\t\t<a href=\"https:\/\/volatusaerospace.com\/\">\n\n\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-text\">Home<\/span>\n\t\t\t\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t\t<\/li>\n\t\t\t\t\t\t\t\t<li class=\"elementor-icon-list-item elementor-inline-item\">\n\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-text\">\/<\/span>\n\t\t\t\t\t\t\t\t\t<\/li>\n\t\t\t\t\t\t\t\t<li class=\"elementor-icon-list-item elementor-inline-item\">\n\t\t\t\t\t\t\t\t\t\t\t<a href=\"https:\/\/volatusaerospace.com\/fr-ca\/services\/\">\n\n\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-text\">Services<\/span>\n\t\t\t\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t\t<\/li>\n\t\t\t\t\t\t\t\t<li class=\"elementor-icon-list-item elementor-inline-item\">\n\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-text\">\/<\/span>\n\t\t\t\t\t\t\t\t\t<\/li>\n\t\t\t\t\t\t\t\t<li class=\"elementor-icon-list-item elementor-inline-item\">\n\t\t\t\t\t\t\t\t\t\t\t<a href=\"https:\/\/volatusaerospace.com\/fr-ca\/services\/technical-capabilities\/\">\n\n\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-text\">Technical Capabilities<\/span>\n\t\t\t\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t\t<\/li>\n\t\t\t\t\t\t\t\t<li class=\"elementor-icon-list-item elementor-inline-item\">\n\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-text\">\/<\/span>\n\t\t\t\t\t\t\t\t\t<\/li>\n\t\t\t\t\t\t\t\t<li class=\"elementor-icon-list-item elementor-inline-item\">\n\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-text\"> <span style=\"color: #FFB601\">Topo-Bathy Lidar Services<span><\/span>\n\t\t\t\t\t\t\t\t\t<\/li>\n\t\t\t\t\t\t<\/ul>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-4b8ad5b elementor-widget-mobile__width-inherit elementor-widget__width-initial elementor-widget-laptop__width-initial elementor-widget-tablet__width-initial elementor-widget elementor-widget-heading\" data-id=\"4b8ad5b\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\"> <span style=\"color: #FFB601\">Topo-Bathy Lidar Surveys<\/span>\n<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-f2911fc elementor-widget__width-initial elementor-widget-tablet__width-initial elementor-widget-mobile__width-inherit elementor-widget elementor-widget-text-editor\" data-id=\"f2911fc\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\tSee Through the Water Line.\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-7e8d2d1 elementor-widget__width-initial elementor-widget-mobile__width-inherit elementor-widget-laptop__width-initial elementor-widget-tablet__width-initial elementor-widget elementor-widget-text-editor\" data-id=\"7e8d2d1\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p>Most lidar Stops at the water&#8217;s edge. Topo-bathy lidar doesn&#8217;t. Using a green-wavelength laser purpose-built to penetrate clear, shallow water, Volatus captures a continuous elevation model from dry land straight through the water colurnn to the bottom, in a single flight. NO dive teams, no boat-based bathymetry, no gap between the topo survey and the hydrographic one.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-c4fe321 e-con-full e-flex e-con e-child\" data-id=\"c4fe321\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-e7edf7b elementor-widget elementor-widget-button\" data-id=\"e7edf7b\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"button.default\">\n\t\t\t\t\t\t\t\t\t\t<a class=\"elementor-button elementor-button-link elementor-size-sm\" href=\"#elementor-action%3Aaction%3Dpopup%3Aopen%26settings%3DeyJpZCI6IjQ5NjIiLCJ0b2dnbGUiOmZhbHNlfQ%3D%3D\">\n\t\t\t\t\t\t<span class=\"elementor-button-content-wrapper\">\n\t\t\t\t\t\t\t\t\t<span class=\"elementor-button-text\">Talk To An Expert<\/span>\n\t\t\t\t\t<\/span>\n\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-3491238 e-con-full e-flex e-con e-child\" data-id=\"3491238\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;position&quot;:&quot;absolute&quot;}\">\n\t\t\t\t<div class=\"elementor-element elementor-element-6583413 elementor-widget elementor-widget-html\" data-id=\"6583413\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<div class=\"scroll-indicator-container\">\r\n  <svg class=\"scroll-arrow arrow-1\" viewBox=\"0 0 24 24\" width=\"24\" height=\"24\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"6 9 12 15 18 9\"><\/polyline><\/svg>\r\n  <svg class=\"scroll-arrow arrow-2\" viewBox=\"0 0 24 24\" width=\"24\" height=\"24\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"6 9 12 15 18 9\"><\/polyline><\/svg>\r\n  <svg class=\"scroll-arrow arrow-3\" viewBox=\"0 0 24 24\" width=\"24\" height=\"24\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"6 9 12 15 18 9\"><\/polyline><\/svg>\r\n<\/div>\r\n\r\n<style>\r\n.scroll-indicator-container {\r\n  display: flex;\r\n  flex-direction: column;\r\n  align-items: center;\r\n  justify-content: center;\r\n}\r\n\r\n.scroll-arrow {\r\n  color: #555555; \/* Base gray color *\/\r\n  animation: lightSequence 2s infinite;\r\n  margin-top: -12px; \/* Adjusted overlap for smaller arrows *\/\r\n}\r\n\r\n\/* Delaying each arrow to create the cascading light effect *\/\r\n.arrow-1 { animation-delay: 0s; }\r\n.arrow-2 { animation-delay: 0.3s; }\r\n.arrow-3 { animation-delay: 0.6s; }\r\n\r\n@keyframes lightSequence {\r\n  0% { color: #555555; }\r\n  20% { \r\n    color: #ffffff; \/* White light *\/\r\n  }\r\n  40% { color: #555555; }\r\n  100% { color: #555555; }\r\n}\r\n<\/style>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-6d2a6b6 e-flex e-con-boxed e-con e-parent\" data-id=\"6d2a6b6\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t<div class=\"elementor-element elementor-element-48e9e59 e-con-full e-flex e-con e-child\" data-id=\"48e9e59\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-17d0a8b e-con-full e-flex e-con e-child\" data-id=\"17d0a8b\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-9aac543 e-con-full e-flex e-con e-child\" data-id=\"9aac543\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-e9433b7 elementor-widget elementor-widget-heading\" data-id=\"e9433b7\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">One Survey.<span style=\"color: #FFB601\">\nTwo Elevations.<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-46e81eb elementor-widget elementor-widget-text-editor\" data-id=\"46e81eb\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p>We&#8217;re adding a new tool to our lidar fleet: the <a href=\"https:\/\/volatusaerospace.com\/equipment\/all-products\/yellowscan-navigator\/\"><strong><span style=\"color: #ffb601;\">YellowScan Navigator<\/span><\/strong><\/a>, a dedicated bathymetric payload built for clear, shallow water. Unlike our standard topographic lidar sensors, the Navigator uses a <strong>532nm green laser<\/strong> to penetrate the water column and return a signal off the bottom, giving us a continuous elevation model from dry land through the shoreline and into the submerged bed, in a single flight.<\/p><p>This is a distinct payload from our topographic lidar systems, not an add-on to them, and it opens up survey work that a standard lidar sensor simply can&#8217;t capture: the transition zone where land meets water. It&#8217;s also a rare capability in this space. Most topo-bathy lidar today is still limited to crewed aircraft; the Navigator brings that same integrated land-and-water dataset to a UAV platform.<\/p><p>We fly the Navigator on our drone platforms, purpose-built for shallow, clear-water environments. The system weighs 3.7 kg, delivers up to 45 minutes of mission time per battery, and operates at up to 3 cm precision, with penetration depth scaling to water clarity on site.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-1d5162e e-con-full e-flex e-con e-child\" data-id=\"1d5162e\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-3e3dd4c elementor-widget elementor-widget-image\" data-id=\"3e3dd4c\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img fetchpriority=\"high\" decoding=\"async\" width=\"540\" height=\"540\" src=\"https:\/\/volatusaerospace.com\/wp-content\/uploads\/2026\/05\/ys_website_post_integration_square_navigator_540x690_01.jpg.webp\" class=\"attachment-large size-large wp-image-27328\" alt=\"\" srcset=\"https:\/\/volatusaerospace.com\/wp-content\/uploads\/2026\/05\/ys_website_post_integration_square_navigator_540x690_01.jpg.webp 540w, https:\/\/volatusaerospace.com\/wp-content\/uploads\/2026\/05\/ys_website_post_integration_square_navigator_540x690_01.jpg-300x300.webp 300w, https:\/\/volatusaerospace.com\/wp-content\/uploads\/2026\/05\/ys_website_post_integration_square_navigator_540x690_01.jpg-150x150.webp 150w\" sizes=\"(max-width: 540px) 100vw, 540px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-52bb8ae e-flex e-con-boxed e-con e-parent\" data-id=\"52bb8ae\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-97110f8 elementor-widget elementor-widget-heading\" data-id=\"97110f8\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Capability <span style=\"color: #FFB601\">Metrics\n<\/h2>\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-8504d8c e-grid e-con-full e-con e-child\" data-id=\"8504d8c\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-d73bf37 e-con-full e-flex e-con e-child\" data-id=\"d73bf37\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t<div class=\"elementor-element elementor-element-4e3ac15 e-con-full e-flex e-con e-child\" data-id=\"4e3ac15\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-7b45cfb elementor-widget-tablet__width-initial elementor-widget-mobile__width-inherit elementor-widget elementor-widget-text-editor\" data-id=\"7b45cfb\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<div class=\"mt-3 text-sm text-[#8A8A8A]\">\n<div class=\"font-mono text-[10px] text-[#8A8A8A] tracking-[0.2em] uppercase mb-3\">Payload Weight<\/div>\n<div class=\"flex items-baseline gap-2\"><\/div>\n\n<\/div>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-a096d9d e-con-full e-flex e-con e-child\" data-id=\"a096d9d\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-a4cd165 e-con-full e-flex e-con e-child\" data-id=\"a4cd165\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-801d537 elementor-widget-mobile__width-auto elementor-widget elementor-widget-heading\" data-id=\"801d537\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">3.7<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-823b7f7 elementor-widget elementor-widget-heading\" data-id=\"823b7f7\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">KG<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-1df1e27 e-con-full e-flex e-con e-child\" data-id=\"1df1e27\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-23d7c78 elementor-widget-tablet__width-initial elementor-widget-mobile__width-inherit elementor-widget elementor-widget-text-editor\" data-id=\"23d7c78\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<div class=\"mt-3 text-sm text-[#8A8A8A]\">Compact UAV-deployable payload<\/div>\n<div class=\"mt-4 h-1 bg-[#1A1A1A]\"><\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-79aa6c2 e-con-full e-flex e-con e-child\" data-id=\"79aa6c2\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t<div class=\"elementor-element elementor-element-8a116e2 e-con-full e-flex e-con e-child\" data-id=\"8a116e2\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-0946415 elementor-widget-tablet__width-initial elementor-widget-mobile__width-inherit elementor-widget elementor-widget-text-editor\" data-id=\"0946415\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<div class=\"mt-3 text-sm text-[#8A8A8A]\"><div class=\"font-mono text-[10px] text-[#8A8A8A] tracking-[0.2em] uppercase mb-3\"><div class=\"font-mono text-[10px] text-[#8A8A8A] tracking-[0.2em] uppercase mb-3\">Mission Time<\/div><\/div><\/div>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-783a33f e-con-full e-flex e-con e-child\" data-id=\"783a33f\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-de3471c e-con-full e-flex e-con e-child\" data-id=\"de3471c\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-63b433d elementor-widget-mobile__width-auto elementor-widget elementor-widget-heading\" data-id=\"63b433d\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">45<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-e3fbe39 elementor-widget elementor-widget-heading\" data-id=\"e3fbe39\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">MIN<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-01866c3 e-con-full e-flex e-con e-child\" data-id=\"01866c3\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-5ab9314 elementor-widget-tablet__width-initial elementor-widget-mobile__width-inherit elementor-widget elementor-widget-text-editor\" data-id=\"5ab9314\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<div class=\"mt-3 text-sm text-[#8A8A8A]\"><div class=\"mt-3 text-sm text-[#8A8A8A]\">Up to per battery<\/div><\/div>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-7a73d53 e-con-full e-flex e-con e-child\" data-id=\"7a73d53\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t<div class=\"elementor-element elementor-element-6c8b126 e-con-full e-flex e-con e-child\" data-id=\"6c8b126\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-4e1a411 elementor-widget-tablet__width-initial elementor-widget-mobile__width-inherit elementor-widget elementor-widget-text-editor\" data-id=\"4e1a411\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<div class=\"mt-3 text-sm text-[#8A8A8A]\"><div class=\"font-mono text-[10px] text-[#8A8A8A] tracking-[0.2em] uppercase mb-3\">Precision<\/div><\/div>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-16366b0 e-con-full e-flex e-con e-child\" data-id=\"16366b0\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-5969dc3 e-con-full e-flex e-con e-child\" data-id=\"5969dc3\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-c3924ac elementor-widget-mobile__width-auto elementor-widget elementor-widget-heading\" data-id=\"c3924ac\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">3<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-7ff7fdf elementor-widget elementor-widget-heading\" data-id=\"7ff7fdf\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">CM<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-9e36ec3 e-con-full e-flex e-con e-child\" data-id=\"9e36ec3\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-1f62fac elementor-widget-tablet__width-initial elementor-widget-mobile__width-inherit elementor-widget elementor-widget-text-editor\" data-id=\"1f62fac\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<div class=\"mt-3 text-sm text-[#8A8A8A]\"><div class=\"mt-3 text-sm text-[#8A8A8A]\">Up to vertical precision<\/div><\/div>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-480e53a e-con-full e-flex e-con e-child\" data-id=\"480e53a\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t<div class=\"elementor-element elementor-element-9766054 e-con-full e-flex e-con e-child\" data-id=\"9766054\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-a9d2dee elementor-widget-tablet__width-initial elementor-widget-mobile__width-inherit elementor-widget elementor-widget-text-editor\" data-id=\"a9d2dee\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<div class=\"mt-3 text-sm text-[#8A8A8A]\">\n<div class=\"font-mono text-[10px] text-[#8A8A8A] tracking-[0.2em] uppercase mb-3\">Wavelength<\/div>\n<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-3b439f7 e-con-full e-flex e-con e-child\" data-id=\"3b439f7\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-07565f9 e-con-full e-flex e-con e-child\" data-id=\"07565f9\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-9161acf elementor-widget-mobile__width-auto elementor-widget elementor-widget-heading\" data-id=\"9161acf\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">532<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-4c5294b elementor-widget elementor-widget-heading\" data-id=\"4c5294b\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">NM<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-bb00480 e-con-full e-flex e-con e-child\" data-id=\"bb00480\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-cc93f57 elementor-widget-tablet__width-initial elementor-widget-mobile__width-inherit elementor-widget elementor-widget-text-editor\" data-id=\"cc93f57\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<div class=\"mt-3 text-sm text-[#8A8A8A]\"><div class=\"mt-3 text-sm text-[#8A8A8A]\">Green laser wavelength<\/div><\/div>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-f2d956c e-con-full e-flex e-con e-parent\" data-id=\"f2d956c\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t<div class=\"elementor-element elementor-element-6367ed1 elementor-widget elementor-widget-html\" data-id=\"6367ed1\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\">\r\n<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Barlow+Condensed:wght@400;500;600;700&family=JetBrains+Mono:wght@300;400;500;600&display=swap\" rel=\"stylesheet\">\r\n<!-- If Barlow Condensed \/ JetBrains Mono are already loaded globally on the site, you can remove the two link tags above. -->\r\n\r\n<div class=\"vlt-topobathy\">\r\n<style>\r\n  .vlt-topobathy {\r\n    position: relative;\r\n    width: 100%;\r\n    height: 100%;\r\n    min-height: 520px;\r\n    overflow: hidden;\r\n    background: #05070a;\r\n    font-family: 'Barlow Condensed', sans-serif;\r\n  }\r\n  .vlt-topobathy, .vlt-topobathy * , .vlt-topobathy *::before, .vlt-topobathy *::after {\r\n    box-sizing: border-box;\r\n  }\r\n  .vlt-topobathy .vlt-canvas-container {\r\n    position: absolute;\r\n    inset: 0;\r\n    background: radial-gradient(circle at 50% 30%, #0d1520 0%, #05070a 100%);\r\n  }\r\n  .vlt-topobathy canvas {\r\n    display: block;\r\n    width: 100%;\r\n    height: 100%;\r\n  }\r\n  .vlt-topobathy .ui-overlay {\r\n    position: absolute;\r\n    inset: 0;\r\n    pointer-events: none;\r\n    z-index: 10;\r\n  }\r\n  .vlt-topobathy .interactive-elem { pointer-events: auto; }\r\n\r\n  .vlt-topobathy .title-block {\r\n    position: absolute;\r\n    bottom: 64px;\r\n    left: 36px;\r\n    max-width: 560px;\r\n    right: 36px;\r\n  }\r\n  .vlt-topobathy .title-main {\r\n    color: #F2F2F2;\r\n    font-size: 32px;\r\n    font-weight: 700;\r\n    line-height: 1.08;\r\n    letter-spacing: 0.02em;\r\n    margin: 0 0 6px;\r\n    text-shadow: 0 4px 24px rgba(0,0,0,0.9);\r\n  }\r\n  .vlt-topobathy .title-sub {\r\n    font-family: 'JetBrains Mono', monospace;\r\n    font-size: 11px;\r\n    color: #8A99AD;\r\n    letter-spacing: 0.12em;\r\n    text-transform: uppercase;\r\n  }\r\n\r\n  .vlt-topobathy .label {\r\n    position: absolute;\r\n    font-family: 'JetBrains Mono', monospace;\r\n    font-size: 10px;\r\n    color: #F2F2F2;\r\n    letter-spacing: 0.14em;\r\n    text-transform: uppercase;\r\n    white-space: nowrap;\r\n    display: flex;\r\n    align-items: center;\r\n    gap: 8px;\r\n    opacity: 0.55;\r\n    transition: opacity 0.4s ease, color 0.4s ease;\r\n  }\r\n  .vlt-topobathy .label.active { opacity: 1; color: #FFF; }\r\n  .vlt-topobathy .label-dot {\r\n    width: 6px; height: 6px;\r\n    border: 1px solid #FFB601;\r\n    transform: rotate(45deg);\r\n    background: transparent;\r\n    flex: none;\r\n    transition: background 0.3s ease, box-shadow 0.3s ease;\r\n  }\r\n  .vlt-topobathy .label.active .label-dot { background: #FFB601; box-shadow: 0 0 8px rgba(255,182,1,0.6); }\r\n  .vlt-topobathy .label.green-theme .label-dot { border-color: #00E676; }\r\n  .vlt-topobathy .label.green-theme.active .label-dot { background: #00E676; box-shadow: 0 0 8px rgba(0,230,118,0.7); }\r\n  .vlt-topobathy .label.cyan-theme .label-dot { border-color: #38BDF8; }\r\n  .vlt-topobathy .label.cyan-theme.active .label-dot { background: #38BDF8; box-shadow: 0 0 8px rgba(56,189,248,0.8); }\r\n  .vlt-topobathy .label-line { height: 1px; background: rgba(255,255,255,0.08); transition: background 0.3s ease; flex: none; }\r\n  .vlt-topobathy .label.active .label-line { background: rgba(255,255,255,0.4); }\r\n\r\n  .vlt-topobathy .data-strip {\r\n    position: absolute;\r\n    bottom: 0; left: 0; width: 100%;\r\n    background: rgba(8,12,18,0.88);\r\n    backdrop-filter: blur(14px);\r\n    -webkit-backdrop-filter: blur(14px);\r\n    border-top: 1px solid rgba(255,255,255,0.08);\r\n    padding: 14px 36px;\r\n    display: flex;\r\n    flex-wrap: wrap;\r\n    row-gap: 6px;\r\n    justify-content: space-between;\r\n    align-items: center;\r\n    font-family: 'JetBrains Mono', monospace;\r\n    font-size: 10px;\r\n    letter-spacing: 0.18em;\r\n    text-transform: uppercase;\r\n    color: #8A99AD;\r\n  }\r\n  .vlt-topobathy .data-item { display: flex; align-items: center; gap: 8px; min-width: 180px; }\r\n  .vlt-topobathy .data-item.fixed-w { min-width: 260px; }\r\n  .vlt-topobathy .data-value { color: #FFF; font-weight: 600; }\r\n  .vlt-topobathy .data-value.highlight-green { color: #00E676; text-shadow: 0 0 8px rgba(0,230,118,0.4); }\r\n  .vlt-topobathy .data-value.highlight-yellow { color: #FFB601; }\r\n  .vlt-topobathy .data-value.highlight-cyan { color: #38BDF8; }\r\n\r\n  .vlt-topobathy .controls-group { display: flex; align-items: center; gap: 10px; }\r\n  .vlt-topobathy .ctrl-btn {\r\n    background: rgba(255,255,255,0.06);\r\n    border: 1px solid rgba(255,255,255,0.08);\r\n    color: #F2F2F2;\r\n    padding: 6px 14px;\r\n    font-family: 'JetBrains Mono', monospace;\r\n    font-size: 10px;\r\n    letter-spacing: 0.14em;\r\n    border-radius: 4px;\r\n    cursor: pointer;\r\n    -webkit-tap-highlight-color: transparent;\r\n    transition: all 0.2s ease;\r\n  }\r\n  .vlt-topobathy .ctrl-btn:hover,\r\n  .vlt-topobathy .ctrl-btn:focus-visible {\r\n    background: rgba(0,230,118,0.15);\r\n    border-color: #00E676;\r\n    color: #00E676;\r\n  }\r\n\r\n  \/* ---- Tablet ---- *\/\r\n  @media (max-width: 1024px) {\r\n    .vlt-topobathy .title-main { font-size: 26px; }\r\n    .vlt-topobathy .title-block { bottom: 58px; left: 24px; right: 24px; }\r\n    .vlt-topobathy .data-strip { padding: 12px 24px; }\r\n    .vlt-topobathy .data-item { min-width: 140px; }\r\n    .vlt-topobathy .data-item.fixed-w { min-width: 200px; }\r\n  }\r\n\r\n  \/* ---- Mobile (Elementor default breakpoint) ---- *\/\r\n  @media (max-width: 767px) {\r\n    .vlt-topobathy { min-height: 420px; }\r\n    .vlt-topobathy .title-main { font-size: 18px; letter-spacing: 0.01em; }\r\n    .vlt-topobathy .title-sub {\r\n      font-size: 8.5px;\r\n      display: block;\r\n      white-space: normal;\r\n      max-width: 100%;\r\n    }\r\n    .vlt-topobathy .title-block { bottom: 88px; left: 14px; right: auto; max-width: 64%; }\r\n\r\n    \/* Shrink labels and stop the connector line from running into the text;\r\n       give the text a small dark chip so canvas art never cuts through it. *\/\r\n    .vlt-topobathy .label { font-size: 7.5px; gap: 4px; opacity: 0.85; }\r\n    .vlt-topobathy .label.active { opacity: 1; }\r\n    .vlt-topobathy .label-line { width: 8px !important; }\r\n    .vlt-topobathy .label span {\r\n      background: rgba(5, 7, 10, 0.6);\r\n      padding: 1px 4px;\r\n      border-radius: 3px;\r\n      backdrop-filter: blur(2px);\r\n      -webkit-backdrop-filter: blur(2px);\r\n      max-width: 34vw;\r\n      overflow: hidden;\r\n      text-overflow: ellipsis;\r\n      white-space: nowrap;\r\n    }\r\n\r\n    .vlt-topobathy .data-strip {\r\n      padding: 8px 14px;\r\n      gap: 6px 10px;\r\n      font-size: 8px;\r\n    }\r\n    .vlt-topobathy .data-item,\r\n    .vlt-topobathy .data-item.fixed-w { min-width: 0; flex: 1 1 auto; gap: 5px; }\r\n    .vlt-topobathy .data-item.vlt-hide-mobile { display: none; }\r\n    .vlt-topobathy .ctrl-btn { padding: 5px 10px; font-size: 8.5px; }\r\n  }\r\n\r\n  @media (max-width: 400px) {\r\n    .vlt-topobathy .title-main { font-size: 15px; }\r\n    .vlt-topobathy .title-sub { font-size: 7.5px; }\r\n    .vlt-topobathy .title-block { bottom: 80px; max-width: 68%; }\r\n    .vlt-topobathy .data-item.vlt-hide-small { display: none; }\r\n\r\n    \/* Below this width, drop the connector lines entirely -- dot + chip only *\/\r\n    .vlt-topobathy .label-line { width: 0 !important; }\r\n    .vlt-topobathy .label { font-size: 7px; gap: 3px; }\r\n    .vlt-topobathy .label span { max-width: 28vw; padding: 1px 3px; }\r\n\r\n    \/* Least essential pin on the smallest screens -- keeps the cluster near\r\n       the shoreline from getting too busy *\/\r\n    .vlt-topobathy .label[data-full^=\"TRANSITION\"] { display: none; }\r\n  }\r\n<\/style>\r\n\r\n  <div class=\"vlt-canvas-container\">\r\n    <canvas><\/canvas>\r\n\r\n    <div class=\"ui-overlay\">\r\n      <div class=\"label\" data-full=\"DRY LAND \/ TOPO\" data-short=\"LAND\" style=\"top: 54%; left: 8%;\">\r\n        <span><\/span>\r\n        <div class=\"label-line\" style=\"width: 36px;\"><\/div>\r\n        <div class=\"label-dot\"><\/div>\r\n      <\/div>\r\n\r\n      <div class=\"label green-theme\" data-full=\"TRANSITION ZONE \/ BANK TOE\" data-short=\"BANK TOE\" style=\"top: 58%; left: 32%;\">\r\n        <span><\/span>\r\n        <div class=\"label-line\" style=\"width: 22px;\"><\/div>\r\n        <div class=\"label-dot\"><\/div>\r\n      <\/div>\r\n\r\n      <div class=\"label cyan-theme\" data-full=\"WATER SURFACE (ELEVATION 1)\" data-short=\"SURFACE\" style=\"top: 42%; left: 58%;\">\r\n        <div class=\"label-dot\"><\/div>\r\n        <div class=\"label-line\" style=\"width: 36px;\"><\/div>\r\n        <span><\/span>\r\n      <\/div>\r\n\r\n      <div class=\"label green-theme\" data-full=\"SUBMERGED BED (ELEVATION 2)\" data-short=\"BED\" style=\"bottom: 24%; right: 14%;\">\r\n        <div class=\"label-dot\"><\/div>\r\n        <div class=\"label-line\" style=\"width: 36px;\"><\/div>\r\n        <span><\/span>\r\n      <\/div>\r\n\r\n      <div class=\"title-block\">\r\n        <div class=\"title-main\">ONE SURVEY. TWO ELEVATIONS. ZERO GAPS.<\/div>\r\n        <div class=\"title-sub\">Dry land through shoreline into submerged bed in a single UAV flight<\/div>\r\n      <\/div>\r\n\r\n      <div class=\"data-strip\">\r\n        <div class=\"data-item\">\r\n          <span>WAVELENGTH<\/span>\r\n          <span class=\"data-value highlight-green\">532 NM<\/span>\r\n        <\/div>\r\n        <div class=\"data-item vlt-hide-mobile\">\r\n          <span>SCAN PATTERN<\/span>\r\n          <span class=\"data-value highlight-green\">40&deg;&ndash;44&deg; FOV<\/span>\r\n        <\/div>\r\n        <div class=\"data-item fixed-w vlt-hide-small\">\r\n          <span>ACTIVE ECHO<\/span>\r\n          <span class=\"data-value highlight-yellow\" data-role=\"return-status\">TOPO RETURN (LAND)<\/span>\r\n        <\/div>\r\n        <div class=\"data-item\">\r\n          <span>POINTS<\/span>\r\n          <span class=\"data-value highlight-green\" data-role=\"point-count\">0 PTS<\/span>\r\n        <\/div>\r\n        <div class=\"controls-group interactive-elem\">\r\n          <button class=\"ctrl-btn\" type=\"button\" data-role=\"pause-btn\">PAUSE<\/button>\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n\r\n<script>\r\n(function () {\r\n  var container = document.currentScript.closest('.vlt-topobathy');\r\n  if (!container) return;\r\n\r\n  \/\/ Tear down any previous instance living on this same container\r\n  \/\/ (guards against Elementor editor re-renders re-running this script)\r\n  if (typeof container._vltCleanup === 'function') {\r\n    container._vltCleanup();\r\n  }\r\n\r\n  var canvasContainer = container.querySelector('.vlt-canvas-container');\r\n  var canvas = container.querySelector('canvas');\r\n  var ctx = canvas.getContext('2d');\r\n\r\n  var pauseBtn = container.querySelector('[data-role=\"pause-btn\"]');\r\n  var returnStatusEl = container.querySelector('[data-role=\"return-status\"]');\r\n  var pointCountEl = container.querySelector('[data-role=\"point-count\"]');\r\n  var lblLand = container.querySelector('.label[data-full^=\"DRY LAND\"]');\r\n  var lblTrans = container.querySelector('.label[data-full^=\"TRANSITION\"]');\r\n  var lblSurf = container.querySelector('.label[data-full^=\"WATER SURFACE\"]');\r\n  var lblBed = container.querySelector('.label[data-full^=\"SUBMERGED BED\"]');\r\n  var allLabels = container.querySelectorAll('.label');\r\n\r\n  var W = 0, H = 0, DPR = 1;\r\n  var isPaused = false;\r\n  var inView = true;\r\n  var LOW_POWER = false;\r\n  var rafId = null;\r\n  var SCAN_SPEED = 1.0;\r\n\r\n  var prefersReducedMotion = window.matchMedia &&\r\n    window.matchMedia('(prefers-reduced-motion: reduce)').matches;\r\n  if (prefersReducedMotion) {\r\n    isPaused = true;\r\n    if (pauseBtn) pauseBtn.innerText = 'PLAY';\r\n  }\r\n\r\n  var env = {\r\n    waterLevelY: 0, bedLevelY: 0, droneBaseY: 0, droneX: 0, time: 0,\r\n    pulses: [], ripples: [], returns: [], particles: [],\r\n    bedPoints: [], landPoints: [], waterStartX: 0,\r\n    pointCloud: [], pointCount: 0,\r\n    airGrad: null, waterGrad: null\r\n  };\r\n\r\n  \/\/ ---------- sizing ----------\r\n  function measureContainer() {\r\n    var rect = canvasContainer.getBoundingClientRect();\r\n    return {\r\n      w: Math.max(1, Math.round(rect.width)),\r\n      h: Math.max(1, Math.round(rect.height))\r\n    };\r\n  }\r\n\r\n  function applyCanvasSize() {\r\n    var size = measureContainer();\r\n    W = size.w;\r\n    H = size.h;\r\n    DPR = Math.min(window.devicePixelRatio || 1, 2);\r\n    canvas.width = Math.round(W * DPR);\r\n    canvas.height = Math.round(H * DPR);\r\n    canvas.style.width = W + 'px';\r\n    canvas.style.height = H + 'px';\r\n    ctx.setTransform(DPR, 0, 0, DPR, 0, 0);\r\n    LOW_POWER = W < 640 || (navigator.hardwareConcurrency && navigator.hardwareConcurrency <= 4);\r\n    initEnvironment();\r\n    updateLabelText();\r\n  }\r\n\r\n  function updateLabelText() {\r\n    var short = W < 560;\r\n    allLabels.forEach(function (lbl) {\r\n      var span = lbl.querySelector('span');\r\n      if (!span) return;\r\n      span.textContent = short ? lbl.getAttribute('data-short') : lbl.getAttribute('data-full');\r\n    });\r\n  }\r\n\r\n  function initEnvironment() {\r\n    env.waterLevelY = H * 0.46;\r\n    env.bedLevelY = H * 0.78;\r\n    env.droneBaseY = H * 0.16;\r\n    env.waterStartX = W * 0.38;\r\n    env.droneX = -60;\r\n\r\n    env.bedPoints = [];\r\n    env.landPoints = [];\r\n    var segments = 120;\r\n\r\n    for (var i = 0; i <= segments; i++) {\r\n      var x = (i \/ segments) * W;\r\n      if (x <= env.waterStartX) {\r\n        var landRatio = x \/ env.waterStartX;\r\n        var heightAboveWater = (1 - landRatio) * 70;\r\n        var y = env.waterLevelY - heightAboveWater + Math.sin(x * 0.035) * 4 * (1 - landRatio);\r\n        env.landPoints.push({ x: x, y: y });\r\n      } else {\r\n        var waterRatio = (x - env.waterStartX) \/ (W - env.waterStartX);\r\n        var bedDepth = Math.pow(waterRatio, 0.75) * (env.bedLevelY - env.waterLevelY);\r\n        \/\/ Taper the decorative wobble to zero right at the shoreline so it\r\n        \/\/ can never push the bed line above the water surface on short\r\n        \/\/ (mobile) containers, then clamp as a hard safety net.\r\n        var contourTaper = Math.min(1, waterRatio * 4);\r\n        var bedContours = (Math.sin(x * 0.025) * 12 + Math.cos(x * 0.015) * 8) * contourTaper;\r\n        var bedY = env.waterLevelY + bedDepth + bedContours;\r\n        bedY = Math.max(bedY, env.waterLevelY + 1);\r\n        env.bedPoints.push({ x: x, y: bedY });\r\n      }\r\n    }\r\n\r\n    var particleCount = LOW_POWER ? 45 : 90;\r\n    env.particles = [];\r\n    for (var p = 0; p < particleCount; p++) {\r\n      env.particles.push({\r\n        x: env.waterStartX + Math.random() * (W - env.waterStartX),\r\n        y: env.waterLevelY + Math.random() * (env.bedLevelY - env.waterLevelY + 30),\r\n        size: Math.random() * 1.4 + 0.4,\r\n        speed: Math.random() * 0.18 + 0.05,\r\n        opacity: Math.random() * 0.35 + 0.1\r\n      });\r\n    }\r\n\r\n    env.pulses = [];\r\n    env.returns = [];\r\n    env.ripples = [];\r\n    env.pointCloud = [];\r\n    env.pointCount = 0;\r\n    if (pointCountEl) pointCountEl.innerText = '0 PTS';\r\n\r\n    \/\/ Cache gradients that only depend on container height\r\n env.airGrad = ctx.createLinearGradient(0, 0, 0, env.waterLevelY);\r\nenv.airGrad.addColorStop(0, '#000000');\r\nenv.airGrad.addColorStop(1, '#000000');\r\n\r\n    env.waterGrad = ctx.createLinearGradient(0, env.waterLevelY, 0, H);\r\n    env.waterGrad.addColorStop(0, 'rgba(4, 30, 48, 0.65)');\r\n    env.waterGrad.addColorStop(0.4, 'rgba(2, 20, 35, 0.85)');\r\n    env.waterGrad.addColorStop(1, 'rgba(1, 10, 20, 0.98)');\r\n  }\r\n\r\n  function drawRoundRect(x, y, w, h, r) {\r\n    ctx.beginPath();\r\n    ctx.moveTo(x + r, y);\r\n    ctx.lineTo(x + w - r, y);\r\n    ctx.quadraticCurveTo(x + w, y, x + w, y + r);\r\n    ctx.lineTo(x + w, y + h - r);\r\n    ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);\r\n    ctx.lineTo(x + r, y + h);\r\n    ctx.quadraticCurveTo(x, y + h, x, y + h - r);\r\n    ctx.lineTo(x, y + r);\r\n    ctx.quadraticCurveTo(x, y, x + r, y);\r\n    ctx.closePath();\r\n  }\r\n\r\n  \/\/ ---------- physics classes (unchanged) ----------\r\n  function LaserPulse(startX, startY, angle) {\r\n    this.x = startX; this.y = startY;\r\n    this.speed = 13;\r\n    this.vx = Math.sin(angle) * this.speed;\r\n    this.vy = Math.cos(angle) * this.speed;\r\n    this.state = 'air';\r\n    this.opacity = 1;\r\n    this.trail = [];\r\n    this.maxTrail = 14;\r\n    this.scatterRadius = 0;\r\n    this.refracted = false;\r\n  }\r\n  LaserPulse.prototype.update = function (currentDroneY) {\r\n    this.trail.push({ x: this.x, y: this.y, state: this.state });\r\n    if (this.trail.length > this.maxTrail) this.trail.shift();\r\n\r\n    if (this.state === 'air') {\r\n      this.x += this.vx; this.y += this.vy;\r\n\r\n      if (!this.refracted && this.x > env.waterStartX && this.y >= env.waterLevelY) {\r\n        this.state = 'water';\r\n        this.refracted = true;\r\n\r\n        env.ripples.push(new Ripple(this.x, env.waterLevelY));\r\n        env.returns.push(new ReturnPulse(this.x, env.waterLevelY, 'surface'));\r\n        addPointCloudPoint(this.x, env.waterLevelY, 'surface');\r\n\r\n        var angleIn = Math.atan2(this.vx, this.vy);\r\n        var sinTheta1 = Math.sin(angleIn);\r\n        var sinTheta2 = sinTheta1 \/ 1.333;\r\n        var angleOut = Math.asin(sinTheta2);\r\n\r\n        this.speed = 9.5;\r\n        this.vx = Math.sin(angleOut) * this.speed;\r\n        this.vy = Math.cos(angleOut) * this.speed;\r\n      }\r\n\r\n      if (this.x <= env.waterStartX) {\r\n        var landY = getTerrainYAt(this.x, 'land');\r\n        if (this.y >= landY) {\r\n          this.state = 'dead';\r\n          env.returns.push(new ReturnPulse(this.x, landY, 'land'));\r\n          env.ripples.push(new ImpactFlash(this.x, landY, 'land'));\r\n          addPointCloudPoint(this.x, landY, 'land');\r\n        }\r\n      }\r\n    } else if (this.state === 'water') {\r\n      this.x += this.vx; this.y += this.vy;\r\n      this.opacity *= 0.994;\r\n      this.scatterRadius += 0.18;\r\n\r\n      var bedY = getTerrainYAt(this.x, 'bed');\r\n      if (this.y >= bedY) {\r\n        this.state = 'dead';\r\n        env.returns.push(new ReturnPulse(this.x, bedY, 'bed'));\r\n        env.ripples.push(new ImpactFlash(this.x, bedY, 'bed'));\r\n        addPointCloudPoint(this.x, bedY, 'bed');\r\n      }\r\n    }\r\n  };\r\n  LaserPulse.prototype.draw = function () {\r\n    if (this.state === 'air') {\r\n      for (var i = 0; i < this.trail.length; i++) {\r\n        var t = this.trail[i];\r\n        var alpha = (i \/ this.trail.length) * this.opacity;\r\n        ctx.beginPath();\r\n        ctx.arc(t.x, t.y, 1.2, 0, Math.PI * 2);\r\n        ctx.fillStyle = 'rgba(0, 230, 118, ' + (alpha * 0.85) + ')';\r\n        ctx.fill();\r\n      }\r\n      if (!LOW_POWER) { ctx.shadowBlur = 14; ctx.shadowColor = 'rgba(0, 230, 118, 0.9)'; }\r\n      ctx.beginPath();\r\n      ctx.arc(this.x, this.y, 2.2, 0, Math.PI * 2);\r\n      ctx.fillStyle = 'rgba(210, 255, 230, ' + this.opacity + ')';\r\n      ctx.fill();\r\n      ctx.shadowBlur = 0;\r\n    } else if (this.state === 'water') {\r\n      for (var j = 0; j < this.trail.length; j++) {\r\n        var tw = this.trail[j];\r\n        if (tw.state === 'water') {\r\n          var alphaW = (j \/ this.trail.length) * this.opacity * 0.6;\r\n          ctx.beginPath();\r\n          ctx.arc(tw.x, tw.y, 1.4 + this.scatterRadius * 0.12, 0, Math.PI * 2);\r\n          ctx.fillStyle = 'rgba(40, 255, 140, ' + alphaW + ')';\r\n          ctx.fill();\r\n        }\r\n      }\r\n      if (!LOW_POWER) { ctx.shadowBlur = 18; ctx.shadowColor = 'rgba(0, 230, 118, 0.7)'; }\r\n      ctx.beginPath();\r\n      ctx.arc(this.x, this.y, 2.8 + this.scatterRadius * 0.4, 0, Math.PI * 2);\r\n      ctx.fillStyle = 'rgba(180, 255, 215, ' + this.opacity + ')';\r\n      ctx.fill();\r\n      ctx.shadowBlur = 0;\r\n    }\r\n  };\r\n\r\n  function ReturnPulse(startX, startY, type) {\r\n    this.x = startX; this.y = startY;\r\n    this.type = type;\r\n    this.speed = 17;\r\n    this.opacity = 0.95;\r\n    this.trail = [];\r\n    this.maxTrail = 6;\r\n    this.state = (type === 'bed') ? 'water' : 'air';\r\n  }\r\n  ReturnPulse.prototype.update = function (droneX, droneReceiverY) {\r\n    this.trail.push({ x: this.x, y: this.y });\r\n    if (this.trail.length > this.maxTrail) this.trail.shift();\r\n\r\n    var dx = droneX - this.x;\r\n    var dy = droneReceiverY - this.y;\r\n    var dist = Math.sqrt(dx * dx + dy * dy);\r\n\r\n    if (dist > 0) {\r\n      this.vx = (dx \/ dist) * this.speed;\r\n      this.vy = (dy \/ dist) * this.speed;\r\n    }\r\n    this.x += this.vx; this.y += this.vy;\r\n\r\n    if (this.state === 'water' && this.y <= env.waterLevelY) {\r\n      this.state = 'air';\r\n      this.speed = 22;\r\n    }\r\n    if (this.y <= droneReceiverY + 4 || dist < 18) {\r\n      this.opacity = 0;\r\n    }\r\n  };\r\n  ReturnPulse.prototype.draw = function () {\r\n    var color = (this.type === 'surface') ? '56, 189, 248' :\r\n                (this.type === 'land') ? '255, 182, 1' : '0, 230, 118';\r\n    for (var i = 0; i < this.trail.length; i++) {\r\n      var t = this.trail[i];\r\n      var alpha = (i \/ this.trail.length) * this.opacity;\r\n      ctx.beginPath();\r\n      ctx.arc(t.x, t.y, 1, 0, Math.PI * 2);\r\n      ctx.fillStyle = 'rgba(' + color + ', ' + (alpha * 0.7) + ')';\r\n      ctx.fill();\r\n    }\r\n    if (!LOW_POWER) { ctx.shadowBlur = 6; ctx.shadowColor = 'rgba(' + color + ', 0.8)'; }\r\n    ctx.beginPath();\r\n    ctx.arc(this.x, this.y, 1.5, 0, Math.PI * 2);\r\n    ctx.fillStyle = 'rgba(255, 255, 255, ' + this.opacity + ')';\r\n    ctx.fill();\r\n    ctx.shadowBlur = 0;\r\n  };\r\n\r\n  function Ripple(x, y) { this.x = x; this.y = y; this.radius = 0; this.opacity = 0.7; }\r\n  Ripple.prototype.update = function () { this.radius += 0.9; this.opacity -= 0.022; };\r\n  Ripple.prototype.draw = function () {\r\n    if (this.opacity <= 0) return;\r\n    ctx.strokeStyle = 'rgba(56, 189, 248, ' + this.opacity + ')';\r\n    ctx.lineWidth = 1;\r\n    ctx.beginPath();\r\n    ctx.ellipse(this.x, this.y, this.radius, this.radius * 0.28, 0, 0, Math.PI * 2);\r\n    ctx.stroke();\r\n  };\r\n\r\n  function ImpactFlash(x, y, type) { this.x = x; this.y = y; this.radius = 0; this.opacity = 1; this.type = type; }\r\n  ImpactFlash.prototype.update = function () { this.radius += 1.6; this.opacity -= 0.07; };\r\n  ImpactFlash.prototype.draw = function () {\r\n    if (this.opacity <= 0) return;\r\n    var baseColor = (this.type === 'bed') ? '0, 230, 118' : '255, 182, 1';\r\n    var gradient = ctx.createRadialGradient(this.x, this.y, 0, this.x, this.y, Math.max(1, this.radius));\r\n    gradient.addColorStop(0, 'rgba(255, 255, 255, ' + this.opacity + ')');\r\n    gradient.addColorStop(0.4, 'rgba(' + baseColor + ', ' + (this.opacity * 0.5) + ')');\r\n    gradient.addColorStop(1, 'rgba(' + baseColor + ', 0)');\r\n    ctx.fillStyle = gradient;\r\n    ctx.beginPath();\r\n    ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);\r\n    ctx.fill();\r\n  };\r\n\r\n  function getTerrainYAt(x, type) {\r\n    var points = (type === 'land') ? env.landPoints : env.bedPoints;\r\n    if (points.length === 0) return H;\r\n    if (x < points[0].x) return points[0].y;\r\n    if (x > points[points.length - 1].x) return points[points.length - 1].y;\r\n    for (var i = 0; i < points.length - 1; i++) {\r\n      if (x >= points[i].x && x <= points[i + 1].x) {\r\n        var t = (x - points[i].x) \/ (points[i + 1].x - points[i].x);\r\n        return points[i].y + t * (points[i + 1].y - points[i].y);\r\n      }\r\n    }\r\n    return H;\r\n  }\r\n\r\n  function addPointCloudPoint(x, y, type) {\r\n    var cap = LOW_POWER ? 3000 : 6000;\r\n    if (env.pointCloud.length < cap) {\r\n      env.pointCloud.push({ x: x, y: y, type: type, alpha: 0 });\r\n      env.pointCount++;\r\n    }\r\n  }\r\n\r\n  function drawGrid() {\r\n    ctx.strokeStyle = 'rgba(255, 255, 255, 0.025)';\r\n    ctx.lineWidth = 1;\r\n    var gridSize = 40;\r\n    for (var x = 0; x < W; x += gridSize) { ctx.beginPath(); ctx.moveTo(x, 0); ctx.lineTo(x, H); ctx.stroke(); }\r\n    for (var y = 0; y < H; y += gridSize) { ctx.beginPath(); ctx.moveTo(0, y); ctx.lineTo(W, y); ctx.stroke(); }\r\n  }\r\n\r\n  function drawBackground() {\r\n    ctx.fillStyle = env.airGrad;\r\n    ctx.fillRect(0, 0, W, env.waterLevelY);\r\n\r\n    ctx.fillStyle = env.waterGrad;\r\n    ctx.fillRect(env.waterStartX, env.waterLevelY, W - env.waterStartX, H - env.waterLevelY);\r\n\r\n    ctx.fillStyle = '#06080b';\r\n    ctx.fillRect(0, env.waterLevelY, env.waterStartX, H - env.waterLevelY);\r\n  }\r\n\r\n  function drawTerrain() {\r\n    ctx.fillStyle = '#0B0F14';\r\n    ctx.beginPath();\r\n    ctx.moveTo(0, H);\r\n    ctx.lineTo(0, env.landPoints[0].y);\r\n    env.landPoints.forEach(function (p) { ctx.lineTo(p.x, p.y); });\r\n    ctx.lineTo(env.waterStartX, H);\r\n    ctx.closePath();\r\n    ctx.fill();\r\n\r\n    ctx.strokeStyle = 'rgba(255, 182, 1, 0.55)';\r\n    ctx.lineWidth = 1.5;\r\n    ctx.beginPath();\r\n    env.landPoints.forEach(function (p, i) { if (i === 0) ctx.moveTo(p.x, p.y); else ctx.lineTo(p.x, p.y); });\r\n    ctx.stroke();\r\n\r\n    ctx.fillStyle = '#070B0E';\r\n    ctx.beginPath();\r\n    ctx.moveTo(env.waterStartX, H);\r\n    ctx.lineTo(env.waterStartX, env.waterLevelY);\r\n    env.bedPoints.forEach(function (p) { ctx.lineTo(p.x, p.y); });\r\n    ctx.lineTo(W, H);\r\n    ctx.closePath();\r\n    ctx.fill();\r\n\r\n    ctx.strokeStyle = 'rgba(0, 230, 118, 0.45)';\r\n    ctx.lineWidth = 1.5;\r\n    ctx.beginPath();\r\n    env.bedPoints.forEach(function (p, i) { if (i === 0) ctx.moveTo(p.x, p.y); else ctx.lineTo(p.x, p.y); });\r\n    ctx.stroke();\r\n  }\r\n\r\n  function drawWaterSurface() {\r\n    ctx.strokeStyle = 'rgba(56, 189, 248, 0.6)';\r\n    ctx.lineWidth = 1.2;\r\n    ctx.beginPath();\r\n    for (var x = env.waterStartX; x <= W; x += 4) {\r\n      var y = env.waterLevelY + Math.sin(x * 0.04 + env.time * 0.02) * 1.5;\r\n      if (x === env.waterStartX) ctx.moveTo(x, y); else ctx.lineTo(x, y);\r\n    }\r\n    ctx.stroke();\r\n\r\n    ctx.strokeStyle = 'rgba(255, 255, 255, 0.18)';\r\n    ctx.lineWidth = 1;\r\n    ctx.beginPath();\r\n    for (var x2 = env.waterStartX; x2 <= W; x2 += 6) {\r\n      var y2 = env.waterLevelY + Math.sin(x2 * 0.04 + env.time * 0.02) * 1.5 - 1.5;\r\n      if (x2 === env.waterStartX) ctx.moveTo(x2, y2); else ctx.lineTo(x2, y2);\r\n    }\r\n    ctx.stroke();\r\n  }\r\n\r\n  function drawParticles() {\r\n    env.particles.forEach(function (p) {\r\n      p.y -= p.speed;\r\n      p.x += Math.sin(env.time * 0.015 + p.y * 0.08) * 0.25;\r\n      if (p.y < env.waterLevelY || p.x < env.waterStartX) {\r\n        p.y = env.bedLevelY + 10;\r\n        p.x = env.waterStartX + Math.random() * (W - env.waterStartX);\r\n      }\r\n      ctx.fillStyle = 'rgba(70, 200, 220, ' + (p.opacity * 0.7) + ')';\r\n      ctx.beginPath(); ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2); ctx.fill();\r\n    });\r\n  }\r\n\r\n  function drawPointCloud() {\r\n    env.pointCloud.forEach(function (p) {\r\n      if (p.alpha < 1) p.alpha += 0.04;\r\n      var color = (p.type === 'surface') ? '56, 189, 248' :\r\n                  (p.type === 'land') ? '255, 182, 1' : '0, 230, 118';\r\n      ctx.fillStyle = 'rgba(' + color + ', ' + (p.alpha * 0.85) + ')';\r\n      ctx.beginPath();\r\n      ctx.arc(p.x, p.y, 1.4, 0, Math.PI * 2);\r\n      ctx.fill();\r\n    });\r\n  }\r\n\r\n  function drawDrone(x, y) {\r\n    ctx.save();\r\n    ctx.translate(x, y);\r\n\r\n    var shadowY = (x < env.waterStartX) ? getTerrainYAt(x, 'land') : env.waterLevelY;\r\n    var shadowDist = shadowY - y;\r\n    var shadowScale = Math.max(0.4, 1 - shadowDist \/ 400);\r\n\r\n    ctx.fillStyle = 'rgba(0, 0, 0, 0.35)';\r\n    ctx.beginPath();\r\n    ctx.ellipse(0, shadowDist - 4, 38 * shadowScale, 5 * shadowScale, 0, 0, Math.PI * 2);\r\n    ctx.fill();\r\n\r\n    ctx.strokeStyle = '#282828';\r\n    ctx.lineWidth = 2.5;\r\n    ctx.beginPath();\r\n    ctx.moveTo(-30, 0); ctx.lineTo(-52, -10);\r\n    ctx.moveTo(30, 0); ctx.lineTo(52, -10);\r\n    ctx.moveTo(-20, 0); ctx.lineTo(-36, -16);\r\n    ctx.moveTo(20, 0); ctx.lineTo(36, -16);\r\n    ctx.stroke();\r\n\r\n    ctx.fillStyle = '#16191E';\r\n    ctx.strokeStyle = '#333842';\r\n    ctx.lineWidth = 1;\r\n    drawRoundRect(-26, -8, 52, 16, 4);\r\n    ctx.fill(); ctx.stroke();\r\n\r\n    ctx.fillStyle = '#222730';\r\n    drawRoundRect(-16, -13, 32, 7, 2);\r\n    ctx.fill();\r\n\r\n    ctx.fillStyle = '#0D1117';\r\n    ctx.strokeStyle = '#FFB601';\r\n    ctx.lineWidth = 1.2;\r\n    drawRoundRect(-14, 8, 28, 14, 2);\r\n    ctx.fill(); ctx.stroke();\r\n\r\n    ctx.fillStyle = '#00E676';\r\n    if (!LOW_POWER) { ctx.shadowBlur = 10; ctx.shadowColor = 'rgba(0, 230, 118, 0.9)'; }\r\n    ctx.beginPath();\r\n    ctx.arc(0, 16, 3, 0, Math.PI * 2);\r\n    ctx.fill();\r\n    ctx.shadowBlur = 0;\r\n\r\n    var r = 20;\r\n    ctx.fillStyle = 'rgba(255, 255, 255, 0.08)';\r\n    ctx.beginPath(); ctx.ellipse(-52, -10, r, 2.5, 0, 0, Math.PI * 2); ctx.fill();\r\n    ctx.beginPath(); ctx.ellipse(52, -10, r, 2.5, 0, 0, Math.PI * 2); ctx.fill();\r\n    ctx.beginPath(); ctx.ellipse(-36, -16, r, 2.5, 0, 0, Math.PI * 2); ctx.fill();\r\n    ctx.beginPath(); ctx.ellipse(36, -16, r, 2.5, 0, 0, Math.PI * 2); ctx.fill();\r\n\r\n    ctx.restore();\r\n  }\r\n\r\n  function drawScanCone() {\r\n    var isOverWater = env.droneX >= env.waterStartX;\r\n\r\n    if (!isOverWater) {\r\n      var landY = getTerrainYAt(env.droneX, 'land');\r\n      var grad = ctx.createLinearGradient(env.droneX, env.droneBaseY + 16, env.droneX, landY);\r\n      grad.addColorStop(0, 'rgba(0, 230, 118, 0.12)');\r\n      grad.addColorStop(1, 'rgba(0, 230, 118, 0.01)');\r\n      ctx.fillStyle = grad;\r\n      ctx.beginPath();\r\n      ctx.moveTo(env.droneX - 4, env.droneBaseY + 16);\r\n      ctx.lineTo(env.droneX + 4, env.droneBaseY + 16);\r\n      ctx.lineTo(env.droneX + 85, landY);\r\n      ctx.lineTo(env.droneX - 85, landY);\r\n      ctx.closePath();\r\n      ctx.fill();\r\n    } else {\r\n      var gradAir = ctx.createLinearGradient(env.droneX, env.droneBaseY + 16, env.droneX, env.waterLevelY);\r\n      gradAir.addColorStop(0, 'rgba(0, 230, 118, 0.14)');\r\n      gradAir.addColorStop(1, 'rgba(0, 230, 118, 0.04)');\r\n      ctx.fillStyle = gradAir;\r\n      ctx.beginPath();\r\n      ctx.moveTo(env.droneX - 4, env.droneBaseY + 16);\r\n      ctx.lineTo(env.droneX + 4, env.droneBaseY + 16);\r\n      ctx.lineTo(env.droneX + 70, env.waterLevelY);\r\n      ctx.lineTo(env.droneX - 70, env.waterLevelY);\r\n      ctx.closePath();\r\n      ctx.fill();\r\n\r\n      var bedY = getTerrainYAt(env.droneX, 'bed');\r\n      var gradWater = ctx.createLinearGradient(env.droneX, env.waterLevelY, env.droneX, bedY);\r\n      gradWater.addColorStop(0, 'rgba(0, 230, 118, 0.08)');\r\n      gradWater.addColorStop(0.6, 'rgba(0, 230, 118, 0.04)');\r\n      gradWater.addColorStop(1, 'rgba(0, 230, 118, 0.0)');\r\n      ctx.fillStyle = gradWater;\r\n      ctx.beginPath();\r\n      ctx.moveTo(env.droneX - 70, env.waterLevelY);\r\n      ctx.lineTo(env.droneX + 70, env.waterLevelY);\r\n      ctx.lineTo(env.droneX + 110, bedY);\r\n      ctx.lineTo(env.droneX - 110, bedY);\r\n      ctx.closePath();\r\n      ctx.fill();\r\n    }\r\n  }\r\n\r\n  var lastTelemetryUpdate = 0;\r\n  function updateDynamicHUD() {\r\n    var transMargin = 70;\r\n    var isNearTransition = Math.abs(env.droneX - env.waterStartX) < transMargin;\r\n    var isOverWater = env.droneX >= env.waterStartX;\r\n\r\n    if (isNearTransition) {\r\n      if (lblTrans) lblTrans.classList.add('active');\r\n      if (lblLand) lblLand.classList.remove('active');\r\n      if (lblSurf) lblSurf.classList.remove('active');\r\n      if (lblBed) lblBed.classList.remove('active');\r\n    } else if (!isOverWater) {\r\n      if (lblLand) lblLand.classList.add('active');\r\n      if (lblTrans) lblTrans.classList.remove('active');\r\n      if (lblSurf) lblSurf.classList.remove('active');\r\n      if (lblBed) lblBed.classList.remove('active');\r\n    } else {\r\n      if (lblSurf) lblSurf.classList.add('active');\r\n      if (lblBed) lblBed.classList.add('active');\r\n      if (lblLand) lblLand.classList.remove('active');\r\n      if (lblTrans) lblTrans.classList.remove('active');\r\n    }\r\n\r\n    if (env.time - lastTelemetryUpdate > 10) {\r\n      lastTelemetryUpdate = env.time;\r\n\r\n      if (returnStatusEl) {\r\n        if (isNearTransition) {\r\n          returnStatusEl.innerText = 'BANK & TOE CONTINUITY';\r\n          returnStatusEl.className = 'data-value highlight-yellow';\r\n        } else if (!isOverWater) {\r\n          returnStatusEl.innerText = 'TOPO RETURN (LAND)';\r\n          returnStatusEl.className = 'data-value highlight-yellow';\r\n        } else {\r\n          returnStatusEl.innerText = 'DUAL-ECHO (SURFACE + BED)';\r\n          returnStatusEl.className = 'data-value highlight-green';\r\n        }\r\n      }\r\n      if (pointCountEl) {\r\n        pointCountEl.innerText = env.pointCount.toLocaleString() + ' PTS';\r\n      }\r\n    }\r\n  }\r\n\r\n  \/\/ ---------- main loop ----------\r\n  var pulseTimer = 0;\r\n  function animate() {\r\n    if (!inView) { rafId = null; return; } \/\/ fully stop scheduling while off-screen\r\n\r\n    if (!isPaused) {\r\n      ctx.clearRect(0, 0, W, H);\r\n      env.time += SCAN_SPEED;\r\n\r\n      env.droneX += 1.15 * SCAN_SPEED;\r\n\r\n      if (env.droneX > W + 60) {\r\n        env.droneX = -60;\r\n        env.pulses = [];\r\n        env.returns = [];\r\n        env.ripples = [];\r\n        env.pointCloud = [];\r\n        env.pointCount = 0;\r\n        if (pointCountEl) pointCountEl.innerText = '0 PTS';\r\n      }\r\n\r\n      var currentDroneY = env.droneBaseY + Math.sin(env.time * 0.015) * 3;\r\n      var droneReceiverY = currentDroneY + 16;\r\n\r\n      drawGrid();\r\n      drawBackground();\r\n      drawParticles();\r\n      drawTerrain();\r\n      drawPointCloud();\r\n      drawWaterSurface();\r\n      drawScanCone();\r\n\r\n      if (env.droneX >= -20 && env.droneX <= W + 20) {\r\n        pulseTimer += SCAN_SPEED;\r\n        if (pulseTimer >= 5.5) {\r\n          pulseTimer = 0;\r\n          var numPulses = LOW_POWER ? 3 : 5;\r\n          var halfFov = 21 * (Math.PI \/ 180);\r\n          for (var i = 0; i < numPulses; i++) {\r\n            var angle = (-halfFov + (i \/ (numPulses - 1)) * (2 * halfFov));\r\n            var ellipseSweep = Math.sin(env.time * 0.06) * 0.05;\r\n            env.pulses.push(new LaserPulse(env.droneX, droneReceiverY, angle + ellipseSweep));\r\n          }\r\n        }\r\n      }\r\n\r\n      for (var pi = env.pulses.length - 1; pi >= 0; pi--) {\r\n        var pulse = env.pulses[pi];\r\n        pulse.update(currentDroneY);\r\n        pulse.draw();\r\n        if (pulse.state === 'dead' || pulse.opacity < 0.04) env.pulses.splice(pi, 1);\r\n      }\r\n\r\n      for (var ri = env.ripples.length - 1; ri >= 0; ri--) {\r\n        var rip = env.ripples[ri];\r\n        rip.update(); rip.draw();\r\n        if (rip.opacity <= 0) env.ripples.splice(ri, 1);\r\n      }\r\n\r\n      for (var reti = env.returns.length - 1; reti >= 0; reti--) {\r\n        var ret = env.returns[reti];\r\n        ret.update(env.droneX, droneReceiverY);\r\n        ret.draw();\r\n        if (ret.opacity <= 0 || ret.y <= droneReceiverY + 4) env.returns.splice(reti, 1);\r\n        else ret.opacity -= 0.012;\r\n      }\r\n\r\n      drawDrone(env.droneX, currentDroneY);\r\n      updateDynamicHUD();\r\n    }\r\n\r\n    rafId = requestAnimationFrame(animate);\r\n  }\r\n\r\n  function startLoop() {\r\n    if (rafId === null) {\r\n      rafId = requestAnimationFrame(animate);\r\n    }\r\n  }\r\n\r\n  \/\/ ---------- responsive wiring ----------\r\n  var resizeTimer = null;\r\n  function onResize() {\r\n    clearTimeout(resizeTimer);\r\n    resizeTimer = setTimeout(applyCanvasSize, 80);\r\n  }\r\n\r\n  var ro = null;\r\n  if (window.ResizeObserver) {\r\n    ro = new ResizeObserver(onResize);\r\n    ro.observe(canvasContainer);\r\n  } else {\r\n    window.addEventListener('resize', onResize);\r\n  }\r\n\r\n  var io = null;\r\n  if (window.IntersectionObserver) {\r\n    io = new IntersectionObserver(function (entries) {\r\n      entries.forEach(function (entry) {\r\n        inView = entry.isIntersecting;\r\n        if (inView) startLoop();\r\n      });\r\n    }, { threshold: 0.05 });\r\n    io.observe(container);\r\n  }\r\n\r\n  function onPauseClick() {\r\n    isPaused = !isPaused;\r\n    if (pauseBtn) pauseBtn.innerText = isPaused ? 'RESUME' : 'PAUSE';\r\n  }\r\n  if (pauseBtn) pauseBtn.addEventListener('click', onPauseClick);\r\n\r\n  function onKeydown(e) {\r\n    if (e.code !== 'Space') return;\r\n    \/\/ Only toggle if nothing on the page has focus (avoid hijacking spacebar\r\n    \/\/ from inputs\/buttons\/forms elsewhere on the site) and this widget is visible.\r\n    var active = document.activeElement;\r\n    var nothingFocused = !active || active === document.body;\r\n    if (nothingFocused && inView) {\r\n      isPaused = !isPaused;\r\n      if (pauseBtn) pauseBtn.innerText = isPaused ? 'RESUME' : 'PAUSE';\r\n    }\r\n  }\r\n  window.addEventListener('keydown', onKeydown);\r\n\r\n  \/\/ ---------- init ----------\r\n  applyCanvasSize();\r\n  startLoop();\r\n\r\n  container._vltCleanup = function () {\r\n    if (rafId !== null) cancelAnimationFrame(rafId);\r\n    rafId = null;\r\n    if (ro) ro.disconnect();\r\n    if (io) io.disconnect();\r\n    window.removeEventListener('resize', onResize);\r\n    window.removeEventListener('keydown', onKeydown);\r\n    if (pauseBtn) pauseBtn.removeEventListener('click', onPauseClick);\r\n  };\r\n})();\r\n<\/script>\r\n<\/div>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-b9e728a e-flex e-con-boxed e-con e-parent\" data-id=\"b9e728a\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-ae22cd3 elementor-widget elementor-widget-heading\" data-id=\"ae22cd3\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Mapping Where\n<span style=\"color: #FFB601\">Land Meets Water\n<\/h2>\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-327fe25 e-grid e-con-full e-con e-child\" data-id=\"327fe25\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-4b8ce47 e-con-full e-flex e-con e-child\" data-id=\"4b8ce47\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-7ff6ec2 e-con-full e-flex e-con e-child\" data-id=\"7ff6ec2\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-f8c730e e-con-full e-flex e-con e-child\" data-id=\"f8c730e\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t<div class=\"elementor-element elementor-element-8775e2f elementor-widget elementor-widget-heading\" data-id=\"8775e2f\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Wetland &amp; Shoreline Mapping\n<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-1d22484 elementor-widget elementor-widget-text-editor\" data-id=\"1d22484\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\tVegetation, water bottom, and adjacent topography in one dataset. No stitching separate surveys.\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-18b28b6 e-con-full e-flex e-con e-child\" data-id=\"18b28b6\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-1dfb9a6 e-con-full e-flex e-con e-child\" data-id=\"1dfb9a6\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-8ffc248 e-con-full e-flex e-con e-child\" data-id=\"8ffc248\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t<div class=\"elementor-element elementor-element-9b58229 elementor-widget elementor-widget-heading\" data-id=\"9b58229\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">River &amp; Floodplain Surveys\n<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-ca3890c elementor-widget elementor-widget-text-editor\" data-id=\"ca3890c\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\tIncluding pre-freshet and low-tide timing windows for comprehensive coverage.\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-b758a9b e-con-full e-flex e-con e-child\" data-id=\"b758a9b\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-7976b86 e-con-full e-flex e-con e-child\" data-id=\"7976b86\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-e6dc997 e-con-full e-flex e-con e-child\" data-id=\"e6dc997\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t<div class=\"elementor-element elementor-element-7403c08 elementor-widget elementor-widget-heading\" data-id=\"7403c08\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Infrastructure Clearance\n<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-cf38412 elementor-widget elementor-widget-text-editor\" data-id=\"cf38412\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\tCulvert, bridge, dam, and infrastructure surveys where the channel bed matters.\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-b380c65 e-con-full e-flex e-con e-child\" data-id=\"b380c65\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-b7ea4c9 e-con-full e-flex e-con e-child\" data-id=\"b7ea4c9\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-683d222 e-con-full e-flex e-con e-child\" data-id=\"683d222\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t<div class=\"elementor-element elementor-element-f3aeed7 elementor-widget elementor-widget-heading\" data-id=\"f3aeed7\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Environmental Studies\n<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-a1a3ccf elementor-widget elementor-widget-text-editor\" data-id=\"a1a3ccf\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\tEnvironmental baseline and habitat studies requiring high-precision integrated data.\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-f17dada e-con-full e-flex e-con e-child\" data-id=\"f17dada\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-d347d03 e-con-full e-flex e-con e-child\" data-id=\"d347d03\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-3900679 e-con-full e-flex e-con e-child\" data-id=\"3900679\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t<div class=\"elementor-element elementor-element-4f77682 elementor-widget elementor-widget-heading\" data-id=\"4f77682\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Dredging Volumetrics\n<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-a854ade elementor-widget elementor-widget-text-editor\" data-id=\"a854ade\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\tDredging planning and volumetric analysis with absolute precision.\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-8468b82 e-con-full e-flex e-con e-child\" data-id=\"8468b82\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-f029074 e-con-full e-flex e-con e-child\" data-id=\"f029074\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-75a76f7 e-con-full e-flex e-con e-child\" data-id=\"75a76f7\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t<div class=\"elementor-element elementor-element-e4218f9 elementor-widget elementor-widget-heading\" data-id=\"e4218f9\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Hydrographic Surveys\n<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-a372190 elementor-widget elementor-widget-text-editor\" data-id=\"a372190\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\tFor ports, marinas, and inland waterways where full boat-based bathymetry isn&#8217;t practical.\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-f5bf91a e-flex e-con-boxed e-con e-parent\" data-id=\"f5bf91a\" data-element_type=\"container\" data-e-type=\"container\" id=\"dark-particle-section\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t<div class=\"elementor-element elementor-element-18bbf3e e-con-full glass-card e-flex e-con e-child\" data-id=\"18bbf3e\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-f338f94 e-con-full e-flex e-con e-child\" data-id=\"f338f94\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t<div class=\"elementor-element elementor-element-1c6bce9 elementor-widget elementor-widget-image\" data-id=\"1c6bce9\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"550\" height=\"550\" src=\"https:\/\/volatusaerospace.com\/wp-content\/uploads\/2026\/05\/ys_navigator_laser_scanner_.png\" class=\"attachment-large size-large wp-image-27316\" alt=\"\" srcset=\"https:\/\/volatusaerospace.com\/wp-content\/uploads\/2026\/05\/ys_navigator_laser_scanner_.png 550w, https:\/\/volatusaerospace.com\/wp-content\/uploads\/2026\/05\/ys_navigator_laser_scanner_-300x300.png 300w, https:\/\/volatusaerospace.com\/wp-content\/uploads\/2026\/05\/ys_navigator_laser_scanner_-150x150.png 150w\" sizes=\"(max-width: 550px) 100vw, 550px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-74a0f3b elementor-widget elementor-widget-html\" data-id=\"74a0f3b\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t\r\n\r\n<style>\r\n@keyframes vlRadarCW    { to { transform: rotate(360deg);  } }\r\n@keyframes vlRadarCCW   { to { transform: rotate(-360deg); } }\r\n@keyframes vlRadarSweep { to { transform: rotate(360deg);  } }\r\n@keyframes vlRadarPulse { 0%,100%{opacity:0.2} 50%{opacity:0.55} }\r\n\r\n.vl-radar-overlay {\r\n  position: absolute !important;\r\n  top: 50% !important;\r\n  left: 50% !important;\r\n  transform: translate(-50%, -50%) !important;\r\n  pointer-events: none !important;\r\n  z-index: 1 !important;\r\n}\r\n\r\n.vl-radar-sweep {\r\n  position: absolute;\r\n  inset: 0;\r\n  border-radius: 50%;\r\n  background: conic-gradient(\r\n    transparent 0deg,\r\n    transparent 285deg,\r\n    rgba(245, 162, 0, 0.07) 312deg,\r\n    rgba(245, 162, 0, 0.09) 348deg,\r\n    rgba(245, 162, 0, 0.16) 360deg\r\n  );\r\n  animation: vlRadarSweep 18s linear infinite;\r\n}\r\n\r\n.vl-radar-svg {\r\n  position: absolute;\r\n  inset: 0;\r\n  \/* SVG uses viewBox=\"0 0 100 100\" so it always fills the overlay *\/\r\n  width: 100%;\r\n  height: 100%;\r\n  overflow: visible;\r\n}\r\n<\/style>\r\n\r\n<div id=\"vl-radar-anchor\" style=\"display:none;\"><\/div>\r\n\r\n<script>\r\n(function () {\r\n  'use strict';\r\n\r\n  \/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n     ADJUST THIS ONE VALUE TO RESIZE THE WHOLE ANIMATION\r\n     \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n     % of the section's shortest dimension (width or height).\r\n     Examples:\r\n       50  \u2192 compact ring behind the drone only\r\n       75  \u2192 standard \u2014 fills nicely between the four cards\r\n       90  \u2192 large, nearly touching the corner cards\r\n       100 \u2192 full shortest-side coverage                        *\/\r\n  var SIZE_PERCENT = 105;\r\n  \/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n\r\n  var GOLD = '#F5A200';   \/* ring \/ tick color \u2014 change freely *\/\r\n  var ns   = 'http:\/\/www.w3.org\/2000\/svg';\r\n\r\n  \/* \u2500\u2500 find the parent Elementor section \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\r\n  function findSection(anchor) {\r\n    var el = anchor.parentElement;\r\n    for (var i = 0; i < 25 && el; i++) {\r\n      if (\r\n        el.tagName === 'SECTION' ||\r\n        el.classList.contains('elementor-section') ||\r\n        el.classList.contains('e-con') ||\r\n        el.classList.contains('elementor-top-section') ||\r\n        el.hasAttribute('data-elementor-type')\r\n      ) return el;\r\n      el = el.parentElement;\r\n    }\r\n    return anchor.closest('.elementor-widget-wrap') || anchor.parentElement;\r\n  }\r\n\r\n  \/* \u2500\u2500 compute pixel size from section dimensions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\r\n  function computeSize(section) {\r\n    var w = section.offsetWidth  || 800;\r\n    var h = section.offsetHeight || 600;\r\n    return Math.min(w, h) * SIZE_PERCENT \/ 100;\r\n  }\r\n\r\n  \/* \u2500\u2500 SVG helpers (normalised 100\u00d7100 coordinate space) \u2500\u2500\u2500\u2500 *\/\r\n  \/* All rings are drawn in a 0\u2013100 unit box.\r\n     CX = CY = 50 always.  Resizing is purely a matter of\r\n     changing the overlay <div> dimensions \u2014 the SVG scales\r\n     automatically via viewBox \/ width:100% \/ height:100%.    *\/\r\n\r\n  var CX = 50, CY = 50;\r\n\r\n  function makeRing(r, dash, op, dur, dir, sw) {\r\n    var g = document.createElementNS(ns, 'g');\r\n    \/* transform-origin in % works reliably for SVG in all browsers *\/\r\n    g.style.cssText =\r\n      'transform-origin:50% 50%;' +\r\n      'animation:vlRadar' + (dir > 0 ? 'CW' : 'CCW') + ' ' + dur + 's linear infinite;';\r\n    var c = document.createElementNS(ns, 'circle');\r\n    c.setAttribute('cx', CX);\r\n    c.setAttribute('cy', CY);\r\n    c.setAttribute('r',  r);\r\n    c.setAttribute('fill',          'none');\r\n    c.setAttribute('stroke',        GOLD);\r\n    c.setAttribute('stroke-width',  sw);\r\n    c.setAttribute('stroke-opacity', op);\r\n    if (dash) c.setAttribute('stroke-dasharray', dash);\r\n    g.appendChild(c);\r\n    return g;\r\n  }\r\n\r\n  function makeTicks(r, count, len, op) {\r\n    var g = document.createElementNS(ns, 'g');\r\n    g.style.cssText =\r\n      'transform-origin:50% 50%;' +\r\n      'animation:vlRadarCW 95s linear infinite;';\r\n    for (var i = 0; i < count; i++) {\r\n      var angle  = (i \/ count) * Math.PI * 2 - Math.PI \/ 2;\r\n      var major  = i % (count \/ 4) === 0;\r\n      var mid    = i % (count \/ 8) === 0;\r\n      var tl     = major ? len * 2.8 : mid ? len * 1.7 : len;\r\n      var sw     = major ? 0.22 : mid ? 0.15 : 0.09;\r\n      var tickOp = major ? Math.min(op * 3.2, 0.70) : mid ? op * 2.0 : op;\r\n      var x1 = CX + (r - tl) * Math.cos(angle);\r\n      var y1 = CY + (r - tl) * Math.sin(angle);\r\n      var x2 = CX + r * Math.cos(angle);\r\n      var y2 = CY + r * Math.sin(angle);\r\n      var ln = document.createElementNS(ns, 'line');\r\n      ln.setAttribute('x1', x1.toFixed(3)); ln.setAttribute('y1', y1.toFixed(3));\r\n      ln.setAttribute('x2', x2.toFixed(3)); ln.setAttribute('y2', y2.toFixed(3));\r\n      ln.setAttribute('stroke',         GOLD);\r\n      ln.setAttribute('stroke-width',   sw);\r\n      ln.setAttribute('stroke-opacity', tickOp);\r\n      g.appendChild(ln);\r\n    }\r\n    return g;\r\n  }\r\n\r\n  function makeCrosshair() {\r\n    var frag = document.createDocumentFragment();\r\n    [[4, CY, 96, CY], [CX, 4, CX, 96]].forEach(function (pts) {\r\n      var l = document.createElementNS(ns, 'line');\r\n      l.setAttribute('x1', pts[0]); l.setAttribute('y1', pts[1]);\r\n      l.setAttribute('x2', pts[2]); l.setAttribute('y2', pts[3]);\r\n      l.setAttribute('stroke',          GOLD);\r\n      l.setAttribute('stroke-width',    '0.07');\r\n      l.setAttribute('stroke-opacity',  '0.1');\r\n      l.setAttribute('stroke-dasharray','0.3 3.5');\r\n      frag.appendChild(l);\r\n    });\r\n    return frag;\r\n  }\r\n\r\n  function makeDot() {\r\n    var c = document.createElementNS(ns, 'circle');\r\n    c.setAttribute('cx', CX); c.setAttribute('cy', CY); c.setAttribute('r', '0.6');\r\n    c.setAttribute('fill', GOLD); c.setAttribute('fill-opacity', '0.45');\r\n    c.style.animation = 'vlRadarPulse 3.5s ease-in-out infinite';\r\n    return c;\r\n  }\r\n\r\n  \/* \u2500\u2500 build the overlay DOM \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\r\n  function buildOverlay() {\r\n    var overlay = document.createElement('div');\r\n    overlay.id        = 'vl-radar-overlay';\r\n    overlay.className = 'vl-radar-overlay';\r\n\r\n    \/* sweep *\/\r\n    var sweep = document.createElement('div');\r\n    sweep.className = 'vl-radar-sweep';\r\n    overlay.appendChild(sweep);\r\n\r\n    \/* svg *\/\r\n    var svg = document.createElementNS(ns, 'svg');\r\n    svg.setAttribute('class',       'vl-radar-svg');\r\n    svg.setAttribute('viewBox',     '0 0 100 100');\r\n    svg.setAttribute('xmlns',       ns);\r\n    svg.setAttribute('aria-hidden', 'true');\r\n\r\n    \/*  ring( radius, dashArray, opacity, duration_s, direction, strokeWidth )\r\n        All values are in the normalised 0\u2013100 unit space.\r\n        Outermost ring r=45, innermost r=13.                              *\/\r\n    svg.appendChild(makeRing(45, '0.55 2.2',  0.40, 95,   1,  0.11));\r\nsvg.appendChild(makeTicks(45, 48, 1.0, 0.40));\r\nsvg.appendChild(makeRing(37, '3.30 1.55', 0.50, 72,  -1,  0.14));\r\nsvg.appendChild(makeRing(29, '1.20 3.60', 0.60, 52,   1,  0.12));\r\nsvg.appendChild(makeRing(21, '2.00 0.90', 0.45, 38,  -1,  0.14));\r\nsvg.appendChild(makeRing(13, null,         0.35, 115,  1,  0.10));\r\n    svg.appendChild(makeCrosshair());\r\n    svg.appendChild(makeDot());\r\n\r\n    overlay.appendChild(svg);\r\n    return overlay;\r\n  }\r\n\r\n  \/* \u2500\u2500 resize handler \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\r\n  function applySize(overlay, section) {\r\n    var px = computeSize(section);\r\n    overlay.style.width  = px + 'px';\r\n    overlay.style.height = px + 'px';\r\n  }\r\n\r\n  \/* \u2500\u2500 init \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\r\n  function init() {\r\n    var anchor = document.getElementById('vl-radar-anchor');\r\n    if (!anchor) return;\r\n\r\n    var section = findSection(anchor);\r\n\r\n    \/* ensure section is positioned so absolute children work *\/\r\n    if (window.getComputedStyle(section).position === 'static') {\r\n      section.style.setProperty('position', 'relative', 'important');\r\n    }\r\n\r\n    \/* remove any existing overlay (safe re-init) *\/\r\n    var old = section.querySelector('#vl-radar-overlay');\r\n    if (old) old.parentNode.removeChild(old);\r\n\r\n    var overlay = buildOverlay();\r\n    applySize(overlay, section);\r\n\r\n    \/* insert behind all other children *\/\r\n    section.insertBefore(overlay, section.firstChild);\r\n\r\n    \/* re-scale on resize *\/\r\n    if (window.ResizeObserver) {\r\n      new ResizeObserver(function () {\r\n        applySize(overlay, section);\r\n      }).observe(section);\r\n    } else {\r\n      window.addEventListener('resize', function () {\r\n        applySize(overlay, section);\r\n      });\r\n    }\r\n  }\r\n\r\n  if (document.readyState === 'loading') {\r\n    document.addEventListener('DOMContentLoaded', init);\r\n  } else {\r\n    setTimeout(init, 50);\r\n  }\r\n\r\n})();\r\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-e266221 e-con-full e-flex e-con e-child\" data-id=\"e266221\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-8623692 elementor-widget elementor-widget-heading\" data-id=\"8623692\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Powered by the  <span style=\"color: #FFB601\">YellowScan Navigator\n<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-ad0e626 elementor-widget elementor-widget-text-editor\" data-id=\"ad0e626\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\tOur topo-bathy capabilities leverage the YellowScan Navigator, a dedicated bathymetric lidar payload designed specifically for shallow, clear-water environments.\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-8a9a0e7 elementor-align-left elementor-mobile-align-left elementor-widget elementor-widget-button\" data-id=\"8a9a0e7\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"button.default\">\n\t\t\t\t\t\t\t\t\t\t<a class=\"elementor-button elementor-button-link elementor-size-sm\" href=\"https:\/\/volatusaerospace.com\/fr-ca\/equipment\/all-products\/yellowscan-navigator\/\">\n\t\t\t\t\t\t<span class=\"elementor-button-content-wrapper\">\n\t\t\t\t\t\t\t\t\t<span class=\"elementor-button-text\">View Equipment Details \u2192<\/span>\n\t\t\t\t\t<\/span>\n\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-2527a35 e-flex e-con-boxed e-con e-parent\" data-id=\"2527a35\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t<div class=\"elementor-element elementor-element-052437f e-con-full filter-section item-drones e-flex e-con e-child\" data-id=\"052437f\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-8c0108f e-con-full e-flex e-con e-child\" data-id=\"8c0108f\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-6ea640e e-con-full e-flex e-con e-child\" data-id=\"6ea640e\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;sticky&quot;:&quot;top&quot;,&quot;sticky_offset&quot;:200,&quot;sticky_parent&quot;:&quot;yes&quot;,&quot;sticky_on&quot;:[&quot;desktop&quot;,&quot;laptop&quot;],&quot;sticky_effects_offset&quot;:0,&quot;sticky_anchor_link_offset&quot;:0}\">\n\t\t\t\t<div class=\"elementor-element elementor-element-52e90c8 elementor-widget elementor-widget-heading\" data-id=\"52e90c8\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">\nErosion &amp; Shoreline\n <span style=\"color: #FFB601\">Change Monitoring.\n<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-75b35a3 elementor-widget elementor-widget-text-editor\" data-id=\"75b35a3\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\tThis is where the land-and-water continuity really pays off A standard topo survey stops at the waterline, so it misses exactly the zone where erosion happens first, the bank face, the toe of slope, and the nearshore bed. <strong>The Navigator captures all of it in one dataset, which supports:<\/strong>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-b0ed8e6 e-con-full e-flex e-con e-child\" data-id=\"b0ed8e6\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-9a64cbc e-grid e-con-full e-con e-child\" data-id=\"9a64cbc\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-7645dba e-con-full e-flex e-con e-child\" data-id=\"7645dba\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;gradient&quot;}\">\n\t\t\t\t<div class=\"elementor-element elementor-element-015495a elementor-widget__width-auto elementor-widget elementor-widget-heading\" data-id=\"015495a\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">01<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-b4f1b58 elementor-widget elementor-widget-icon-box\" data-id=\"b4f1b58\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"icon-box.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-icon-box-wrapper\">\n\n\t\t\t\n\t\t\t\t\t\t<div class=\"elementor-icon-box-content\">\n\n\t\t\t\t\t\t\t\t\t<h3 class=\"elementor-icon-box-title\">\n\t\t\t\t\t\t<span  >\n\t\t\t\t\t\t\tTime-Series Shoreline Monitoring\t\t\t\t\t\t<\/span>\n\t\t\t\t\t<\/h3>\n\t\t\t\t\n\t\t\t\t\t\t\t\t\t<p class=\"elementor-icon-box-description\">\n\t\t\t\t\t\tRepeat surveys at the same site over time, compared as a time series to track shoreline retreat or bank advance.\t\t\t\t\t<\/p>\n\t\t\t\t\n\t\t\t<\/div>\n\t\t\t\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-7766a19 e-con-full e-flex e-con e-child\" data-id=\"7766a19\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;gradient&quot;}\">\n\t\t\t\t<div class=\"elementor-element elementor-element-017e823 elementor-widget__width-auto elementor-widget elementor-widget-heading\" data-id=\"017e823\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">02<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-54ef376 elementor-widget elementor-widget-icon-box\" data-id=\"54ef376\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"icon-box.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-icon-box-wrapper\">\n\n\t\t\t\n\t\t\t\t\t\t<div class=\"elementor-icon-box-content\">\n\n\t\t\t\t\t\t\t\t\t<h3 class=\"elementor-icon-box-title\">\n\t\t\t\t\t\t<span  >\n\t\t\t\t\t\t\tVolumetric Change Detection\t\t\t\t\t\t<\/span>\n\t\t\t\t\t<\/h3>\n\t\t\t\t\n\t\t\t\t\t\t\t\t\t<p class=\"elementor-icon-box-description\">\n\t\t\t\t\t\tVolumetric change detection (cut and fill) between surveys, quantifying material lost or gained rather than just visually flagging it.\t\t\t\t\t<\/p>\n\t\t\t\t\n\t\t\t<\/div>\n\t\t\t\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-ef6c64b e-con-full e-flex e-con e-child\" data-id=\"ef6c64b\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;gradient&quot;}\">\n\t\t\t\t<div class=\"elementor-element elementor-element-cb6f8be elementor-widget__width-auto elementor-widget elementor-widget-heading\" data-id=\"cb6f8be\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">03<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-f19e32a elementor-widget elementor-widget-icon-box\" data-id=\"f19e32a\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"icon-box.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-icon-box-wrapper\">\n\n\t\t\t\n\t\t\t\t\t\t<div class=\"elementor-icon-box-content\">\n\n\t\t\t\t\t\t\t\t\t<h3 class=\"elementor-icon-box-title\">\n\t\t\t\t\t\t<span  >\n\t\t\t\t\t\t\tStorm &amp; Seasonal Change Monitoring\t\t\t\t\t\t<\/span>\n\t\t\t\t\t<\/h3>\n\t\t\t\t\n\t\t\t\t\t\t\t\t\t<p class=\"elementor-icon-box-description\">\n\t\t\t\t\t\tBefore-and-after capture around storm events, spring freshet, or ice breakup, to document rate and extent of change.\t\t\t\t\t<\/p>\n\t\t\t\t\n\t\t\t<\/div>\n\t\t\t\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-541c523 e-con-full e-flex e-con e-child\" data-id=\"541c523\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;gradient&quot;}\">\n\t\t\t\t<div class=\"elementor-element elementor-element-18cade0 elementor-widget__width-auto elementor-widget elementor-widget-heading\" data-id=\"18cade0\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">04<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-d857572 elementor-widget elementor-widget-icon-box\" data-id=\"d857572\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"icon-box.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-icon-box-wrapper\">\n\n\t\t\t\n\t\t\t\t\t\t<div class=\"elementor-icon-box-content\">\n\n\t\t\t\t\t\t\t\t\t<h3 class=\"elementor-icon-box-title\">\n\t\t\t\t\t\t<span  >\n\t\t\t\t\t\t\tSubmerged Toe Erosion Detection\t\t\t\t\t\t<\/span>\n\t\t\t\t\t<\/h3>\n\t\t\t\t\n\t\t\t\t\t\t\t\t\t<p class=\"elementor-icon-box-description\">\n\t\t\t\t\t\tIdentifying undercutting and toe erosion below the waterline that a land-only or water-only survey would miss entirely.\t\t\t\t\t<\/p>\n\t\t\t\t\n\t\t\t<\/div>\n\t\t\t\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-68d559c e-con-full e-flex e-con e-child\" data-id=\"68d559c\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;gradient&quot;}\">\n\t\t\t\t<div class=\"elementor-element elementor-element-9f80709 elementor-widget__width-auto elementor-widget elementor-widget-heading\" data-id=\"9f80709\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">05<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-11dadbd elementor-widget elementor-widget-icon-box\" data-id=\"11dadbd\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"icon-box.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-icon-box-wrapper\">\n\n\t\t\t\n\t\t\t\t\t\t<div class=\"elementor-icon-box-content\">\n\n\t\t\t\t\t\t\t\t\t<h3 class=\"elementor-icon-box-title\">\n\t\t\t\t\t\t<span  >\n\t\t\t\t\t\t\tRegulatory &amp; Infrastructure Support\t\t\t\t\t\t<\/span>\n\t\t\t\t\t<\/h3>\n\t\t\t\t\n\t\t\t\t\t\t\t\t\t<p class=\"elementor-icon-box-description\">\n\t\t\t\t\t\tSupporting data for regulatory reporting, infrastructure risk assessment (roads, pipelines, utility crossings near banks), and restoration or armouring project design.\t\t\t\t\t<\/p>\n\t\t\t\t\n\t\t\t<\/div>\n\t\t\t\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-3d63d44 e-flex e-con-boxed e-con e-parent\" data-id=\"3d63d44\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-e01d023 elementor-widget elementor-widget-heading\" data-id=\"e01d023\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Why <span style=\"color: #FFB601\"> Volatus\n<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-457e5fa elementor-hidden-desktop elementor-hidden-tablet elementor-hidden-mobile elementor-widget elementor-widget-html\" data-id=\"457e5fa\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<style>\r\n\/* Expanded to fill the ENTIRE container *\/\r\n.vts-gravity-module {\r\n  position: absolute;\r\n  top: 0; \r\n  left: 0; \r\n  width: 100%; \r\n  height: 100%; \/* Changed from 50% *\/\r\n  min-height: 250px; \r\n  z-index: 0; \r\n  pointer-events: none; \r\n  background: transparent; \r\n  overflow: hidden; \r\n  font-family: 'Courier New', monospace; \r\n  user-select: none;\r\n}\r\n\r\n.vts-gravity-module canvas {\r\n  width: 100% !important; height: 100% !important; display: block;\r\n}\r\n<\/style>\r\n\r\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/three.js\/r128\/three.min.js\"><\/script>\r\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/simplex-noise\/2.4.0\/simplex-noise.min.js\"><\/script>\r\n\r\n<div class=\"vts-gravity-module\"><\/div>\r\n\r\n<script>\r\n\/\/ ==========================================\r\n\/\/ EASY CUSTOMIZATION OPTIONS\r\n\/\/ ==========================================\r\nconst VTS_CONFIG = {\r\n  particleColor: 0xFFB601, \/\/ Lighter yellow (Hex format: 0xRRGGBB)\r\n  particleOpacity: 0.3,    \/\/ Lowered opacity (0.0 is invisible, 1.0 is solid)\r\n  particleSize: 3,         \/\/ Size of the individual dots\r\n  particleCount: 2000,     \/\/ Total number of dots in the scene\r\n  flowSpeed: 0.4,          \/\/ How fast the particles flow horizontally\r\n  waveSpeed: 0.002         \/\/ How fast the 3D waves ripple\r\n};\r\n\r\n(function(){\r\n  let bootAttempts = 0;\r\n  \r\n  function bootAllModules(){\r\n    if(bootAttempts > 50) return;\r\n    bootAttempts++;\r\n\r\n    \/\/ Wait for libraries\r\n    if(!window.THREE || !window.SimplexNoise) {\r\n        setTimeout(bootAllModules, 100);\r\n        return;\r\n    }\r\n\r\n    \/\/ Find ALL wrappers on the page that haven't been initialized yet\r\n    const wrappers = document.querySelectorAll('.vts-gravity-module:not(.vts-active)');\r\n    \r\n    wrappers.forEach(wrapper => {\r\n        wrapper.classList.add('vts-active');\r\n\r\n        \/\/ ==========================================\r\n        \/\/ ELEMENTOR DOM RELOCATION FIX \r\n        \/\/ ==========================================\r\n        const parentContainer = wrapper.closest('.e-con, .e-container, .elementor-section');\r\n        if(parentContainer && wrapper.parentElement !== parentContainer) {\r\n            parentContainer.style.position = 'relative';\r\n            parentContainer.style.overflow = 'hidden';\r\n            parentContainer.insertBefore(wrapper, parentContainer.firstChild); \r\n        }\r\n\r\n        let W = wrapper.clientWidth;\r\n        let H = wrapper.clientHeight;\r\n        if (H < 100) H = 250;\r\n\r\n        \/\/ ==========================================\r\n        \/\/ ISOLATED 3D SCENE SETUP\r\n        \/\/ ==========================================\r\n        const scene = new THREE.Scene(); \r\n        const camera = new THREE.PerspectiveCamera(45, W\/H, 1, 2000); \r\n        \r\n        \/\/ Leveled the camera\r\n        camera.position.set(0, 10, 200); \r\n        camera.lookAt(0, 0, 0); \/\/ Adjusted lookAt to center\r\n\r\n        const renderer = new THREE.WebGLRenderer({alpha: true, antialias: true}); \r\n        renderer.setSize(W, H); \r\n        renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));\r\n        wrapper.appendChild(renderer.domElement);\r\n        \r\n        \/\/ ==========================================\r\n        \/\/ PARTICLE SYSTEM\r\n        \/\/ ==========================================\r\n        const particleCount = VTS_CONFIG.particleCount;\r\n        const geo = new THREE.BufferGeometry();\r\n        const posArray = new Float32Array(particleCount * 3);\r\n        const initialY = new Float32Array(particleCount);\r\n\r\n        for(let i = 0; i < particleCount; i++) {\r\n            posArray[i * 3] = (Math.random() - 0.5) * 1400; \/\/ X spread    \r\n            \/\/ Spreads particles fully across the vertical space\r\n            posArray[i * 3 + 1] = (Math.random() - 0.5) * 600;   \r\n            posArray[i * 3 + 2] = (Math.random() - 0.5) * 800; \/\/ Z spread \r\n            initialY[i] = posArray[i * 3 + 1];\r\n        }\r\n        \r\n        geo.setAttribute('position', new THREE.BufferAttribute(posArray, 3));\r\n\r\n        const canvas = document.createElement('canvas');\r\n        canvas.width = 16; canvas.height = 16;\r\n        const context = canvas.getContext('2d');\r\n        context.beginPath(); context.arc(8, 8, 8, 0, 2 * Math.PI);\r\n        context.fillStyle = '#ffffff'; context.fill();\r\n        const circleTexture = new THREE.CanvasTexture(canvas);\r\n\r\n        const mat = new THREE.PointsMaterial({ \r\n            color: VTS_CONFIG.particleColor, \r\n            size: VTS_CONFIG.particleSize, \r\n            map: circleTexture, \r\n            transparent: true, \r\n            opacity: VTS_CONFIG.particleOpacity, \r\n            alphaTest: 0.1, \r\n            sizeAttenuation: true \r\n        });\r\n        \r\n        const particles = new THREE.Points(geo, mat); \r\n        scene.add(particles);\r\n\r\n        const simplex = new SimplexNoise();\r\n        let localTime = Math.random() * 100; \r\n        \r\n        \/\/ ==========================================\r\n        \/\/ LOCAL ANIMATION LOOP\r\n        \/\/ ==========================================\r\n        function animateGrav() {\r\n            requestAnimationFrame(animateGrav);\r\n            localTime += VTS_CONFIG.waveSpeed; \r\n\r\n            const pos = geo.attributes.position.array;\r\n            \r\n            for(let i = 0; i < particleCount; i++) {\r\n                let index = i * 3;\r\n                pos[index] -= VTS_CONFIG.flowSpeed; \r\n                \r\n                if (pos[index] < -700) { pos[index] = 700; }\r\n\r\n                const x = pos[index], z = pos[index + 2];\r\n                const noiseVal = simplex.noise3D(x * 0.004, z * 0.004, localTime) * 25;\r\n                const dist = Math.sqrt(x*x + z*z);\r\n                const well = dist < 150 ? -30 * Math.cos(dist*Math.PI\/300) : 0;\r\n                \r\n                const slope = x * 0.06; \r\n                \r\n                pos[index + 1] = initialY[i] + noiseVal + well + slope;\r\n            }\r\n            \r\n            geo.attributes.position.needsUpdate = true;\r\n            renderer.render(scene, camera);\r\n        }\r\n        \r\n        animateGrav();\r\n\r\n        \/\/ ==========================================\r\n        \/\/ ISOLATED RESIZE OBSERVER\r\n        \/\/ ==========================================\r\n        let resizeTimer;\r\n        if(window.ResizeObserver) {\r\n            new ResizeObserver(()=>{\r\n              clearTimeout(resizeTimer);\r\n              resizeTimer = setTimeout(() => {\r\n                  if(!wrapper) return;\r\n                  const newW = wrapper.clientWidth;\r\n                  let newH = wrapper.clientHeight;\r\n                  if (newH < 100) newH = 250;\r\n                  \r\n                  if(newW > 0 && newH > 0 && (newW !== W || newH !== H)){\r\n                      W = newW; H = newH;\r\n                      renderer.setSize(W, H);\r\n                      camera.aspect = W \/ H;\r\n                      camera.updateProjectionMatrix();\r\n                  }\r\n              }, 200);\r\n            }).observe(parentContainer || wrapper);\r\n        }\r\n    });\r\n  }\r\n  \r\n  if(document.readyState==='complete'){ bootAllModules(); } \r\n  else { window.addEventListener('load', bootAllModules); }\r\n  document.addEventListener('DOMContentLoaded', bootAllModules);\r\n})();\r\n<\/script>\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-089bf89 e-con-full e-flex e-con e-child\" data-id=\"089bf89\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-effad84 e-con-full e-flex e-con e-child\" data-id=\"effad84\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-b779c32 e-con-full glass-card  e-flex e-con e-child\" data-id=\"b779c32\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-af7eff4 elementor-widget elementor-widget-heading\" data-id=\"af7eff4\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">01<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-8127223 elementor-widget elementor-widget-icon-box\" data-id=\"8127223\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"icon-box.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-icon-box-wrapper\">\n\n\t\t\t\n\t\t\t\t\t\t<div class=\"elementor-icon-box-content\">\n\n\t\t\t\t\t\t\t\t\t<h3 class=\"elementor-icon-box-title\">\n\t\t\t\t\t\t<span  >\n\t\t\t\t\t\t\tNew capability, proven experience:\t\t\t\t\t\t<\/span>\n\t\t\t\t\t<\/h3>\n\t\t\t\t\n\t\t\t\t\t\t\t\t\t<p class=\"elementor-icon-box-description\">\n\t\t\t\t\t\tour team has delivered topographic and\nbathymetric lidar on tidal rivers, with the operational know-how for precise low-tide\nand pre-freshet timing\t\t\t\t\t<\/p>\n\t\t\t\t\n\t\t\t<\/div>\n\t\t\t\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-2db4b66 e-con-full e-flex e-con e-child\" data-id=\"2db4b66\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-c673f24 e-con-full glass-card  e-flex e-con e-child\" data-id=\"c673f24\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-ec8604e elementor-widget elementor-widget-heading\" data-id=\"ec8604e\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">02<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-46972a9 elementor-widget elementor-widget-icon-box\" data-id=\"46972a9\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"icon-box.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-icon-box-wrapper\">\n\n\t\t\t\n\t\t\t\t\t\t<div class=\"elementor-icon-box-content\">\n\n\t\t\t\t\t\t\t\t\t<h3 class=\"elementor-icon-box-title\">\n\t\t\t\t\t\t<span  >\n\t\t\t\t\t\t\tRare UAV-Based Capability\t\t\t\t\t\t<\/span>\n\t\t\t\t\t<\/h3>\n\t\t\t\t\n\t\t\t\t\t\t\t\t\t<p class=\"elementor-icon-box-description\">\n\t\t\t\t\t\tRare in the UAV space: most topo-bathy lidar is still crewed-aircraft only; the Navigator brings that integrated capability to drone-based surveying.\t\t\t\t\t<\/p>\n\t\t\t\t\n\t\t\t<\/div>\n\t\t\t\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-f6ec880 e-con-full glass-card  e-flex e-con e-child\" data-id=\"f6ec880\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-83d16d3 elementor-widget elementor-widget-heading\" data-id=\"83d16d3\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">03<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-8ba6636 elementor-widget elementor-widget-icon-box\" data-id=\"8ba6636\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"icon-box.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-icon-box-wrapper\">\n\n\t\t\t\n\t\t\t\t\t\t<div class=\"elementor-icon-box-content\">\n\n\t\t\t\t\t\t\t\t\t<h3 class=\"elementor-icon-box-title\">\n\t\t\t\t\t\t<span  >\n\t\t\t\t\t\t\tAgile Drone Deployment\t\t\t\t\t\t<\/span>\n\t\t\t\t\t<\/h3>\n\t\t\t\t\n\t\t\t\t\t\t\t\t\t<p class=\"elementor-icon-box-description\">\n\t\t\t\t\t\tDrone-based capture: agile, targeted deployment for shallow, clear-water sites without the cost and lead time of a crewed aircraft or boat-based survey.\t\t\t\t\t<\/p>\n\t\t\t\t\n\t\t\t<\/div>\n\t\t\t\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-9d3e60c e-con-full e-flex e-con e-child\" data-id=\"9d3e60c\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-9faacb7 e-con-full glass-card  e-flex e-con e-child\" data-id=\"9faacb7\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-e0b0f09 elementor-widget elementor-widget-heading\" data-id=\"e0b0f09\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">04<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-02a2946 elementor-widget elementor-widget-icon-box\" data-id=\"02a2946\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"icon-box.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-icon-box-wrapper\">\n\n\t\t\t\n\t\t\t\t\t\t<div class=\"elementor-icon-box-content\">\n\n\t\t\t\t\t\t\t\t\t<h3 class=\"elementor-icon-box-title\">\n\t\t\t\t\t\t<span  >\n\t\t\t\t\t\t\tSingle Integrated Deliverable\t\t\t\t\t\t<\/span>\n\t\t\t\t\t<\/h3>\n\t\t\t\t\n\t\t\t\t\t\t\t\t\t<p class=\"elementor-icon-box-description\">\n\t\t\t\t\t\tOne deliverable, not two: a single integrated point cloud instead of stitching together separate topo and bathy datasets from different vendors.\t\t\t\t\t<\/p>\n\t\t\t\t\n\t\t\t<\/div>\n\t\t\t\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-33d5118 e-con-full glass-card  e-flex e-con e-child\" data-id=\"33d5118\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-19d993c elementor-widget elementor-widget-heading\" data-id=\"19d993c\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">05<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-2b54158 elementor-widget elementor-widget-icon-box\" data-id=\"2b54158\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"icon-box.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-icon-box-wrapper\">\n\n\t\t\t\n\t\t\t\t\t\t<div class=\"elementor-icon-box-content\">\n\n\t\t\t\t\t\t\t\t\t<h3 class=\"elementor-icon-box-title\">\n\t\t\t\t\t\t<span  >\n\t\t\t\t\t\t\tCanada-Wide Operational Reach\t\t\t\t\t\t<\/span>\n\t\t\t\t\t<\/h3>\n\t\t\t\t\n\t\t\t\t\t\t\t\t\t<p class=\"elementor-icon-box-description\">\n\t\t\t\t\t\tCanada-wide operational footprint with the regulatory and BVLOS experience to fly complex sites efficiently.\t\t\t\t\t<\/p>\n\t\t\t\t\n\t\t\t<\/div>\n\t\t\t\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-a5dec0d e-flex e-con-boxed e-con e-parent\" data-id=\"a5dec0d\" data-element_type=\"container\" data-e-type=\"container\" id=\"particle-section\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-97d57c0 elementor-widget__width-initial elementor-widget elementor-widget-heading\" data-id=\"97d57c0\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Ready to see below the surface?\n<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-48c8148 elementor-widget__width-initial elementor-widget-mobile__width-inherit elementor-widget elementor-widget-text-editor\" data-id=\"48c8148\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p class=\"cta-desc\">Talk to our team about your site&#8217;s water clarity, depth range, and timing window. We&#8217;ll tell you straight away whether topo-bathy lidar is the right fit.<\/p\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-b0cb3a1 elementor-widget elementor-widget-button\" data-id=\"b0cb3a1\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"button.default\">\n\t\t\t\t\t\t\t\t\t\t<a class=\"elementor-button elementor-button-link elementor-size-sm\" href=\"#elementor-action%3Aaction%3Dpopup%3Aopen%26settings%3DeyJpZCI6IjQ5NjIiLCJ0b2dnbGUiOmZhbHNlfQ%3D%3D\">\n\t\t\t\t\t\t<span class=\"elementor-button-content-wrapper\">\n\t\t\t\t\t\t\t\t\t<span class=\"elementor-button-text\">Talk to an expert<\/span>\n\t\t\t\t\t<\/span>\n\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Home \/ Services \/ Technical Capabilities \/ Topo-Bathy Lidar Services Topo-Bathy Lidar Surveys See Through the Water Line. Most lidar Stops at the water&#8217;s edge. Topo-bathy lidar doesn&#8217;t. Using a green-wavelength laser purpose-built to penetrate clear, shallow water, Volatus captures a continuous elevation model from dry land straight through the water colurnn to the bottom, [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":0,"parent":36391,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_header_footer","meta":{"footnotes":"","_links_to":"","_links_to_target":""},"class_list":["post-36191","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/volatusaerospace.com\/fr-ca\/wp-json\/wp\/v2\/pages\/36191","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/volatusaerospace.com\/fr-ca\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/volatusaerospace.com\/fr-ca\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/volatusaerospace.com\/fr-ca\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/volatusaerospace.com\/fr-ca\/wp-json\/wp\/v2\/comments?post=36191"}],"version-history":[{"count":108,"href":"https:\/\/volatusaerospace.com\/fr-ca\/wp-json\/wp\/v2\/pages\/36191\/revisions"}],"predecessor-version":[{"id":36646,"href":"https:\/\/volatusaerospace.com\/fr-ca\/wp-json\/wp\/v2\/pages\/36191\/revisions\/36646"}],"up":[{"embeddable":true,"href":"https:\/\/volatusaerospace.com\/fr-ca\/wp-json\/wp\/v2\/pages\/36391"}],"wp:attachment":[{"href":"https:\/\/volatusaerospace.com\/fr-ca\/wp-json\/wp\/v2\/media?parent=36191"}],"curies":[{"name":"Bien jou\u00e9","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}