PageSourceSearch

https://www.flyingshapes.com/portfolio/

html flyingshapes.com collected 2026-10-04 01:16:50 UTC 153,550 bytes, 2,679 lines download raw bytes

1<!DOCTYPE html>
2<html lang="en-GB">
3<head>
4	<meta charset="UTF-8">
5	<meta name="viewport" content="width=device-width, initial-scale=1">
6	<link rel="icon" href="https://www.flyingshapes.com/wp-content/themes/flyingshapes/assets/images/favicon.png" type="image/png">
7	
7<script type="text/javascript" data-cookieconsent="ignore">
8	window.dataLayer = window.dataLayer || [];
9
10	function gtag() {
11		dataLayer.push(arguments);
12	}
13
14	gtag("consent", "default", {
15		ad_personalization: "denied",
16		ad_storage: "denied",
17		ad_user_data: "denied",
18		analytics_storage: "denied",
19		functionality_storage: "denied",
20		personalization_storage: "denied",
21		security_storage: "granted",
22		wait_for_update: 500,
23	});
24	gtag("set", "ads_data_redaction", true);
25	</script>
vendor: 1 bytes, line 25
25
26<script type="text/javascript" data-cookieconsent="ignore">
27		(function (w, d, s, l, i) {
28		w[l] = w[l] || [];
29		w[l].push({'gtm.start': new Date().getTime(), event: 'gtm.js'});
30		var f = d.getElementsByTagName(s)[0], j = d.createElement(s), dl = l !== 'dataLayer' ? '&l=' + l : '';
31		j.async = true;
32		j.src = 'https://www.googletagmanager.com/gtm.js?id=' + i + dl;
33		f.parentNode.insertBefore(j, f);
34	})(
35		window,
36		document,
37		'script',
38		'dataLayer',
39		'GTM-T3BH7W7'
40	);
41</script>
vendor: 1 bytes, line 41
41
42<script type="text/javascript"
43		id="Cookiebot"
44		src="https://consent.cookiebot.com/uc.js"
45		data-implementation="wp"
46		data-cbid="b06ede66-e802-4a55-93d8-86b7bbd26af9"
47							data-blockingmode="auto"
48	></script>
48
49<meta name='robots' content='index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1' />
50
51	<!-- This site is optimized with the Yoast SEO plugin v28.6 - https://yoast.com/product/yoast-seo-wordpress/ -->
52	<title>portfolio - Flyingshapes</title>
53	<link rel="canonical" href="https://www.flyingshapes.com/portfolio/" />
54	<meta property="og:locale" content="en_GB" />
55	<meta property="og:type" content="article" />
56	<meta property="og:title" content="portfolio - Flyingshapes" />
57	<meta property="og:url" content="https://www.flyingshapes.com/portfolio/" />
58	<meta property="og:site_name" content="Flyingshapes" />
59	<meta property="article:modified_time" content="2026-09-09T07:21:33+00:00" />
60	<meta name="twitter:card" content="summary_large_image" />
61	
61<script type="application/ld+json" class="yoast-schema-graph">{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.flyingshapes.com\/portfolio\/","url":"https:\/\/www.flyingshapes.com\/portfolio\/","name":"portfolio - Flyingshapes","isPartOf":{"@id":"https:\/\/www.flyingshapes.com\/#website"},"datePublished":"2026-09-04T14:56:03+00:00","dateModified":"2026-09-09T07:21:33+00:00","breadcrumb":{"@id":"https:\/\/www.flyingshapes.com\/portfolio\/#breadcrumb"},"inLanguage":"en-GB","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.flyingshapes.com\/portfolio\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.flyingshapes.com\/portfolio\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.flyingshapes.com\/"},{"@type":"ListItem","position":2,"name":"portfolio"}]},{"@type":"WebSite","@id":"https:\/\/www.flyingshapes.com\/#website","url":"https:\/\/www.flyingshapes.com\/","name":"Flyingshapes","description":"Instant Interactive 3D Ideation","publisher":{"@id":"https:\/\/www.flyingshapes.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.flyingshapes.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-GB"},{"@type":"Organization","@id":"https:\/\/www.flyingshapes.com\/#organization","name":"Flyingshapes GmbH","url":"https:\/\/www.flyingshapes.com\/","logo":{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/www.flyingshapes.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.flyingshapes.com\/wp-content\/uploads\/2026\/09\/Icon-2026-black-on-white-1600.png","contentUrl":"https:\/\/www.flyingshapes.com\/wp-content\/uploads\/2026\/09\/Icon-2026-black-on-white-1600.png","width":1600,"height":1600,"caption":"Flyingshapes GmbH"},"image":{"@id":"https:\/\/www.flyingshapes.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/de.linkedin.com\/company\/flyingshapes"]}]}</script>
61
62	<!-- / Yoast SEO plugin. -->
63
64
65<link rel='dns-prefetch' href='//www.googletagmanager.com' />
66<link rel="alternate" title="oEmbed (JSON)" type="application/json+oembed" href="https://www.flyingshapes.com/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fwww.flyingshapes.com%2Fportfolio%2F" />
67<link rel="alternate" title="oEmbed (XML)" type="text/xml+oembed" href="https://www.flyingshapes.com/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fwww.flyingshapes.com%2Fportfolio%2F&#038;format=xml" />
68<style id="wp-img-auto-sizes-contain-inline-css">
69img:is([sizes=auto i],[sizes^="auto," i]){contain-intrinsic-size:3000px 1500px}
70/*# sourceURL=wp-img-auto-sizes-contain-inline-css */
71</style>
72<style id="wp-emoji-styles-inline-css">
73
74	img.wp-smiley, img.emoji {
75		display: inline !important;
76		border: none !important;
77		box-shadow: none !important;
78		height: 1em !important;
79		width: 1em !important;
80		margin: 0 0.07em !important;
81		vertical-align: -0.1em !important;
82		background: none !important;
83		padding: 0 !important;
84	}
85/*# sourceURL=wp-emoji-styles-inline-css */
86</style>
87<style id="wp-block-library-inline-css">
88:root{--wp-block-synced-color:#7a00df;--wp-block-synced-color--rgb:122,0,223;--wp-bound-block-color:var(--wp-block-synced-color);--wp-editor-canvas-background:#ddd;--wp-admin-theme-color:#007cba;--wp-admin-theme-color--rgb:0,124,186;--wp-admin-theme-color-darker-10:#006ba1;--wp-admin-theme-color-darker-10--rgb:0,107,160.5;--wp-admin-theme-color-darker-20:#005a87;--wp-admin-theme-color-darker-20--rgb:0,90,135;--wp-admin-border-width-focus:2px}@media (min-resolution:192dpi){:root{--wp-admin-border-width-focus:1.5px}}.wp-element-button{cursor:pointer}:root .has-very-light-gray-background-color{background-color:#eee}:root .has-very-dark-gray-background-color{background-color:#313131}:root .has-very-light-gray-color{color:#eee}:root .has-very-dark-gray-color{color:#313131}:root .has-vivid-green-cyan-to-vivid-cyan-blue-gradient-background{background:linear-gradient(135deg,#00d084,#0693e3)}:root .has-purple-crush-gradient-background{background:linear-gradient(135deg,#34e2e4,#4721fb 50%,#ab1dfe)}:root .has-hazy-dawn-gradient-background{background:linear-gradient(135deg,#faaca8,#dad0ec)}:root .has-subdued-olive-gradient-background{background:linear-gradient(135deg,#fafae1,#67a671)}:root .has-atomic-cream-gradient-background{background:linear-gradient(135deg,#fdd79a,#004a59)}:root .has-nightshade-gradient-background{background:linear-gradient(135deg,#330968,#31cdcf)}:root .has-midnight-gradient-background{background:linear-gradient(135deg,#020381,#2874fc)}:root{--wp--preset--font-size--normal:16px;
88--wp--preset--font-size--huge:42px}.has-regular-font-size{font-size:1em}.has-larger-font-size{font-size:2.625em}.has-normal-font-size{font-size:var(--wp--preset--font-size--normal)}.has-huge-font-size{font-size:var(--wp--preset--font-size--huge)}:root .has-text-align-center{text-align:center}:root .has-text-align-left{text-align:left}:root .has-text-align-right{text-align:right}.has-fit-text{white-space:nowrap!important}#end-resizable-editor-section{display:none}.aligncenter{clear:both}.items-justified-left{justify-content:flex-start}.items-justified-center{justify-content:center}.items-justified-right{justify-content:flex-end}.items-justified-space-between{justify-content:space-between}.screen-reader-text{word-wrap:normal!important;border:0;clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;word-break:normal!important}.screen-reader-text:focus{background-color:#ddd;clip-path:none;color:#444;display:block;font-size:1em;height:auto;left:5px;line-height:normal;padding:15px 23px 14px;text-decoration:none;top:5px;width:auto;z-index:100000}html :where(.has-border-color){border-style:solid}html :where([style^=border-color],[style*=";border-color"],[style*="; border-color"]){border-style:solid}html :where([style^=border-top-color],[style*=";border-top-color"],[style*="; border-top-color"]){border-top-style:solid}html :where([style^=border-right-color],[style*=";border-right-color"],[style*="; border-right-color"]){border-right-style:solid}html :where([style^=border-bottom-color],[style*=";border-bottom-color"],[style*="; border-bottom-color"]){border-bottom-style:solid}html :where([style^=border-left-color],[style*=";border-left-color"],[style*="; border-left-color"]){border-left-style:solid}html :where([style^=border-width],[style*=";border-width"],[style*="; border-width"]){border-style:solid}html :where([style^=border-top-width],[style*=";border-top-width"],[style*="; border-top-width"]){border-top-style:solid}html :where([style^=border-right-width],[style*=";border-right-width"],[style*="; border-right-width"]){border-right-style:solid}html :where([style^=border-bottom-width],[style*=";border-bottom-width"],[style*="; border-bottom-width"]){border-bottom-style:solid}html :where([style^=border-left-width],[style*=";border-left-width"],[style*="; border-left-width"]){border-left-style:solid}html :where(img[class*=wp-image-]){height:auto;max-width:100%}:where(figure){margin:0 0 1em}html :where(.is-position-sticky){--wp-admin--admin-bar--position-offset:var(--wp-admin--admin-bar--height,0px)}@media screen and (max-width:600px){html :where(.is-position-sticky){--wp-admin--admin-bar--position-offset:0px}}
89
90/*# sourceURL=/wp-includes/css/dist/block-library/common.min.css */
91</style>
92
93<style id="global-styles-inline-css">
94:root{--wp--preset--aspect-ratio--square: 1;--wp--preset--aspect-ratio--4-3: 4/3;--wp--preset--aspect-ratio--3-4: 3/4;--wp--preset--aspect-ratio--3-2: 3/2;--wp--preset--aspect-ratio--2-3: 2/3;--wp--preset--aspect-ratio--16-9: 16/9;--wp--preset--aspect-ratio--9-16: 9/16;--wp--preset--color--black: #000000;--wp--preset--color--cyan-bluish-gray: #abb8c3;--wp--preset--color--white: #ffffff;--wp--preset--color--pale-pink: #f78da7;--wp--preset--color--vivid-red: #cf2e2e;--wp--preset--color--luminous-vivid-orange: #ff6900;--wp--preset--color--luminous-vivid-amber: #fcb900;--wp--preset--color--light-green-cyan: #7bdcb5;--wp--preset--color--vivid-green-cyan: #00d084;--wp--preset--color--pale-cyan-blue: #8ed1fc;--wp--preset--color--vivid-cyan-blue: #0693e3;--wp--preset--color--vivid-purple: #9b51e0;--wp--preset--color--ink: #0a0a0a;--wp--preset--color--near-black: #141414;--wp--preset--color--charcoal: #1b1b1b;--wp--preset--color--muted: rgba(255,255,255,0.6);--wp--preset--color--soft: rgba(255,255,255,0.85);--wp--preset--color--paper: #ffffff;--wp--preset--color--accent: #ffffff;--wp--preset--color--accent-hover: rgb(56, 56, 56);--wp--preset--color--line: rgba(255,255,255,0.12);--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple: linear-gradient(135deg,rgb(6,147,227) 0%,rgb(155,81,224) 100%);--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan: linear-gradient(135deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%);--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange: linear-gradient(135deg,rgb(252,185,
940) 0%,rgb(255,105,0) 100%);--wp--preset--gradient--luminous-vivid-orange-to-vivid-red: linear-gradient(135deg,rgb(255,105,0) 0%,rgb(207,46,46) 100%);--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray: linear-gradient(135deg,rgb(238,238,238) 0%,rgb(169,184,195) 100%);--wp--preset--gradient--cool-to-warm-spectrum: linear-gradient(135deg,rgb(74,234,220) 0%,rgb(151,120,209) 20%,rgb(207,42,186) 40%,rgb(238,44,130) 60%,rgb(251,105,98) 80%,rgb(254,248,76) 100%);--wp--preset--gradient--blush-light-purple: linear-gradient(135deg,rgb(255,206,236) 0%,rgb(152,150,240) 100%);--wp--preset--gradient--blush-bordeaux: linear-gradient(135deg,rgb(254,205,165) 0%,rgb(254,45,45) 50%,rgb(107,0,62) 100%);--wp--preset--gradient--luminous-dusk: linear-gradient(135deg,rgb(255,203,112) 0%,rgb(199,81,192) 50%,rgb(65,88,208) 100%);--wp--preset--gradient--pale-ocean: linear-gradient(135deg,rgb(255,245,203) 0%,rgb(182,227,212) 50%,rgb(51,167,181) 100%);--wp--preset--gradient--electric-grass: linear-gradient(135deg,rgb(202,248,128) 0%,rgb(113,206,126) 100%);--wp--preset--gradient--midnight: linear-gradient(135deg,rgb(2,3,129) 0%,rgb(40,116,252) 100%);--wp--preset--font-size--small: 0.875rem;--wp--preset--font-size--medium: clamp(0.875rem, 0.875rem + ((1vw - 0.2rem) * 0.455), 1.125rem);--wp--preset--font-size--large: clamp(0.984rem, 0.984rem + ((1vw - 0.2rem) * 0.938), 1.5rem);--wp--preset--font-size--x-large: clamp(2rem, 4vw, 3rem);--wp--preset--font-size--xx-large: clamp(2.75rem, 7vw, 5rem);--wp--preset--font-family--roboto: Roboto, sans-serif;--wp--preset--spacing--20: 0.44rem;--wp--preset--spacing--30: 0.67rem;--wp--preset--spacing--40: 1rem;--wp--preset--spacing--50: 1.5rem;--wp--preset--spacing--60: 2.25rem;--wp--preset--spacing--70: 3.38rem;--wp--preset--spacing--80: 5.06rem;--wp--preset--shadow--natural: 6px 6px 9px rgba(0, 0, 0, 0.2);--wp--preset--shadow--deep: 12px 12px 50px rgba(0, 0, 0, 0.4);--wp--preset--shadow--sharp: 6px 6px 0px rgba(0, 0, 0, 0.2);--wp--preset--shadow--outlined: 6px 6px 0px -3px rgb(255, 255, 255), 6px 6px rgb(0, 0, 0);--wp--preset--shadow--crisp: 6px 6px 0px rgb(0, 0, 0);}.wp-block-button{--wp--preset--dimension--25: 25%;--wp--preset--dimension--50: 50%;--wp--preset--dimension--75: 75%;--wp--preset--dimension--100: 100%;}:root { --wp--style--global--content-size: 720px;--wp--style--global--wide-size: 1200px; }:where(body) { margin: 0; }.wp-site-blocks { padding-top: var(--wp--style--root--padding-top); padding-bottom: var(--wp--style--root--padding-bottom); }.has-global-padding { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }.has-global-padding > .alignfull { margin-right: calc(var(--wp--style--root--padding-right) * -1); margin-left: calc(var(--wp--style--root--padding-left) * -1); }.has-global-padding :where(:not(.alignfull.is-layout-flow) > .has-global-padding:not(.wp-block-block, .alignfull)) { padding-right: 0; padding-left: 0; }.has-global-padding :where(:not(.alignfull.is-layout-flow) > .has-global-padding:not(.wp-block-block, .alignfull)) > .alignfull { margin-left: 0; margin-right: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: 24px; margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: 24px; }:root :where(.is-layout-flow) > :first-child{margin-block-start: 0;}:root :where(.is-layout-flow) > :last-child{margin-block-end: 0;}:root :where(.is-layout-flow) > *{margin-block-start: 24px;margin-block-end: 0;}:root :where(.is-layout-constrained) > :first-child{margin-block-start: 0;}:root :where(.is-layout-constrained) > :last-child{margin-block-end: 0;}:root :where(.is-layout-constrained) > *{margin-block-start: 24px;margin-block-end: 0;}:root :where(.is-layout-flex){gap: 24px;}:root :where(.is-layout-grid){gap: 24px;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained >
94 :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width: var(--wp--style--global--content-size);margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignwide{max-width: var(--wp--style--global--wide-size);}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}body{background-color: var(--wp--preset--color--ink);color: var(--wp--preset--color--paper);font-family: var(--wp--preset--font-family--roboto);font-size: var(--wp--preset--font-size--medium);font-weight: 400;line-height: 1.55;--wp--style--root--padding-top: 0px;--wp--style--root--padding-right: 0px;--wp--style--root--padding-bottom: 0px;--wp--style--root--padding-left: 0px;}a:where(:not(.wp-element-button)){color: var(--wp--preset--color--paper);}:root :where(a:where(:not(.wp-element-button)):hover){color: var(--wp--preset--color--accent);}h1, h2, h3, h4, h5, h6{color: var(--wp--preset--color--paper);font-family: var(--wp--preset--font-family--roboto);font-weight: 700;line-height: 1.1;}h1{font-size: var(--wp--preset--font-size--xx-large);}h2{font-size: var(--wp--preset--font-size--x-large);}h3{font-size: var(--wp--preset--font-size--large);}:root :where(.wp-element-button, .wp-block-button__link){background-color: var(--wp--preset--color--ink);border-radius: 980px;border-width: 0;color: var(--wp--preset--color--paper);font-family: var(--wp--preset--font-family--roboto);font-size: clamp(0.875rem, 0.875rem + ((1vw - 0.2rem) * 0.227), 1rem);font-style: inherit;font-weight: 400;letter-spacing: inherit;line-height: inherit;padding-top: 0.75rem;padding-right: 1.375rem;padding-bottom: 0.75rem;padding-left: 1.375rem;text-decoration: none;text-transform: inherit;}:root :where(.wp-element-button:hover, .wp-block-button__link:hover){background-color: var(--wp--preset--color--near-black);color: var(--wp--preset--color--paper);}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-color{color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-color{color: var(--wp--preset--color--white) !important;}.has-pale-pink-color{color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-color{color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-color{color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-color{color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-color{color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-color{color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-color{color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-color{color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-color{color: var(--wp--preset--color--vivid-purple) !important;}.has-ink-color{color: var(--wp--preset--color--ink) !important;}.has-near-black-color{color: var(--wp--preset--color--near-black) !important;}.has-charcoal-color{color: var(--wp--preset--color--charcoal) !important;}.has-muted-color{color: var(--wp--preset--color--muted) !important;}.has-soft-color{color: var(--wp--preset--color--soft) !important;}.has-paper-color{color: var(--wp--preset--color--paper) !important;}.has-accent-color{color: var(--wp--preset--color--accent) !important;}.has-accent-hover-color{color: var(--wp--preset--color--accent-hover) !important;}.has-line-color{color: var(--wp--preset--color--line) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-background-color{background-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-pale-pink-background-color{background-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-background-color{background-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-background-color{background-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-background-color{background-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-background-color{background-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-background-color{background-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-background-color{background-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-background-color{background-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-background-color{background-color: var(--wp--preset--color--vivid-purple) !important;}.has-ink-background-color{background-color: var(--wp--preset--color--ink) !important;}.has-near-black-background-color{background-color: var(--wp--preset--color--near-black) !important;}.has-charcoal-background-color{background-color: var(--wp--preset--color--charcoal) !important;}.has-muted-background-color{background-color: var(--wp--preset--color--muted) !important;}.has-soft-background-color{background-color: var(--wp--preset--color--soft) !important;}.has-paper-background-color{background-color: var(--wp--preset--color--paper) !important;}.has-accent-background-color{background-color: var(--wp--preset--color--accent) !important;}.has-accent-hover-background-color{background-color: var(--wp--preset--color--accent-hover) !important;}.has-line-background-color{background-color: var(--wp--preset--color--line) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-border-color{border-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-pale-pink-border-color{border-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-border-color{border-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-border-color{border-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-border-color{border-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-border-color{border-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-border-color{border-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-border-color{border-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-border-color{border-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-border-color{border-color: var(--wp--preset--color--vivid-purple) !important;}.has-ink-border-color{border-color: var(--wp--preset--color--ink) !important;}.has-near-black-border-color{border-color: var(--wp--preset--color--near-black) !important;}.has-charcoal-border-color{border-color: var(--wp--preset--color--charcoal) !important;}.has-muted-border-color{border-color: var(--wp--preset--color--muted) !important;}.has-soft-border-color{border-color: var(--wp--preset--color--soft) !important;}.has-paper-border-color{border-color: var(--wp--preset--color--paper) !important;}.has-accent-border-color{border-color: var(--wp--preset--color--accent) !important;}.has-accent-hover-border-color{border-color: var(--wp--preset--color--accent-hover) !important;}.has-line-border-color{border-color: var(--wp--preset--color--line) !important;}.has-vivid-cyan-blue-to-vivid-purple-gradient-background{background: var(--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple) !important;}.has-light-green-cyan-to-vivid-green-cyan-gradient-background{background: var(--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan) !important;}.has-luminous-vivid-amber-to-luminous-vivid-orange-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange) !important;}.has-luminous-vivid-orange-to-vivid-red-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-orange-to-vivid-red) !important;}
94.has-very-light-gray-to-cyan-bluish-gray-gradient-background{background: var(--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray) !important;}.has-cool-to-warm-spectrum-gradient-background{background: var(--wp--preset--gradient--cool-to-warm-spectrum) !important;}.has-blush-light-purple-gradient-background{background: var(--wp--preset--gradient--blush-light-purple) !important;}.has-blush-bordeaux-gradient-background{background: var(--wp--preset--gradient--blush-bordeaux) !important;}.has-luminous-dusk-gradient-background{background: var(--wp--preset--gradient--luminous-dusk) !important;}.has-pale-ocean-gradient-background{background: var(--wp--preset--gradient--pale-ocean) !important;}.has-electric-grass-gradient-background{background: var(--wp--preset--gradient--electric-grass) !important;}.has-midnight-gradient-background{background: var(--wp--preset--gradient--midnight) !important;}.has-small-font-size{font-size: var(--wp--preset--font-size--small) !important;}.has-medium-font-size{font-size: var(--wp--preset--font-size--medium) !important;}.has-large-font-size{font-size: var(--wp--preset--font-size--large) !important;}.has-x-large-font-size{font-size: var(--wp--preset--font-size--x-large) !important;}.has-xx-large-font-size{font-size: var(--wp--preset--font-size--xx-large) !important;}.has-roboto-font-family{font-family: var(--wp--preset--font-family--roboto) !important;}
95/*# sourceURL=global-styles-inline-css */
96</style>
97
98<link rel='stylesheet' id='flyingshapes-main-css' href='https://www.flyingshapes.com/wp-content/themes/flyingshapes/assets/css/main.css?ver=1790940220' media='all' />
99<link rel='stylesheet' id='flyingshapes-lightbox-css' href='https://www.flyingshapes.com/wp-content/themes/flyingshapes/assets/css/lightbox.css?ver=1789135126' media='all' />
100
101<!-- Google tag (gtag.js) snippet added by Site Kit -->
102<!-- Google Analytics snippet added by Site Kit -->
vendor: 80 bytes, lines 102-103
102
103<script id="google_gtagjs-js" src="https://www.googletagmanager.com/gtag/js?id=
103G-CLFT2P9W9L
vendor: 18 bytes, line 103
103" async></script>
104<script id="google_gtagjs-js-after">
105window.dataLayer = window.dataLayer || [];function gtag(){dataLayer.push(arguments);}
106gtag("set","linker",{"domains":["www.flyingshapes.com"]});
107gtag("js", new Date());
108gtag("set", "developer_id.dZTNiMT", true);
109gtag("config", "G-CLFT2P9W9L", {"googlesitekit_post_type":"page"});
110 window._googlesitekit = window._googlesitekit || {}; window._googlesitekit.throttledEvents = []; window._googlesitekit.gtagEvent = (name, data) => { var key = JSON.stringify( { name, data } ); if ( !! window._googlesitekit.throttledEvents[ key ] ) { return; } window._googlesitekit.throttledEvents[ key ] = true; setTimeout( () => { delete window._googlesitekit.throttledEvents[ key ]; }, 5 ); gtag( "event", name, { ...data, event_source: "site-kit" } ); }; 
111//# sourceURL=google_gtagjs-js-after
112</script>
112
113<link rel="https://api.w.org/" href="https://www.flyingshapes.com/wp-json/" /><link rel="alternate" title="JSON" type="application/json" href="https://www.flyingshapes.com/wp-json/wp/v2/pages/24" /><link rel="EditURI" type="application/rsd+xml" title="RSD" href="https://www.flyingshapes.com/xmlrpc.php?rsd" />
114<meta name="generator" content="WordPress 7.1.2" />
115<link rel='shortlink' href='https://www.flyingshapes.com/?p=24' />
116<meta name="generator" content="Site Kit by Google 1.188.0" /><style class="wp-fonts-local">
117@font-face{font-family:Roboto;font-style:normal;font-weight:400;font-display:swap;src:url('https://www.flyingshapes.com/wp-content/themes/flyingshapes/assets/fonts/roboto-latin-400-normal.woff2') format('woff2');}
118@font-face{font-family:Roboto;font-style:italic;font-weight:400;font-display:swap;src:url('https://www.flyingshapes.com/wp-content/themes/flyingshapes/assets/fonts/roboto-latin-400-italic.woff2') format('woff2');}
119@font-face{font-family:Roboto;font-style:normal;font-weight:500;font-display:swap;src:url('https://www.flyingshapes.com/wp-content/themes/flyingshapes/assets/fonts/roboto-latin-500-normal.woff2') format('woff2');}
120@font-face{font-family:Roboto;font-style:normal;font-weight:700;font-display:swap;src:url('https://www.flyingshapes.com/wp-content/themes/flyingshapes/assets/fonts/roboto-latin-700-normal.woff2') format('woff2');}
121@font-face{font-family:Roboto;font-style:italic;font-weight:700;font-display:swap;src:url('https://www.flyingshapes.com/wp-content/themes/flyingshapes/assets/fonts/roboto-latin-700-italic.woff2') format('woff2');}
122</style>
123<link rel="icon" href="https://www.flyingshapes.com/wp-content/uploads/2026/09/cropped-FS-Favicon-x256-32x32.png" sizes="32x32" />
124<link rel="icon" href="https://www.flyingshapes.com/wp-content/uploads/2026/09/cropped-FS-Favicon-x256-192x192.png" sizes="192x192" />
125<link rel="apple-touch-icon" href="https://www.flyingshapes.com/wp-content/uploads/2026/09/cropped-FS-Favicon-x256-180x180.png" />
126<meta name="msapplication-TileImage" content="https://www.flyingshapes.com/wp-content/uploads/2026/09/cropped-FS-Favicon-x256-270x270.png" />
127</head>
128<body class="wp-singular page-template-default page page-id-24 wp-embed-responsive wp-theme-flyingshapes fs-theme">
129<a class="fs-skip-link" href="#fs-main">Skip to content</a>
130
131<header class="fs-header">
132	<div class="fs-header__inner">
133		<a class="fs-brand" href="https://www.flyingshapes.com/">
134			<img class="fs-brand__wordmark" src="https://www.flyingshapes.com/wp-content/themes/flyingshapes/assets/images/logo-wordmark.png" width="281" height="16" alt="Flyingshapes" />
135		</a>
136
137		<button type="button" class="fs-nav-toggle" data-nav-toggle aria-expanded="false" aria-controls="fs-primary-nav" aria-label="Menu">
138			<span class="fs-nav-toggle__bar" aria-hidden="true"></span>
139			<span class="fs-nav-toggle__bar" aria-hidden="true"></span>
140			<span class="fs-nav-toggle__bar" aria-hidden="true"></span>
141		</button>
142
143		<nav aria-label="Primary">
144			<ul id="fs-primary-nav" class="fs-nav" data-nav>
145				<li>
146					<a href="https://www.flyingshapes.com/">Home</a>
147				</li>
148				<li>
149					<a href="https://www.flyingshapes.com/portfolio/" aria-current="page">Portfolio</a>
150				</li>
151				<li><button type="button" data-lightbox="contact">Contact</button></li>
152			</ul>
153		</nav>
154	</div>
155</header>
156<main id="fs-main" class="fs-main">
157	<article class="fs-section fs-section--tight fs-section--portfolio">
158	<div class="fs-container">
159		<h1 class="fs-visually-hidden">Portfolio</h1>
160
161		<div class="fs-portfolio-grid">
162											<div class="fs-portfolio-card">
163					<img
164						class="fs-portfolio-card__image"
165						src="https://www.flyingshapes.com/wp-content/uploads/2024/01/Periscopio-2.png"
166						alt=""
167						width="800"
168						height="400"
169						 fetchpriority="high"					/>
170					<div class="fs-portfolio-card__actions">
171												<a
172							class="fs-portfolio-card__hit fs-portfolio-card__hit--3d"
173							href="https://app.flyingshapes.com/12a47eb9-739b-40d3-879f-315712ac2284?domeEyeHeight=.6&#038;shadowPlaneOpacity=1"
174							 target="_blank" rel="noopener noreferrer"							aria-label="Open Periscopio in 3D"
175						>
176							<span class="fs-portfolio-card__icon" aria-hidden="true">
177								<svg class="fs-portfolio-card__glyph" viewBox="0 0 24 24" focusable="false">
178									<path fill="currentColor" d="M7.52 21.48C4.25 19.94 1.91 16.76 1.55 13H.05C.56 19.16 5.71 24 12 24l.66-.03-4.31-4.01-.83 1.52zM23.95 11C23.44 4.84 18.29 0 12 0l-.66.03 4.31 4.01.83-1.49C19.75 4.06 22.09 7.24 22.45 11h1.5z"/>
179									<text x="12" y="12" dy="0.35em" text-anchor="middle" fill="currentColor" font-size="7" font-weight="700" font-family="Roboto, sans-serif">3D</text>
180								</svg>
181							</span>
182						</a>
183					</div>
184				</div>
185											<div class="fs-portfolio-card fs-portfolio-card--split">
186					<img
187						class="fs-portfolio-card__image"
188						src="https://www.flyingshapes.com/wp-content/uploads/2024/01/Molsheim-Coupe.png"
189						alt=""
190						width="800"
191						height="400"
192						 fetchpriority="high"					/>
193					<div class="fs-portfolio-card__actions">
194													<button
195								type="button"
196								class="fs-portfolio-card__hit fs-portfolio-card__hit--play"
197								data-media-lightbox="https://www.flyingshapes.com/wp-content/uploads/2023/10/Molsheim_Coupe-compressed.mp4"
198								aria-label="Play video: Molsheim Coupe"
199							>
200								<span class="fs-portfolio-card__icon" aria-hidden="true">
201									<span class="fs-portfolio-card__play-glyph"></span>
202								</span>
203							</button>
204												<a
205							class="fs-portfolio-card__hit fs-portfolio-card__hit--3d"
206							href="https://app.flyingshapes.com/f2a08e5c-b42b-498d-acef-68b841247756?domeEyeHeight=.6&#038;moodBoard=false&#038;shadowPlaneOpacity=1"
207							 target="_blank" rel="noopener noreferrer"							aria-label="Open Molsheim Coupe in 3D"
208						>
209							<span class="fs-portfolio-card__icon" aria-hidden="true">
210								<svg class="fs-portfolio-card__glyph" viewBox="0 0 24 24" focusable="false">
211									<path fill="currentColor" d="M7.52 21.48C4.25 19.94 1.91 16.76 1.55 13H.05C.56 19.16 5.71 24 12 24l.66-.03-4.31-4.01-.83 1.52zM23.95 11C23.44 4.84 18.29 0 12 0l-.66.03 4.31 4.01.83-1.49C19.75 4.06 22.09 7.24 22.45 11h1.5z"/>
212									<text x="12" y="12" dy="0.35em" text-anchor="middle" fill="currentColor" font-size="7" font-weight="700" font-family="Roboto, sans-serif">3D</text>
213								</svg>
214							</span>
215						</a>
216					</div>
217				</div>
218											<div class="fs-portfolio-card fs-portfolio-card--split">
219					<img
220						class="fs-portfolio-card__image"
221						src="https://www.flyingshapes.com/wp-content/uploads/2024/01/Experimental-Coupe.png"
222						alt=""
223						width="800"
224						height="400"
225						 fetchpriority="high"					/>
226					<div class="fs-portfolio-card__actions">
227													<button
228								type="button"
229								class="fs-portfolio-card__hit fs-portfolio-card__hit--play"
230								data-media-lightbox="https://www.flyingshapes.com/wp-content/uploads/2024/06/experimental-coupe-ai.mp4"
231								aria-label="Play video: Experimental Coupe"
232							>
233								<span class="fs-portfolio-card__icon" aria-hidden="true">
234									<span class="fs-portfolio-card__play-glyph"></span>
235								</span>
236							</button>
237												<a
238							class="fs-portfolio-card__hit fs-portfolio-card__hit--3d"
239							href="https://app.flyingshapes.com/966f8596-9243-428e-ac83-98478cbd48a3?domeEyeHeight=.6&#038;moodBoard=false&#038;shadowPlaneOpacity=1"
240							 target="_blank" rel="noopener noreferrer"							aria-label="Open Experimental Coupe in 3D"
241						>
242							<span class="fs-portfolio-card__icon" aria-hidden="true">
243								<svg class="fs-portfolio-card__glyph" viewBox="0 0 24 24" focusable="false">
244									<path fill="currentColor" d="M7.52 21.48C4.25 19.94 1.91 16.76 1.55 13H.05C.56 19.16 5.71 24 12 24l.66-.03-4.31-4.01-.83 1.52zM23.95 11C23.44 4.84 18.29 0 12 0l-.66.03 4.31 4.01.83-1.49C19.75 4.06 22.09 7.24 22.45 11h1.5z"/>
245									<text x="12" y="12" dy="0.35em" text-anchor="middle" fill="currentColor" font-size="7" font-weight="700" font-family="Roboto, sans-serif">3D</text>
246								</svg>
247							</span>
248						</a>
249					</div>
250				</div>
251											<div class="fs-portfolio-card">
252					<img
253						class="fs-portfolio-card__image"
254						src="https://www.flyingshapes.com/wp-content/uploads/2024/01/Battista.png"
255						alt=""
256						width="800"
257						height="400"
258						 loading="lazy" decoding="async"					/>
259					<div class="fs-portfolio-card__actions">
260												<a
261							class="fs-portfolio-card__hit fs-portfolio-card__hit--3d"
262							href="https://app.flyingshapes.com/1d4fe6e4-4e5e-4a2b-8596-c939a3a03a02?domeEyeHeight=.6&#038;moodBoard=false&#038;shadowPlaneOpacity=1"
263							 target="_blank" rel="noopener noreferrer"							aria-label="Open Battista in 3D"
264						>
265							<span class="fs-portfolio-card__icon" aria-hidden="true">
266								<svg class="fs-portfolio-card__glyph" viewBox="0 0 24 24" focusable="false">
267									<path fill="currentColor" d="M7.52 21.48C4.25 19.94 1.91 16.76 1.55 13H.05C.56 19.16 5.71 24 12 24l.66-.03-4.31-4.01-.83 1.52zM23.95 11C23.44 4.84 18.29 0 12 0l-.66.03 4.31 4.01.83-1.49C19.75 4.06 22.09 7.24 22.45 11h1.5z"/>
268									<text x="12" y="12" dy="0.35em" text-anchor="middle" fill="currentColor" font-size="7" font-weight="700" font-family="Roboto, sans-serif">3D</text>
269								</svg>
270							</span>
271						</a>
272					</div>
273				</div>
274											<div class="fs-portfolio-card">
275					<img
276						class="fs-portfolio-card__image"
277						src="https://www.flyingshapes.com/wp-content/uploads/2024/01/Battista-Interior-2.png"
278						alt=""
279						width="800"
280						height="400"
281						 loading="lazy" decoding="async"					/>
282					<div class="fs-portfolio-card__actions">
283												<a
284							class="fs-portfolio-card__hit fs-portfolio-card__hit--3d"
285							href="https://app.flyingshapes.com/55e686da-ae2e-4ae7-8d2c-8dfdd5ef5ff7?domeEyeHeight=.6&#038;moodBoard=false&#038;shadowPlaneOpacity=1"
286							 target="_blank" rel="noopener noreferrer"							aria-label="Open Battista Interior in 3D"
287						>
288							<span class="fs-portfolio-card__icon" aria-hidden="true">
289								<svg class="fs-portfolio-card__glyph" viewBox="0 0 24 24" focusable="false">
290									<path fill="currentColor" d="M7.52 21.48C4.25 19.94 1.91 16.76 1.55 13H.05C.56 19.16 5.71 24 12 24l.66-.03-4.31-4.01-.83 1.52zM23.95 11C23.44 4.84 18.29 0 12 0l-.66.03 4.31 4.01.83-1.49C19.75 4.06 22.09 7.24 22.45 11h1.5z"/>
291									<text x="12" y="12" dy="0.35em" text-anchor="middle" fill="currentColor" font-size="7" font-weight="700" font-family="Roboto, sans-serif">3D</text>
292								</svg>
293							</span>
294						</a>
295					</div>
296				</div>
297											<div class="fs-portfolio-card">
298					<img
299						class="fs-portfolio-card__image"
300						src="https://www.flyingshapes.com/wp-content/uploads/2024/01/EV9-Interior-2.png"
301						alt=""
302						width="800"
303						height="400"
304						 loading="lazy" decoding="async"					/>
305					<div class="fs-portfolio-card__actions">
306												<a
307							class="fs-portfolio-card__hit fs-portfolio-card__hit--3d"
308							href="https://app.flyingshapes.com/2703b08e-9d09-4bd1-83d4-45d9e3a19189?domeEyeHeight=.6&#038;moodBoard=false&#038;shadowPlaneOpacity=1"
309							 target="_blank" rel="noopener noreferrer"							aria-label="Open EV9 Interior in 3D"
310						>
311							<span class="fs-portfolio-card__icon" aria-hidden="true">
312								<svg class="fs-portfolio-card__glyph" viewBox="0 0 24 24" focusable="false">
313									<path fill="currentColor" d="M7.52 21.48C4.25 19.94 1.91 16.76 1.55 13H.05C.56 19.16 5.71 24 12 24l.66-.03-4.31-4.01-.83 1.52zM23.95 11C23.44 4.84 18.29 0 12 0l-.66.03 4.31 4.01.83-1.49C19.75 4.06 22.09 7.24 22.45 11h1.5z"/>
314									<text x="12" y="12" dy="0.35em" text-anchor="middle" fill="currentColor" font-size="7" font-weight="700" font-family="Roboto, sans-serif">3D</text>
315								</svg>
316							</span>
317						</a>
318					</div>
319				</div>
320											<div class="fs-portfolio-card fs-portfolio-card--split">
321					<img
322						class="fs-portfolio-card__image"
323						src="https://www.flyingshapes.com/wp-content/uploads/2024/01/Wind.png"
324						alt=""
325						width="800"
326						height="400"
327						 loading="lazy" decoding="async"					/>
328					<div class="fs-portfolio-card__actions">
329													<button
330								type="button"
331								class="fs-portfolio-card__hit fs-portfolio-card__hit--play"
332								data-media-lightbox="https://www.flyingshapes.com/wp-content/uploads/2023/10/Wind-compressed.mp4"
333								aria-label="Play video: Wind"
334							>
335								<span class="fs-portfolio-card__icon" aria-hidden="true">
336									<span class="fs-portfolio-card__play-glyph"></span>
337								</span>
338							</button>
339												<a
340							class="fs-portfolio-card__hit fs-portfolio-card__hit--3d"
341							href="https://app.flyingshapes.com/d6eee81c-8501-4bab-a337-17010dce2b21?domeEyeHeight=.6&#038;moodBoard=false&#038;shadowPlaneOpacity=1"
342							 target="_blank" rel="noopener noreferrer"							aria-label="Open Wind in 3D"
343						>
344							<span class="fs-portfolio-card__icon" aria-hidden="true">
345								<svg class="fs-portfolio-card__glyph" viewBox="0 0 24 24" focusable="false">
346									<path fill="currentColor" d="M7.52 21.48C4.25 19.94 1.91 16.76 1.55 13H.05C.56 19.16 5.71 24 12 24l.66-.03-4.31-4.01-.83 1.52zM23.95 11C23.44 4.84 18.29 0 12 0l-.66.03 4.31 4.01.83-1.49C19.75 4.06 22.09 7.24 22.45 11h1.5z"/>
347									<text x="12" y="12" dy="0.35em" text-anchor="middle" fill="currentColor" font-size="7" font-weight="700" font-family="Roboto, sans-serif">3D</text>
348								</svg>
349							</span>
350						</a>
351					</div>
352				</div>
353											<div class="fs-portfolio-card fs-portfolio-card--split">
354					<img
355						class="fs-portfolio-card__image"
356						src="https://www.flyingshapes.com/wp-content/uploads/2024/01/EV9-2.png"
357						alt=""
358						width="800"
359						height="400"
360						 loading="lazy" decoding="async"					/>
361					<div class="fs-portfolio-card__actions">
362													<button
363								type="button"
364								class="fs-portfolio-card__hit fs-portfolio-card__hit--play"
365								data-media-lightbox="https://www.flyingshapes.com/wp-content/uploads/2023/12/EV9.mp4"
366								aria-label="Play video: EV9"
367							>
368								<span class="fs-portfolio-card__icon" aria-hidden="true">
369									<span class="fs-portfolio-card__play-glyph"></span>
370								</span>
371							</button>
372												<a
373							class="fs-portfolio-card__hit fs-portfolio-card__hit--3d"
374							href="https://app.flyingshapes.com/dd69a480-42c4-4e91-9925-42c42063787e?domeEyeHeight=.6&#038;moodBoard=false&#038;shadowPlaneOpacity=1"
375							 target="_blank" rel="noopener noreferrer"							aria-label="Open EV9 in 3D"
376						>
377							<span class="fs-portfolio-card__icon" aria-hidden="true">
378								<svg class="fs-portfolio-card__glyph" viewBox="0 0 24 24" focusable="false">
379									<path fill="currentColor" d="M7.52 21.48C4.25 19.94 1.91 16.76 1.55 13H.05C.56 19.16 5.71 24 12 24l.66-.03-4.31-4.01-.83 1.52zM23.95 11C23.44 4.84 18.29 0 12 0l-.66.03 4.31 4.01.83-1.49C19.75 4.06 22.09 7.24 22.45 11h1.5z"/>
380									<text x="12" y="12" dy="0.35em" text-anchor="middle" fill="currentColor" font-size="7" font-weight="700" font-family="Roboto, sans-serif">3D</text>
381								</svg>
382							</span>
383						</a>
384					</div>
385				</div>
386											<div class="fs-portfolio-card">
387					<img
388						class="fs-portfolio-card__image"
389						src="https://www.flyingshapes.com/wp-content/uploads/2024/01/Sphere-RS.png"
390						alt=""
391						width="800"
392						height="400"
393						 loading="lazy" decoding="async"					/>
394					<div class="fs-portfolio-card__actions">
395												<a
396							class="fs-portfolio-card__hit fs-portfolio-card__hit--3d"
397							href="https://app.flyingshapes.com/1d5612dd-cb74-4e02-8e15-04bcd9ef8655?domeEyeHeight=.6&#038;moodBoard=false&#038;shadowPlaneOpacity=1"
398							 target="_blank" rel="noopener noreferrer"							aria-label="Open Sphere RS in 3D"
399						>
400							<span class="fs-portfolio-card__icon" aria-hidden="true">
401								<svg class="fs-portfolio-card__glyph" viewBox="0 0 24 24" focusable="false">
402									<path fill="currentColor" d="M7.52 21.48C4.25 19.94 1.91 16.76 1.55 13H.05C.56 19.16 5.71 24 12 24l.66-.03-4.31-4.01-.83 1.52zM23.95 11C23.44 4.84 18.29 0 12 0l-.66.03 4.31 4.01.83-1.49C19.75 4.06 22.09 7.24 22.45 11h1.5z"/>
403									<text x="12" y="12" dy="0.35em" text-anchor="middle" fill="currentColor" font-size="7" font-weight="700" font-family="Roboto, sans-serif">3D</text>
404								</svg>
405							</span>
406						</a>
407					</div>
408				</div>
409											<div class="fs-portfolio-card fs-portfolio-card--split">
410					<img
411						class="fs-portfolio-card__image"
412						src="https://www.flyingshapes.com/wp-content/uploads/2024/01/Classy-Bavarian.png"
413						alt=""
414						width="800"
415						height="400"
416						 loading="lazy" decoding="async"					/>
417					<div class="fs-portfolio-card__actions">
418													<button
419								type="button"
420								class="fs-portfolio-card__hit fs-portfolio-card__hit--play"
421								data-media-lightbox="https://www.flyingshapes.com/wp-content/uploads/2023/10/Classy_Bavarian-compressed.mp4"
422								aria-label="Play video: Classy Bavarian"
423							>
424								<span class="fs-portfolio-card__icon" aria-hidden="true">
425									<span class="fs-portfolio-card__play-glyph"></span>
426								</span>
427							</button>
428												<a
429							class="fs-portfolio-card__hit fs-portfolio-card__hit--3d"
430							href="https://app.flyingshapes.com/6918f186-6d60-4b89-a28a-0ebbf853f503?domeEyeHeight=.6&#038;moodBoard=false&#038;shadowPlaneOpacity=1"
431							 target="_blank" rel="noopener noreferrer"							aria-label="Open Classy Bavarian in 3D"
432						>
433							<span class="fs-portfolio-card__icon" aria-hidden="true">
434								<svg class="fs-portfolio-card__glyph" viewBox="0 0 24 24" focusable="false">
435									<path fill="currentColor" d="M7.52 21.48C4.25 19.94 1.91 16.76 1.55 13H.05C.56 19.16 5.71 24 12 24l.66-.03-4.31-4.01-.83 1.52zM23.95 11C23.44 4.84 18.29 0 12 0l-.66.03 4.31 4.01.83-1.49C19.75 4.06 22.09 7.24 22.45 11h1.5z"/>
436									<text x="12" y="12" dy="0.35em" text-anchor="middle" fill="currentColor" font-size="7" font-weight="700" font-family="Roboto, sans-serif">3D</text>
437								</svg>
438							</span>
439						</a>
440					</div>
441				</div>
442											<div class="fs-portfolio-card fs-portfolio-card--split">
443					<img
444						class="fs-portfolio-card__image"
445						src="https://www.flyingshapes.com/wp-content/uploads/2024/01/Aang.png"
446						alt=""
447						width="800"
448						height="400"
449						 loading="lazy" decoding="async"					/>
450					<div class="fs-portfolio-card__actions">
451													<button
452								type="button"
453								class="fs-portfolio-card__hit fs-portfolio-card__hit--play"
454								data-media-lightbox="https://www.flyingshapes.com/wp-content/uploads/2023/10/Avatr-compressed-1.mp4"
455								aria-label="Play video: Aang"
456							>
457								<span class="fs-portfolio-card__icon" aria-hidden="true">
458									<span class="fs-portfolio-card__play-glyph"></span>
459								</span>
460							</button>
461												<a
462							class="fs-portfolio-card__hit fs-portfolio-card__hit--3d"
463							href="https://app.flyingshapes.com/5498660c-fd1d-4781-8ff3-ea0a7e48d2b4?domeEyeHeight=.6&#038;moodBoard=false&#038;shadowPlaneOpacity=1"
464							 target="_blank" rel="noopener noreferrer"							aria-label="Open Aang in 3D"
465						>
466							<span class="fs-portfolio-card__icon" aria-hidden="true">
467								<svg class="fs-portfolio-card__glyph" viewBox="0 0 24 24" focusable="false">
468									<path fill="currentColor" d="M7.52 21.48C4.25 19.94 1.91 16.76 1.55 13H.05C.56 19.16 5.71 24 12 24l.66-.03-4.31-4.01-.83 1.52zM23.95 11C23.44 4.84 18.29 0 12 0l-.66.03 4.31 4.01.83-1.49C19.75 4.06 22.09 7.24 22.45 11h1.5z"/>
469									<text x="12" y="12" dy="0.35em" text-anchor="middle" fill="currentColor" font-size="7" font-weight="700" font-family="Roboto, sans-serif">3D</text>
470								</svg>
471							</span>
472						</a>
473					</div>
474				</div>
475											<div class="fs-portfolio-card fs-portfolio-card--split">
476					<img
477						class="fs-portfolio-card__image"
478						src="https://www.flyingshapes.com/wp-content/uploads/2024/01/Silver-Arrow.png"
479						alt=""
480						width="800"
481						height="400"
482						 loading="lazy" decoding="async"					/>
483					<div class="fs-portfolio-card__actions">
484													<button
485								type="button"
486								class="fs-portfolio-card__hit fs-portfolio-card__hit--play"
487								data-media-lightbox="https://www.flyingshapes.com/wp-content/uploads/2023/10/Silver_Arrow-compressed.mp4"
488								aria-label="Play video: Silver Arrow"
489							>
490								<span class="fs-portfolio-card__icon" aria-hidden="true">
491									<span class="fs-portfolio-card__play-glyph"></span>
492								</span>
493							</button>
494												<a
495							class="fs-portfolio-card__hit fs-portfolio-card__hit--3d"
496							href="https://app.flyingshapes.com/70a39edf-8642-48e3-8e5b-9a154426f0e7?domeEyeHeight=.6&#038;moodBoard=false&#038;shadowPlaneOpacity=1"
497							 target="_blank" rel="noopener noreferrer"							aria-label="Open Silver Arrow in 3D"
498						>
499							<span class="fs-portfolio-card__icon" aria-hidden="true">
500								<svg class="fs-portfolio-card__glyph" viewBox="0 0 24 24" focusable="false">
501									<path fill="currentColor" d="M7.52 21.48C4.25 19.94 1.91 16.76 1.55 13H.05C.56 19.16 5.71 24 12 24l.66-.03-4.31-4.01-.83 1.52zM23.95 11C23.44 4.84 18.29 0 12 0l-.66.03 4.31 4.01.83-1.49C19.75 4.06 22.09 7.24 22.45 11h1.5z"/>
502									<text x="12" y="12" dy="0.35em" text-anchor="middle" fill="currentColor" font-size="7" font-weight="700" font-family="Roboto, sans-serif">3D</text>
503								</svg>
504							</span>
505						</a>
506					</div>
507				</div>
508											<div class="fs-portfolio-card fs-portfolio-card--split">
509					<img
510						class="fs-portfolio-card__image"
511						src="https://www.flyingshapes.com/wp-content/uploads/2024/01/Italian-Bull.png"
512						alt=""
513						width="800"
514						height="400"
515						 loading="lazy" decoding="async"					/>
516					<div class="fs-portfolio-card__actions">
517													<button
518								type="button"
519								class="fs-portfolio-card__hit fs-portfolio-card__hit--play"
520								data-media-lightbox="https://www.flyingshapes.com/wp-content/uploads/2023/10/Italian-Bull-compressed.mp4"
521								aria-label="Play video: Italian Bull"
522							>
523								<span class="fs-portfolio-card__icon" aria-hidden="true">
524									<span class="fs-portfolio-card__play-glyph"></span>
525								</span>
526							</button>
527												<a
528							class="fs-portfolio-card__hit fs-portfolio-card__hit--3d"
529							href="https://app.flyingshapes.com/65440530-e52e-4c12-9fd9-4ecb9c218bb9?domeEyeHeight=.6&#038;moodBoard=false&#038;shadowPlaneOpacity=1"
530							 target="_blank" rel="noopener noreferrer"							aria-label="Open Italian Bull in 3D"
531						>
532							<span class="fs-portfolio-card__icon" aria-hidden="true">
533								<svg class="fs-portfolio-card__glyph" viewBox="0 0 24 24" focusable="false">
534									<path fill="currentColor" d="M7.52 21.48C4.25 19.94 1.91 16.76 1.55 13H.05C.56 19.16 5.71 24 12 24l.66-.03-4.31-4.01-.83 1.52zM23.95 11C23.44 4.84 18.29 0 12 0l-.66.03 4.31 4.01.83-1.49C19.75 4.06 22.09 7.24 22.45 11h1.5z"/>
535									<text x="12" y="12" dy="0.35em" text-anchor="middle" fill="currentColor" font-size="7" font-weight="700" font-family="Roboto, sans-serif">3D</text>
536								</svg>
537							</span>
538						</a>
539					</div>
540				</div>
541											<div class="fs-portfolio-card">
542					<img
543						class="fs-portfolio-card__image"
544						src="https://www.flyingshapes.com/wp-content/uploads/2024/01/Ringtaxi.png"
545						alt=""
546						width="800"
547						height="400"
548						 loading="lazy" decoding="async"					/>
549					<div class="fs-portfolio-card__actions">
550												<a
551							class="fs-portfolio-card__hit fs-portfolio-card__hit--3d"
552							href="https://app.flyingshapes.com/20fb55fd-da68-4af3-912e-e3bb4602c84f?domeEyeHeight=.6&#038;moodBoard=false&#038;shadowPlaneOpacity=1"
553							 target="_blank" rel="noopener noreferrer"							aria-label="Open Ringtaxi in 3D"
554						>
555							<span class="fs-portfolio-card__icon" aria-hidden="true">
556								<svg class="fs-portfolio-card__glyph" viewBox="0 0 24 24" focusable="false">
557									<path fill="currentColor" d="M7.52 21.48C4.25 19.94 1.91 16.76 1.55 13H.05C.56 19.16 5.71 24 12 24l.66-.03-4.31-4.01-.83 1.52zM23.95 11C23.44 4.84 18.29 0 12 0l-.66.03 4.31 4.01.83-1.49C19.75 4.06 22.09 7.24 22.45 11h1.5z"/>
558									<text x="12" y="12" dy="0.35em" text-anchor="middle" fill="currentColor" font-size="7" font-weight="700" font-family="Roboto, sans-serif">3D</text>
559								</svg>
560							</span>
561						</a>
562					</div>
563				</div>
564											<div class="fs-portfolio-card fs-portfolio-card--split">
565					<img
566						class="fs-portfolio-card__image"
567						src="https://www.flyingshapes.com/wp-content/uploads/2024/01/Nordic-Coupe.png"
568						alt=""
569						width="800"
570						height="400"
571						 loading="lazy" decoding="async"					/>
572					<div class="fs-portfolio-card__actions">
573													<button
574								type="button"
575								class="fs-portfolio-card__hit fs-portfolio-card__hit--play"
576								data-media-lightbox="https://www.flyingshapes.com/wp-content/uploads/2023/10/Nordic-Coupe-compressed.mp4"
577								aria-label="Play video: Nordic Coupe"
578							>
579								<span class="fs-portfolio-card__icon" aria-hidden="true">
580									<span class="fs-portfolio-card__play-glyph"></span>
581								</span>
582							</button>
583												<a
584							class="fs-portfolio-card__hit fs-portfolio-card__hit--3d"
585							href="https://app.flyingshapes.com/ed305e6b-0f78-458a-a9d2-66b10724d74b?domeEyeHeight=.6&#038;moodBoard=false&#038;shadowPlaneOpacity=1"
586							 target="_blank" rel="noopener noreferrer"							aria-label="Open Nordic Coupe in 3D"
587						>
588							<span class="fs-portfolio-card__icon" aria-hidden="true">
589								<svg class="fs-portfolio-card__glyph" viewBox="0 0 24 24" focusable="false">
590									<path fill="currentColor" d="M7.52 21.48C4.25 19.94 1.91 16.76 1.55 13H.05C.56 19.16 5.71 24 12 24l.66-.03-4.31-4.01-.83 1.52zM23.95 11C23.44 4.84 18.29 0 12 0l-.66.03 4.31 4.01.83-1.49C19.75 4.06 22.09 7.24 22.45 11h1.5z"/>
591									<text x="12" y="12" dy="0.35em" text-anchor="middle" fill="currentColor" font-size="7" font-weight="700" font-family="Roboto, sans-serif">3D</text>
592								</svg>
593							</span>
594						</a>
595					</div>
596				</div>
597											<div class="fs-portfolio-card">
598					<img
599						class="fs-portfolio-card__image"
600						src="https://www.flyingshapes.com/wp-content/uploads/2024/01/R5.png"
601						alt=""
602						width="800"
603						height="400"
604						 loading="lazy" decoding="async"					/>
605					<div class="fs-portfolio-card__actions">
606												<a
607							class="fs-portfolio-card__hit fs-portfolio-card__hit--3d"
608							href="https://app.flyingshapes.com/94f4dd54-afa1-43f5-a03d-b09b796b4c25?domeEyeHeight=.6&#038;moodBoard=false&#038;shadowPlaneOpacity=1"
609							 target="_blank" rel="noopener noreferrer"							aria-label="Open R5 in 3D"
610						>
611							<span class="fs-portfolio-card__icon" aria-hidden="true">
612								<svg class="fs-portfolio-card__glyph" viewBox="0 0 24 24" focusable="false">
613									<path fill="currentColor" d="M7.52 21.48C4.25 19.94 1.91 16.76 1.55 13H.05C.56 19.16 5.71 24 12 24l.66-.03-4.31-4.01-.83 1.52zM23.95 11C23.44 4.84 18.29 0 12 0l-.66.03 4.31 4.01.83-1.49C19.75 4.06 22.09 7.24 22.45 11h1.5z"/>
614									<text x="12" y="12" dy="0.35em" text-anchor="middle" fill="currentColor" font-size="7" font-weight="700" font-family="Roboto, sans-serif">3D</text>
615								</svg>
616							</span>
617						</a>
618					</div>
619				</div>
620											<div class="fs-portfolio-card">
621					<img
622						class="fs-portfolio-card__image"
623						src="https://www.flyingshapes.com/wp-content/uploads/2024/01/VGT.png"
624						alt=""
625						width="800"
626						height="400"
627						 loading="lazy" decoding="async"					/>
628					<div class="fs-portfolio-card__actions">
629												<a
630							class="fs-portfolio-card__hit fs-portfolio-card__hit--3d"
631							href="https://app.flyingshapes.com/36056834-c6c8-4212-81d8-48bb4236aa0e?domeEyeHeight=.6&#038;moodBoard=false&#038;shadowPlaneOpacity=1"
632							 target="_blank" rel="noopener noreferrer"							aria-label="Open VGT in 3D"
633						>
634							<span class="fs-portfolio-card__icon" aria-hidden="true">
635								<svg class="fs-portfolio-card__glyph" viewBox="0 0 24 24" focusable="false">
636									<path fill="currentColor" d="M7.52 21.48C4.25 19.94 1.91 16.76 1.55 13H.05C.56 19.16 5.71 24 12 24l.66-.03-4.31-4.01-.83 1.52zM23.95 11C23.44 4.84 18.29 0 12 0l-.66.03 4.31 4.01.83-1.49C19.75 4.06 22.09 7.24 22.45 11h1.5z"/>
637									<text x="12" y="12" dy="0.35em" text-anchor="middle" fill="currentColor" font-size="7" font-weight="700" font-family="Roboto, sans-serif">3D</text>
638								</svg>
639							</span>
640						</a>
641					</div>
642				</div>
643											<div class="fs-portfolio-card">
644					<img
645						class="fs-portfolio-card__image"
646						src="https://www.flyingshapes.com/wp-content/uploads/2024/03/id-gta.webp"
647						alt=""
648						width="800"
649						height="400"
650						 loading="lazy" decoding="async"					/>
651					<div class="fs-portfolio-card__actions">
652												<a
653							class="fs-portfolio-card__hit fs-portfolio-card__hit--3d"
654							href="https://www.flyingshapes.com/id-gti"
655														aria-label="Open ID GTI in 3D"
656						>
657							<span class="fs-portfolio-card__icon" aria-hidden="true">
658								<svg class="fs-portfolio-card__glyph" viewBox="0 0 24 24" focusable="false">
659									<path fill="currentColor" d="M7.52 21.48C4.25 19.94 1.91 16.76 1.55 13H.05C.56 19.16 5.71 24 12 24l.66-.03-4.31-4.01-.83 1.52zM23.95 11C23.44 4.84 18.29 0 12 0l-.66.03 4.31 4.01.83-1.49C19.75 4.06 22.09 7.24 22.45 11h1.5z"/>
660									<text x="12" y="12" dy="0.35em" text-anchor="middle" fill="currentColor" font-size="7" font-weight="700" font-family="Roboto, sans-serif">3D</text>
661								</svg>
662							</span>
663						</a>
664					</div>
665				</div>
666					</div>
667
668		<p class="fs-disclaimer">
669			Disclaimer: Our software is independent and not affiliated with the original manufacturers of the depicted vehicles. The shown models are replicas and not original products of the respective automotive manufacturers. All trademarks and designs are owned by their respective rights holders and are used for demonstration purposes only.
670		</p>
671	</div>
672</article></main>
673<footer class="fs-footer">
674	<div class="fs-footer__grid">
675		<div>
676			<h4>get started</h4>
677			<ul>
678				<li><button type="button" data-lightbox="trial">free trial</button></li>
679				<li><a href="https://www.flyingshapes.com/faq/">faq</a></li>
680				<li><a href="https://www.flyingshapes.com/setup/">setup XR</a></li>
681			</ul>
682		</div>
683		<div>
684			<h4>community</h4>
685			<ul>
686				<li><a href="https://app.flyingshapes.com" rel="noopener noreferrer">login</a></li>
687				<li><a href="https://www.flyingshapes.com/support/">support</a></li>
688				<li><button type="button" data-lightbox="newsletter">newsletter</button></li>
689			</ul>
690		</div>
691		<div>
692			<h4>reach out</h4>
693			<ul>
694				<li><button type="button" data-lightbox="contact">contact</button></li>
695				<!-- <li><a href="https://www.flyingshapes.com/careers/">careers</a></li> -->
696				<!-- <li><a href="https://www.flyingshapes.com/press/">press</a></li> -->
697			</ul>
698		</div>
699		<div>
700			<h4>legal information</h4>
701			<ul>
702				<li><a href="https://www.flyingshapes.com/imprint/">imprint</a></li>
703				<li><a href="https://www.flyingshapes.com/privacy/">orivacy policy</a></li>
704			</ul>
705		</div>
706	</div>
707	<div class="fs-footer__bottom">
708		&copy; 2026 flyingshapes GmbH
709	</div>
710</footer>
711
712		<dialog class="fs-lightbox" id="fs-lightbox-newsletter" data-lightbox-panel="newsletter" aria-labelledby="fs-lightbox-title-newsletter">
713			<div class="fs-lightbox__panel">
714				<button type="button" class="fs-lightbox__close" data-lightbox-close aria-label="Close">
715					<span aria-hidden="true">&times;</span>
716				</button>
717				<div class="fs-lightbox__body">
718					<h2 id="fs-lightbox-title-newsletter" class="fs-lightbox__title">Stay up to date</h2>
719											<p class="fs-lightbox__desc">If you sign up for our newsletter, we will occasionally send you updates about our company, our upcoming product, beta launches and we will share some information on the latest trends in product design, virtual reality and CAD.</p>
720										<div class="fs-lightbox__form" data-ac-form="newsletter" data-fs-form-slot="newsletter">
721						<form method="POST" action="https://flyingshapes.activehosted.com/proc.php" id="_form_1_" class="_form _form_1 _inline-form  _dark" novalidate data-styles-version="5">
722  <input type="hidden" name="u" value="1" />
723  <input type="hidden" name="f" value="1" />
724  <input type="hidden" name="s" />
725  <input type="hidden" name="c" value="0" />
726  <input type="hidden" name="m" value="0" />
727  <input type="hidden" name="act" value="sub" />
728  <input type="hidden" name="v" value="2" />
729  <input type="hidden" name="or" value="bd96b2eb-9b61-9dec-8861-59ebe557602c" />
730  <div class="_form-content">
731    <div class="_form_element _x98082402 _full_width " >
732      <label for="fullname" class="_form-label">
733        Name<span class="field-required">
734        *
735      </span>
736    </label>
737    <div class="_field-wrapper">
738      <input type="text" id="fullname" name="fullname" placeholder="How may we call you?" required/>
739    </div>
740  </div>
741  <div class="_form_element _x05723213 _full_width " >
742    <label for="email" class="_form-label">
743      E-mail<span class="field-required">
744      *
745    </span>
746  </label>
747  <div class="_field-wrapper">
748    <input type="text" id="email" name="email" placeholder="" required/>
749  </div>
750</div>
751<div class="_button-wrapper _full_width">
752  <button id="_form_1_submit" class="_submit" type="submit">
753    subscribe
754  </button>
755</div>
756<div class="_clear-element">
757</div>
758</div>
759<div class="_form-thank-you" style="display:none;">
760</div>
761</form>
761<script>
762window.cfields = [];
763window._show_thank_you = function(id, message, trackcmp_url, email) {
764    var form = document.getElementById('_form_' + id + '_'), thank_you = form.querySelector('._form-thank-you');
765    form.querySelector('._form-content').style.display = 'none';
766    thank_you.innerHTML = message;
767    thank_you.style.display = 'block';
768    const vgoAlias = typeof visitorGlobalObjectAlias === 'undefined' ? 'vgo' : visitorGlobalObjectAlias;
769    var visitorObject = window[vgoAlias];
770    if (email && typeof visitorObject !== 'undefined') {
771        visitorObject('setEmail', email);
772        visitorObject('update');
773    } else if (typeof(trackcmp_url) != 'undefined' && trackcmp_url) {
774        // Site tracking URL to use after inline form submission.
775        _load_script(trackcmp_url);
776    }
777    if (typeof window._form_callback !== 'undefined') window._form_callback(id);
778    thank_you.setAttribute('tabindex', '-1');
779    thank_you.focus();
780};
781window._show_unsubscribe = function(id, message, trackcmp_url, email) {
782    var form = document.getElementById('_form_' + id + '_'), unsub = form.querySelector('._form-thank-you');
783    var branding = form.querySelector('._form-branding');
784    if (branding) {
785        branding.style.display = 'none';
786    }
787    form.querySelector('._form-content').style.display = 'none';
788    unsub.style.display = 'block';
789    form.insertAdjacentHTML('afterend', message)
790    const vgoAlias = typeof visitorGlobalObjectAlias === 'undefined' ? 'vgo' : visitorGlobalObjectAlias;
791    var visitorObject = window[vgoAlias];
792    if (email && typeof visitorObject !== 'undefined') {
793        visitorObject('setEmail', email);
794        visitorObject('update');
795    } else if (typeof(trackcmp_url) != 'undefined' && trackcmp_url) {
796        // Site tracking URL to use after inline form submission.
797        _load_script(trackcmp_url);
798    }
799    if (typeof window._form_callback !== 'undefined') window._form_callback(id);
800};
801window._show_error = function(id, message, html) {
802    var form = document.getElementById('_form_' + id + '_'),
803        err = document.createElement('div'),
804        button = form.querySelector('button[type="submit"]'),
805        old_error = form.querySelector('._form_error');
806    if (old_error) old_error.parentNode.removeChild(old_error);
807    err.innerHTML = message;
808    err.className = '_error-inner _form_error _no_arrow';
809    var wrapper = document.createElement('div');
810    wrapper.className = '_form-inner _show_be_error';
811    wrapper.appendChild(err);
812    button.parentNode.insertBefore(wrapper, button);
813    var submitButton = form.querySelector('[id^="_form"][id$="_submit"]');
814    submitButton.disabled = false;
815    submitButton.classList.remove('processing');
816    if (html) {
817        var div = document.createElement('div');
818        div.className = '_error-html';
819        div.innerHTML = html;
820        err.appendChild(div);
821    }
822};
823window._show_pc_confirmation = function(id, header, detail, show, email) {
824    var form = document.getElementById('_form_' + id + '_'), pc_confirmation = form.querySelector('._form-pc-confirmation');
825    if (pc_confirmation.style.display === 'none') {
826        form.querySelector('._form-content').style.display = 'none';
827        pc_confirmation.innerHTML = "<div class='_form-title'>" + header + "</div>" + "<p>" + detail + "</p>" +
828        "<button class='_submit' id='hideButton'>Manage preferences</button>";
829        pc_confirmation.style.display = 'block';
830        var mp = document.querySelector('input[name="mp"]');
831        mp.value = '0';
832    } else {
833        form.querySelector('._form-content').style.display = 'inline';
834        pc_confirmation.style.display = 'none';
835    }
836
837    var hideButton = document.getElementById('hideButton');
838    // Add event listener to the button
839    hideButton.addEventListener('click', function() {
840        var submitButton = document.querySelector('#_form_1_submit');
841        submitButton.disabled = false;
842        submitButton.classList.remove('processing');
843        var mp = document.querySelector('input[name="mp"]');
844        mp.value = '1';
845        const cacheBuster = new URL(window.location.href);
846        cacheBuster.searchParams.set('v', new Date().getTime());
847        window.location.href = cacheBuster.toString();
848    });
849
850    const vgoAlias = typeof visitorGlobalObjectAlias === 'undefined' ? 'vgo' : visitorGlobalObjectAlias;
851    var visitorObject = window[vgoAlias];
852    if (email && typeof visitorObject !== 'undefined') {
853        visitorObject('setEmail', email);
854        visitorObject('update');
855    } else if (typeof(trackcmp_url) != 'undefined' && trackcmp_url) {
856        // Site tracking URL to use after inline form submission.
857        _load_script(trackcmp_url);
858    }
859    if (typeof window._form_callback !== 'undefined') window._form_callback(id);
860};
861window._load_script = function(url, callback, isSubmit) {
862    var head = document.querySelector('head'), script = document.createElement('script'), r = false;
863    var submitButton = document.querySelector('#_form_1_submit');
864    script.charset = 'utf-8';
865    script.src = url;
866    if (callback) {
867        script.onload = script.onreadystatechange = function() {
868            if (!r && (!this.readyState || this.readyState == 'complete')) {
869                r = true;
870                callback();
871            }
872        };
873    }
874    script.onerror = function() {
875        if (isSubmit) {
876            if (script.src.length > 10000) {
877                _show_error("1", "Sorry, your submission failed. Please shorten your responses and try again.");
878            } else {
879                _show_error("1", "Sorry, your submission failed. Please try again.");
880            }
881            submitButton.disabled = false;
882            submitButton.classList.remove('processing');
883        }
884    }
885
886    head.appendChild(script);
887};
888(function() {
889    var iti;
890    if (window.location.search.search("excludeform") !== -1) return false;
891    var getCookie = function(name) {
892        var match = document.cookie.match(new RegExp('(^|; )' + name + '=([^;]+)'));
893        return match ? match[2] : localStorage.getItem(name);
894    }
895    var setCookie = function(name, value) {
896        var now = new Date();
897        var time = now.getTime();
898        var expireTime = time + 1000 * 60 * 60 * 24 * 365;
899        now.setTime(expireTime);
900        document.cookie = name + '=' + value + '; expires=' + now + ';path=/; Secure; SameSite=Lax;';
901        localStorage.setItem(name, value);
902    }
903    var addEvent = function(element, event, func) {
904        if (element.addEventListener) {
905            element.addEventListener(event, func);
906        } else {
907            var oldFunc = element['on' + event];
908            element['on' + event] = function() {
909                oldFunc.apply(this, arguments);
910                func.apply(this, arguments);
911            };
912        }
913    }
914    var _removed = false;
915        var form_to_submit = document.getElementById('_form_1_');
916    var allInputs = form_to_submit.querySelectorAll('input, select, textarea'), tooltips = [], submitted = false;
917
918    var getUrlParam = function(name) {
919        if (name.toLowerCase() !== 'email') {
920            var params = new URLSearchParams(window.location.search);
921            return params.get(name) || false;
922        }
923        // email is a special case because a plus is valid in the email address
924        var qString = window.location.search;
925        if (!qString) {
926            return false;
927        }
928        var parameters = qString.substr(1).split('&');
929        for (var i = 0; i < parameters.length; i++) {
930            var parameter = parameters[i].split('=');
931            if (parameter[0].toLowerCase() === 'email') {
932                return parameter[1] === undefined ? true : decodeURIComponent(parameter[1]);
933            }
934        }
935        return false;
936    };
937
938    var acctDateFormat = "%B-%d-%Y";
939    var getNormalizedDate = function(date, acctFormat) {
940        var decodedDate = decodeURIComponent(date);
941        if (acctFormat && acctFormat.match(/(%d|%e).*%m/gi) !== null) {
942            return decodedDate.replace(/(\d{2}).*(\d{2}).*(\d{4})/g, '$3-$2-$1');
943        } else if (Date.parse(decodedDate)) {
944            var dateObj = new Date(decodedDate);
945            var year = dateObj.getFullYear();
946            var month = dateObj.getMonth() + 1;
947            var day = dateObj.getDate();
948            return `${year}-${month < 10 ? `0${month}` : month}-${day < 10 ? `0${day}` : day}`;
949        }
950        return false;
951    };
952
953    var getNormalizedTime = function(time) {
954        var hour, minutes;
955        var decodedTime = decodeURIComponent(time);
956        var timeParts = Array.from(decodedTime.matchAll(/(\d{1,2}):(\d{1,2})\W*([AaPp][Mm])?/gm))[0];
957        if (timeParts[3]) { // 12 hour format
958            var isPM = timeParts[3].toLowerCase() === 'pm';
959            if (isPM) {
960                hour = parseInt(timeParts[1]) === 12 ? '12' : `${parseInt(timeParts[1]) + 12}`;
961            } else {
962                hour = parseInt(timeParts[1]) === 12 ? '0' : timeParts[1];
963            }
964        } else { // 24 hour format
965            hour = timeParts[1];
966        }
967        var normalizedHour = parseInt(hour) < 10 ? `0${parseInt(hour)}` : hour;
968        var minutes = timeParts[2];
969        return `${normalizedHour}:${minutes}`;
970    };
971
972    for (var i = 0; i < allInputs.length; i++) {
973        var regexStr = "field\\[(\\d+)\\]";
974        var results = new RegExp(regexStr).exec(allInputs[i].name);
975        if (results != undefined) {
976            allInputs[i].dataset.name = allInputs[i].name.match(/\[time\]$/)
977                ? `${window.cfields[results[1]]}_time`
978                : window.cfields[results[1]];
979        } else {
980            allInputs[i].dataset.name = allInputs[i].name;
981        }
982        var fieldVal = getUrlParam(allInputs[i].dataset.name);
983
984        if (fieldVal) {
985            if (allInputs[i].dataset.autofill === "false") {
986                continue;
987            }
988            if (allInputs[i].type == "radio" || allInputs[i].type == "checkbox") {
989                if (allInputs[i].value == fieldVal) {
990                    allInputs[i].checked = true;
991                }
992            } else if (allInputs[i].type == "date") {
993                allInputs[i].value = getNormalizedDate(fieldVal, acctDateFormat);
994            } else if (allInputs[i].type == "time") {
995                allInputs[i].value = getNormalizedTime(fieldVal);
996            } else {
997                allInputs[i].value = fieldVal;
998            }
999        }
1000    }
1001
1002    var remove_tooltips = function() {
1003        for (var i = 0; i < tooltips.length; i++) {
1004            tooltips[i].tip.parentNode.removeChild(tooltips[i].tip);
1005        }
1006        tooltips = [];
1007    };
1008    var remove_tooltip = function(elem) {
1009        for (var i = 0; i < tooltips.length; i++) {
1010            if (tooltips[i].elem === elem) {
1011                tooltips[i].tip.parentNode.removeChild(tooltips[i].tip);
1012                tooltips.splice(i, 1);
1013                return;
1014            }
1015        }
1016    };
1017    var create_tooltip = function(elem, text) {
1018        var tooltip = document.createElement('div'),
1019            arrow = document.createElement('div'),
1020            inner = document.createElement('div'), new_tooltip = {};
1021        tooltip.id = `${elem.id}-error`;
1022        tooltip.setAttribute('role', 'alert')
1023        if (elem.type != 'radio' && (elem.type != 'checkbox' || elem.name === 'sms_consent')) {
1024            tooltip.className = '_error';
1025            arrow.className = '_error-arrow';
1026            inner.className = '_error-inner';
1027            inner.innerHTML = text;
1028            tooltip.appendChild(arrow);
1029            tooltip.appendChild(inner);
1030            elem.parentNode.appendChild(tooltip);
1031        } else {
1032            tooltip.className = '_error-inner _no_arrow';
1033            tooltip.innerHTML = text;
1034            elem.parentNode.insertBefore(tooltip, elem);
1035            new_tooltip.no_arrow = true;
1036        }
1037        new_tooltip.tip = tooltip;
1038        new_tooltip.elem = elem;
1039        tooltips.push(new_tooltip);
1040        return new_tooltip;
1041    };
1042    var resize_tooltip = function(tooltip) {
1043        var rect = tooltip.elem.getBoundingClientRect();
1044        var doc = document.documentElement,
1045            scrollPosition = rect.top - ((window.pageYOffset || doc.scrollTop)  - (doc.clientTop || 0));
1046        if (scrollPosition < 40) {
1047            tooltip.tip.className = tooltip.tip.className.replace(/ ?(_above|_below) ?/g, '') + ' _below';
1048        } else {
1049            tooltip.tip.className = tooltip.tip.className.replace(/ ?(_above|_below) ?/g, '') + ' _above';
1050        }
1051    };
1052    var resize_tooltips = function() {
1053        if (_removed) return;
1054        for (var i = 0; i < tooltips.length; i++) {
1055            if (!tooltips[i].no_arrow) resize_tooltip(tooltips[i]);
1056        }
1057    };
1058    var validate_field = function(elem, remove) {
1059        var tooltip = null, value = elem.value, no_error = true;
1060        remove ? remove_tooltip(elem) : false;
1061        elem.removeAttribute('aria-invalid');
1062        elem.removeAttribute('aria-describedby');
1063        if (elem.type != 'checkbox') elem.className = elem.className.replace(/ ?_has_error ?/g, '');
1064        if (elem.getAttribute('required') !== null) {
1065            if (elem.type == 'radio' || (elem.type == 'checkbox' && /any/.test(elem.className))) {
1066                var elems = form_to_submit.elements[elem.name];
1067                if (!(elems instanceof NodeList || elems instanceof HTMLCollection) || elems.length <= 1) {
1068                    no_error = elem.checked;
1069                }
1070                else {
1071                    no_error = false;
1072                    for (var i = 0; i < elems.length; i++) {
1073                        if (elems[i].checked) no_error = true;
1074                    }
1075                }
1076                if (!no_error) {
1077                    tooltip = create_tooltip(elem, "Please select an option.");
1078                }
1079            } else if (elem.type =='checkbox') {
1080                var elems = form_to_submit.elements[elem.name], found = false, err = [];
1081                no_error = true;
1082                for (var i = 0; i < elems.length; i++) {
1083                    if (elems[i].getAttribute('required') === null) continue;
1084                    if (!found && elems[i] !== elem) return true;
1085                    found = true;
1086                    elems[i].className = elems[i].className.replace(/ ?_has_error ?/g, '');
1087                    if (!elems[i].checked) {
1088                        no_error = false;
1089                        elems[i].className = elems[i].className + ' _has_error';
1090                        err.push("Checking %s is required".replace("%s", elems[i].value));
1091                    }
1092                }
1093                if (!no_error) {
1094                    tooltip = create_tooltip(elem, err.join('<br/>'));
1095                }
1096            } else if (elem.tagName == 'SELECT') {
1097                var selected = true;
1098                if (elem.multiple) {
1099                    selected = false;
1100                    for (var i = 0; i < elem.options.length; i++) {
1101                        if (elem.options[i].selected) {
1102                            selected = true;
1103                            break;
1104                        }
1105                    }
1106                } else {
1107                    for (var i = 0; i < elem.options.length; i++) {
1108                        if (elem.options[i].selected
1109                            && (!elem.options[i].value
1110                            || (elem.options[i].value.match(/\n/g)))
1111                        ) {
1112                            selected = false;
1113                        }
1114                    }
1115                }
1116                if (!selected) {
1117                    elem.className = elem.className + ' _has_error';
1118                    no_error = false;
1119                    tooltip = create_tooltip(elem, "Please select an option.");
1120                }
1121            } else if (value === undefined || value === null || value === '') {
1122                elem.className = elem.className + ' _has_error';
1123                no_error = false;
1124                tooltip = create_tooltip(elem, "This field is required.");
1125            }
1126        }
1127        if (no_error && elem.name == 'email') {
1128            if (!value.match(/^[\+_a-z0-9-'&=]+(\.[\+_a-z0-9-']+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,})$/i)) {
1129                elem.className = elem.className + ' _has_error';
1130                no_error = false;
1131                tooltip = create_tooltip(elem, "Enter a valid email address.");
1132            }
1133        }
1134        if (no_error && (elem.id == 'phone')) {
1135            if (elem.value.trim() && typeof iti != 'undefined' && !iti.isValidNumber()) {
1136                elem.className = elem.className + ' _has_error';
1137                no_error = false;
1138                tooltip = create_tooltip(elem, "Enter a valid phone number.");
1139            }
1140        }
1141        if (no_error && /date_field/.test(elem.className)) {
1142            if (!value.match(/^\d\d\d\d-\d\d-\d\d$/)) {
1143                elem.className = elem.className + ' _has_error';
1144                no_error = false;
1145                tooltip = create_tooltip(elem, "Enter a valid date.");
1146            }
1147        }
1148
1149        if (no_error && elem.name === 'sms_consent') {
1150            const showError = !!elem.attributes.required && !elem.checked;
1151            if (showError) {
1152                elem.className = elem.className + ' _has_error';
1153                no_error = false;
1154                tooltip = create_tooltip(elem, "Please check this box to continue");
1155            } else {
1156                elem.className = elem.className.replace(/ ?_has_error ?/g, '');
1157            }
1158        }
1159        tooltip ? resize_tooltip(tooltip) : false;
1160        if (!no_error && elem.hasAttribute('id')) {
1161            elem.setAttribute('aria-invalid', 'true');
1162            elem.setAttribute('aria-describedby', `${elem.id}-error`);
1163        }
1164        return no_error;
1165    };
1166    var needs_validate = function(el) {
1167        if(el.getAttribute('required') !== null){
1168            return true;
1169        }
1170        if((el.name === 'email' || el.name === 'phone' || el.id === 'sms_consent') && el.value !== ""){
1171            return true;
1172        }
1173
1174        return false;
1175    };
1176    var validate_email_or_phone_required = function() {
1177        var emailInput = form_to_submit.querySelector('input[name="email"]');
1178        var phoneInput = form_to_submit.querySelector('input[name="phone"]');
1179        if (!emailInput && !phoneInput) {
1180            return true;
1181        }
1182        var hasEmailValue = emailInput && emailInput.value.trim() !== '';
1183        var hasPhoneValue = phoneInput && phoneInput.value.trim() !== '';
1184        if (hasEmailValue || hasPhoneValue) {
1185            return true;
1186        }
1187        var errorField = emailInput || phoneInput;
1188        errorField.className = errorField.className.replace(/ ?_has_error ?/g, '') + ' _has_error';
1189        var tooltip = create_tooltip(
1190            errorField,
1191            "Forms must have an email field or a phone field present"
1192        );
1193        resize_tooltip(tooltip);
1194        errorField.setAttribute('aria-invalid', 'true');
1195        if (errorField.hasAttribute('id')) {
1196            errorField.setAttribute('aria-describedby', errorField.id + '-error');
1197        }
1198        return false;
1199    };
1200    var validate_form = function(e) {
1201        var err = form_to_submit.querySelector('._form_error'), no_error = true;
1202        if (!submitted) {
1203            submitted = true;
1204            for (var i = 0, len = allInputs.length; i < len; i++) {
1205                var input = allInputs[i];
1206                if (needs_validate(input)) {
1207                    if (input.type == 'text' || input.type == 'number' || input.type == 'time' || input.type == 'tel') {
1208                        addEvent(input, 'blur', function() {
1209                            this.value = this.value.trim();
1210                            validate_field(this, true);
1211                        });
1212                        addEvent(input, 'input', function() {
1213                            validate_field(this, true);
1214                        });
1215                    } else if (input.type == 'radio' || input.type == 'checkbox') {
1216                        (function(el) {
1217                            function getElementsArray(name){
1218                                const value =  form_to_submit.elements[name];
1219                                if (Array.isArray(value)){
1220                                    return value;
1221                                }
1222                                return [value];
1223                            }
1224                            var radios = getElementsArray(el.name);
1225                            for (var i = 0; i < radios.length; i++) {
1226                                addEvent(radios[i], 'change', function() {
1227                                    validate_field(el, true);
1228                                });
1229                            }
1230                        })(input);
1231                    } else if (input.tagName == 'SELECT') {
1232                        addEvent(input, 'change', function() {
1233                            validate_field(this, true);
1234                        });
1235                    } else if (input.type == 'textarea'){
1236                        addEvent(input, 'input', function() {
1237                            validate_field(this, true);
1238                        });
1239                    }
1240                }
1241            }
1242        }
1243        remove_tooltips();
1244        for (var i = 0, len = allInputs.length; i < len; i++) {
1245            var elem = allInputs[i];
1246            if (needs_validate(elem)) {
1247                if (elem.tagName.toLowerCase() !== "select") {
1248                    elem.value = elem.value.trim();
1249                }
1250                validate_field(elem) ? true : no_error = false;
1251            }
1252        }
1253        if (!validate_email_or_phone_required()) {
1254            no_error = false;
1255        }
1256        if (!no_error && e) {
1257            e.preventDefault();
1258        }
1259        if (!no_error) {
1260            const firstFocusableError = form_to_submit.querySelector('._has_error:not([disabled])');
1261            if (firstFocusableError && typeof firstFocusableError.focus === 'function') {
1262                firstFocusableError.focus();
1263            }
1264        }
1265        resize_tooltips();
1266        return no_error;
1267    };
1268    addEvent(window, 'resize', resize_tooltips);
1269    addEvent(window, 'scroll', resize_tooltips);
1270
1271    var _form_serialize = function(form){if(!form||form.nodeName!=="FORM"){return }var i,j,q=[];for(i=0;i<form.elements.length;i++){if(form.elements[i].name===""){continue}switch(form.elements[i].nodeName){case"INPUT":switch(form.elements[i].type){case"tel":q.push(form.elements[i].name+"="+encodeURIComponent(form.elements[i].previousSibling.querySelector('div.iti__selected-dial-code').innerText)+encodeURIComponent(" ")+encodeURIComponent(form.elements[i].value));break;case"text":case"number":case"date":case"time":case"hidden":case"password":case"button":case"reset":case"submit":q.push(form.elements[i].name+"="+encodeURIComponent(form.elements[i].value));break;case"checkbox":case"radio":if(form.elements[i].checked){q.push(form.elements[i].name+"="+encodeURIComponent(form.elements[i].value))}break;case"file":break}break;case"TEXTAREA":q.push(form.elements[i].name+"="+encodeURIComponent(form.elements[i].value));break;case"SELECT":switch(form.elements[i].type){case"select-one":q.push(form.elements[i].name+"="+encodeURIComponent(form.elements[i].value));break;case"select-multiple":for(j=0;j<form.elements[i].options.length;j++){if(form.elements[i].options[j].selected){q.push(form.elements[i].name+"="+encodeURIComponent(form.elements[i].options[j].value))}}break}break;case"BUTTON":switch(form.elements[i].type){case"reset":case"submit":case"button":q.push(form.elements[i].name+"="+encodeURIComponent(form.elements[i].value));break}break}}return q.join("&")};
1272
1273    const formSupportsPost = false;
1274    var form_submit = function(e) {
1275
1276        e.preventDefault();
1277        if(form_to_submit.querySelector('input[name="phone"]') && typeof iti != 'undefined') {
1278            form_to_submit.querySelector('input[name="phone"]').value = iti.getNumber();
1279        }
1280        if (validate_form()) {
1281            // use this trick to get the submit button & disable it using plain javascript
1282            var submitButton = e.target.querySelector('#_form_1_submit');
1283            submitButton.disabled = true;
1284            submitButton.classList.add('processing');
1285                    var serialized = _form_serialize(document.getElementById('_form_1_')).replace(/%0A/g, '\\n');
1286            var err = form_to_submit.querySelector('._form_error');
1287            err ? err.parentNode.removeChild(err) : false;
1288            async function submitForm() {
1289                var formData = new FormData();
1290                const searchParams = new URLSearchParams(serialized);
1291                searchParams.forEach((value, key) => {
1292                    if (key !== 'hideButton') {
1293                        formData.append(key, value);
1294                    }
1295                });
1296                let request = {
1297                    headers: {
1298                        "Accept": "application/json"
1299                    },
1300                    body: formData,
1301                    method: "POST"
1302                };
1303
1304                let pageUrlParams = new URLSearchParams(window.location.search);
1305                if (pageUrlParams.has('t')) {
1306                    request.headers.Authorization = 'Bearer ' + pageUrlParams.get('t');
1307                }
1308                const response = await fetch('https://flyingshapes.activehosted.com/proc.php?jsonp=true', request);
1309
1310                return response.json();
1311            }
1312            if (formSupportsPost) {
1313                submitForm().then((data) => {
1314                    eval(data.js);
1315                }).catch(() => {
1316                    _show_error("1", "Sorry, your submission failed. Please try again.");
1317                });
1318            } else {
1319                _load_script('https://flyingshapes.activehosted.com/proc.php?' + serialized + '&jsonp=true', null, true);
1320            }
1321        }
1322        return false;
1323    };
1324    addEvent(form_to_submit, 'submit', form_submit);
1325})();
1326
1327</script>
1327					</div>
1328					<p class="fs-lightbox__legal">Our <a href="https://www.flyingshapes.com/privacy/">Privacy Policy</a> applies.</p>
1329				</div>
1330			</div>
1331		</dialog>
1332				<dialog class="fs-lightbox" id="fs-lightbox-contact" data-lightbox-panel="contact" aria-labelledby="fs-lightbox-title-contact">
1333			<div class="fs-lightbox__panel">
1334				<button type="button" class="fs-lightbox__close" data-lightbox-close aria-label="Close">
1335					<span aria-hidden="true">&times;</span>
1336				</button>
1337				<div class="fs-lightbox__body">
1338					<h2 id="fs-lightbox-title-contact" class="fs-lightbox__title">How can we help?</h2>
1339											<p class="fs-lightbox__desc">You have questions regarding our software? We are looking forward to get in touch with you!</p>
1340										<div class="fs-lightbox__form" data-ac-form="contact" data-fs-form-slot="contact">
1341						<form method="POST" action="https://flyingshapes.activehosted.com/proc.php" id="_form_14_" class="_form _form_14 _inline-form  _dark" novalidate data-styles-version="5">
1342  <input type="hidden" name="u" value="14" />
1343  <input type="hidden" name="f" value="14" />
1344  <input type="hidden" name="s" />
1345  <input type="hidden" name="c" value="0" />
1346  <input type="hidden" name="m" value="0" />
1347  <input type="hidden" name="act" value="sub" />
1348  <input type="hidden" name="v" value="2" />
1349  <input type="hidden" name="or" value="d94998e4-e031-48a8-b23e-2b5a9d94695a" />
1350  <div class="_form-content">
1351    <div class="_form_element _x98082402 _full_width " >
1352      <label for="fullname" class="_form-label">
1353      </label>
1354      <div class="_field-wrapper">
1355        <input type="text" id="fullname" name="fullname" placeholder="How may we call you?" />
1356      </div>
1357    </div>
1358    <div class="_form_element _x43160217 _full_width " >
1359      <label for="phone" class="_form-label">
1360      </label>
1361      <div class="_field-wrapper">
1362        <input type="text" id="phone" name="phone" placeholder="Type your phone number" />
1363      </div>
1364    </div>
1365    <div class="_form_element _x05723213 _full_width " >
1366      <label for="email" class="_form-label">
1367      </label>
1368      <div class="_field-wrapper">
1369        <input type="text" id="email" name="email" placeholder="Type your email" required/>
1370      </div>
1371    </div>
1372    <div class="_form_element _x72819360 _full_width _clear" >
1373      <div class="_html-code">
1374      </div>
1375    </div>
1376    <div class="_form_element _x14647724 _full_width " >
1377      <label for="field[33]" class="_form-label">
1378      </label>
1379      <div class="_field-wrapper">
1380        <textarea id="field[33]" name="field[33]" placeholder="How can we help you?"  ></textarea>
1381      </div>
1382    </div>
1383    <div class="_button-wrapper _full_width">
1384      <button id="_form_14_submit" class="_submit" type="submit">
1385        send
1386      </button>
1387    </div>
1388    <div class="_clear-element">
1389    </div>
1390  </div>
1391  <div class="_form-thank-you" style="display:none;">
1392  </div>
1393  </form>
1393<script>
1394window.cfields = {"33":"request"};
1395window._show_thank_you = function(id, message, trackcmp_url, email) {
1396    var form = document.getElementById('_form_' + id + '_'), thank_you = form.querySelector('._form-thank-you');
1397    form.querySelector('._form-content').style.display = 'none';
1398    thank_you.innerHTML = message;
1399    thank_you.style.display = 'block';
1400    const vgoAlias = typeof visitorGlobalObjectAlias === 'undefined' ? 'vgo' : visitorGlobalObjectAlias;
1401    var visitorObject = window[vgoAlias];
1402    if (email && typeof visitorObject !== 'undefined') {
1403        visitorObject('setEmail', email);
1404        visitorObject('update');
1405    } else if (typeof(trackcmp_url) != 'undefined' && trackcmp_url) {
1406        // Site tracking URL to use after inline form submission.
1407        _load_script(trackcmp_url);
1408    }
1409    if (typeof window._form_callback !== 'undefined') window._form_callback(id);
1410    thank_you.setAttribute('tabindex', '-1');
1411    thank_you.focus();
1412};
1413window._show_unsubscribe = function(id, message, trackcmp_url, email) {
1414    var form = document.getElementById('_form_' + id + '_'), unsub = form.querySelector('._form-thank-you');
1415    var branding = form.querySelector('._form-branding');
1416    if (branding) {
1417        branding.style.display = 'none';
1418    }
1419    form.querySelector('._form-content').style.display = 'none';
1420    unsub.style.display = 'block';
1421    form.insertAdjacentHTML('afterend', message)
1422    const vgoAlias = typeof visitorGlobalObjectAlias === 'undefined' ? 'vgo' : visitorGlobalObjectAlias;
1423    var visitorObject = window[vgoAlias];
1424    if (email && typeof visitorObject !== 'undefined') {
1425        visitorObject('setEmail', email);
1426        visitorObject('update');
1427    } else if (typeof(trackcmp_url) != 'undefined' && trackcmp_url) {
1428        // Site tracking URL to use after inline form submission.
1429        _load_script(trackcmp_url);
1430    }
1431    if (typeof window._form_callback !== 'undefined') window._form_callback(id);
1432};
1433window._show_error = function(id, message, html) {
1434    var form = document.getElementById('_form_' + id + '_'),
1435        err = document.createElement('div'),
1436        button = form.querySelector('button[type="submit"]'),
1437        old_error = form.querySelector('._form_error');
1438    if (old_error) old_error.parentNode.removeChild(old_error);
1439    err.innerHTML = message;
1440    err.className = '_error-inner _form_error _no_arrow';
1441    var wrapper = document.createElement('div');
1442    wrapper.className = '_form-inner _show_be_error';
1443    wrapper.appendChild(err);
1444    button.parentNode.insertBefore(wrapper, button);
1445    var submitButton = form.querySelector('[id^="_form"][id$="_submit"]');
1446    submitButton.disabled = false;
1447    submitButton.classList.remove('processing');
1448    if (html) {
1449        var div = document.createElement('div');
1450        div.className = '_error-html';
1451        div.innerHTML = html;
1452        err.appendChild(div);
1453    }
1454};
1455window._show_pc_confirmation = function(id, header, detail, show, email) {
1456    var form = document.getElementById('_form_' + id + '_'), pc_confirmation = form.querySelector('._form-pc-confirmation');
1457    if (pc_confirmation.style.display === 'none') {
1458        form.querySelector('._form-content').style.display = 'none';
1459        pc_confirmation.innerHTML = "<div class='_form-title'>" + header + "</div>" + "<p>" + detail + "</p>" +
1460        "<button class='_submit' id='hideButton'>Manage preferences</button>";
1461        pc_confirmation.style.display = 'block';
1462        var mp = document.querySelector('input[name="mp"]');
1463        mp.value = '0';
1464    } else {
1465        form.querySelector('._form-content').style.display = 'inline';
1466        pc_confirmation.style.display = 'none';
1467    }
1468
1469    var hideButton = document.getElementById('hideButton');
1470    // Add event listener to the button
1471    hideButton.addEventListener('click', function() {
1472        var submitButton = document.querySelector('#_form_14_submit');
1473        submitButton.disabled = false;
1474        submitButton.classList.remove('processing');
1475        var mp = document.querySelector('input[name="mp"]');
1476        mp.value = '1';
1477        const cacheBuster = new URL(window.location.href);
1478        cacheBuster.searchParams.set('v', new Date().getTime());
1479        window.location.href = cacheBuster.toString();
1480    });
1481
1482    const vgoAlias = typeof visitorGlobalObjectAlias === 'undefined' ? 'vgo' : visitorGlobalObjectAlias;
1483    var visitorObject = window[vgoAlias];
1484    if (email && typeof visitorObject !== 'undefined') {
1485        visitorObject('setEmail', email);
1486        visitorObject('update');
1487    } else if (typeof(trackcmp_url) != 'undefined' && trackcmp_url) {
1488        // Site tracking URL to use after inline form submission.
1489        _load_script(trackcmp_url);
1490    }
1491    if (typeof window._form_callback !== 'undefined') window._form_callback(id);
1492};
1493window._load_script = function(url, callback, isSubmit) {
1494    var head = document.querySelector('head'), script = document.createElement('script'), r = false;
1495    var submitButton = document.querySelector('#_form_14_submit');
1496    script.charset = 'utf-8';
1497    script.src = url;
1498    if (callback) {
1499        script.onload = script.onreadystatechange = function() {
1500            if (!r && (!this.readyState || this.readyState == 'complete')) {
1501                r = true;
1502                callback();
1503            }
1504        };
1505    }
1506    script.onerror = function() {
1507        if (isSubmit) {
1508            if (script.src.length > 10000) {
1509                _show_error("14", "Sorry, your submission failed. Please shorten your responses and try again.");
1510            } else {
1511                _show_error("14", "Sorry, your submission failed. Please try again.");
1512            }
1513            submitButton.disabled = false;
1514            submitButton.classList.remove('processing');
1515        }
1516    }
1517
1518    head.appendChild(script);
1519};
1520(function() {
1521    var iti;
1522    if (window.location.search.search("excludeform") !== -1) return false;
1523    var getCookie = function(name) {
1524        var match = document.cookie.match(new RegExp('(^|; )' + name + '=([^;]+)'));
1525        return match ? match[2] : localStorage.getItem(name);
1526    }
1527    var setCookie = function(name, value) {
1528        var now = new Date();
1529        var time = now.getTime();
1530        var expireTime = time + 1000 * 60 * 60 * 24 * 365;
1531        now.setTime(expireTime);
1532        document.cookie = name + '=' + value + '; expires=' + now + ';path=/; Secure; SameSite=Lax;';
1533        localStorage.setItem(name, value);
1534    }
1535    var addEvent = function(element, event, func) {
1536        if (element.addEventListener) {
1537            element.addEventListener(event, func);
1538        } else {
1539            var oldFunc = element['on' + event];
1540            element['on' + event] = function() {
1541                oldFunc.apply(this, arguments);
1542                func.apply(this, arguments);
1543            };
1544        }
1545    }
1546    var _removed = false;
1547        var form_to_submit = document.getElementById('_form_14_');
1548    var allInputs = form_to_submit.querySelectorAll('input, select, textarea'), tooltips = [], submitted = false;
1549
1550    var getUrlParam = function(name) {
1551        if (name.toLowerCase() !== 'email') {
1552            var params = new URLSearchParams(window.location.search);
1553            return params.get(name) || false;
1554        }
1555        // email is a special case because a plus is valid in the email address
1556        var qString = window.location.search;
1557        if (!qString) {
1558            return false;
1559        }
1560        var parameters = qString.substr(1).split('&');
1561        for (var i = 0; i < parameters.length; i++) {
1562            var parameter = parameters[i].split('=');
1563            if (parameter[0].toLowerCase() === 'email') {
1564                return parameter[1] === undefined ? true : decodeURIComponent(parameter[1]);
1565            }
1566        }
1567        return false;
1568    };
1569
1570    var acctDateFormat = "%B-%d-%Y";
1571    var getNormalizedDate = function(date, acctFormat) {
1572        var decodedDate = decodeURIComponent(date);
1573        if (acctFormat && acctFormat.match(/(%d|%e).*%m/gi) !== null) {
1574            return decodedDate.replace(/(\d{2}).*(\d{2}).*(\d{4})/g, '$3-$2-$1');
1575        } else if (Date.parse(decodedDate)) {
1576            var dateObj = new Date(decodedDate);
1577            var year = dateObj.getFullYear();
1578            var month = dateObj.getMonth() + 1;
1579            var day = dateObj.getDate();
1580            return `${year}-${month < 10 ? `0${month}` : month}-${day < 10 ? `0${day}` : day}`;
1581        }
1582        return false;
1583    };
1584
1585    var getNormalizedTime = function(time) {
1586        var hour, minutes;
1587        var decodedTime = decodeURIComponent(time);
1588        var timeParts = Array.from(decodedTime.matchAll(/(\d{1,2}):(\d{1,2})\W*([AaPp][Mm])?/gm))[0];
1589        if (timeParts[3]) { // 12 hour format
1590            var isPM = timeParts[3].toLowerCase() === 'pm';
1591            if (isPM) {
1592                hour = parseInt(timeParts[1]) === 12 ? '12' : `${parseInt(timeParts[1]) + 12}`;
1593            } else {
1594                hour = parseInt(timeParts[1]) === 12 ? '0' : timeParts[1];
1595            }
1596        } else { // 24 hour format
1597            hour = timeParts[1];
1598        }
1599        var normalizedHour = parseInt(hour) < 10 ? `0${parseInt(hour)}` : hour;
1600        var minutes = timeParts[2];
1601        return `${normalizedHour}:${minutes}`;
1602    };
1603
1604    for (var i = 0; i < allInputs.length; i++) {
1605        var regexStr = "field\\[(\\d+)\\]";
1606        var results = new RegExp(regexStr).exec(allInputs[i].name);
1607        if (results != undefined) {
1608            allInputs[i].dataset.name = allInputs[i].name.match(/\[time\]$/)
1609                ? `${window.cfields[results[1]]}_time`
1610                : window.cfields[results[1]];
1611        } else {
1612            allInputs[i].dataset.name = allInputs[i].name;
1613        }
1614        var fieldVal = getUrlParam(allInputs[i].dataset.name);
1615
1616        if (fieldVal) {
1617            if (allInputs[i].dataset.autofill === "false") {
1618                continue;
1619            }
1620            if (allInputs[i].type == "radio" || allInputs[i].type == "checkbox") {
1621                if (allInputs[i].value == fieldVal) {
1622                    allInputs[i].checked = true;
1623                }
1624            } else if (allInputs[i].type == "date") {
1625                allInputs[i].value = getNormalizedDate(fieldVal, acctDateFormat);
1626            } else if (allInputs[i].type == "time") {
1627                allInputs[i].value = getNormalizedTime(fieldVal);
1628            } else {
1629                allInputs[i].value = fieldVal;
1630            }
1631        }
1632    }
1633
1634    var remove_tooltips = function() {
1635        for (var i = 0; i < tooltips.length; i++) {
1636            tooltips[i].tip.parentNode.removeChild(tooltips[i].tip);
1637        }
1638        tooltips = [];
1639    };
1640    var remove_tooltip = function(elem) {
1641        for (var i = 0; i < tooltips.length; i++) {
1642            if (tooltips[i].elem === elem) {
1643                tooltips[i].tip.parentNode.removeChild(tooltips[i].tip);
1644                tooltips.splice(i, 1);
1645                return;
1646            }
1647        }
1648    };
1649    var create_tooltip = function(elem, text) {
1650        var tooltip = document.createElement('div'),
1651            arrow = document.createElement('div'),
1652            inner = document.createElement('div'), new_tooltip = {};
1653        tooltip.id = `${elem.id}-error`;
1654        tooltip.setAttribute('role', 'alert')
1655        if (elem.type != 'radio' && (elem.type != 'checkbox' || elem.name === 'sms_consent')) {
1656            tooltip.className = '_error';
1657            arrow.className = '_error-arrow';
1658            inner.className = '_error-inner';
1659            inner.innerHTML = text;
1660            tooltip.appendChild(arrow);
1661            tooltip.appendChild(inner);
1662            elem.parentNode.appendChild(tooltip);
1663        } else {
1664            tooltip.className = '_error-inner _no_arrow';
1665            tooltip.innerHTML = text;
1666            elem.parentNode.insertBefore(tooltip, elem);
1667            new_tooltip.no_arrow = true;
1668        }
1669        new_tooltip.tip = tooltip;
1670        new_tooltip.elem = elem;
1671        tooltips.push(new_tooltip);
1672        return new_tooltip;
1673    };
1674    var resize_tooltip = function(tooltip) {
1675        var rect = tooltip.elem.getBoundingClientRect();
1676        var doc = document.documentElement,
1677            scrollPosition = rect.top - ((window.pageYOffset || doc.scrollTop)  - (doc.clientTop || 0));
1678        if (scrollPosition < 40) {
1679            tooltip.tip.className = tooltip.tip.className.replace(/ ?(_above|_below) ?/g, '') + ' _below';
1680        } else {
1681            tooltip.tip.className = tooltip.tip.className.replace(/ ?(_above|_below) ?/g, '') + ' _above';
1682        }
1683    };
1684    var resize_tooltips = function() {
1685        if (_removed) return;
1686        for (var i = 0; i < tooltips.length; i++) {
1687            if (!tooltips[i].no_arrow) resize_tooltip(tooltips[i]);
1688        }
1689    };
1690    var validate_field = function(elem, remove) {
1691        var tooltip = null, value = elem.value, no_error = true;
1692        remove ? remove_tooltip(elem) : false;
1693        elem.removeAttribute('aria-invalid');
1694        elem.removeAttribute('aria-describedby');
1695        if (elem.type != 'checkbox') elem.className = elem.className.replace(/ ?_has_error ?/g, '');
1696        if (elem.getAttribute('required') !== null) {
1697            if (elem.type == 'radio' || (elem.type == 'checkbox' && /any/.test(elem.className))) {
1698                var elems = form_to_submit.elements[elem.name];
1699                if (!(elems instanceof NodeList || elems instanceof HTMLCollection) || elems.length <= 1) {
1700                    no_error = elem.checked;
1701                }
1702                else {
1703                    no_error = false;
1704                    for (var i = 0; i < elems.length; i++) {
1705                        if (elems[i].checked) no_error = true;
1706                    }
1707                }
1708                if (!no_error) {
1709                    tooltip = create_tooltip(elem, "Please select an option.");
1710                }
1711            } else if (elem.type =='checkbox') {
1712                var elems = form_to_submit.elements[elem.name], found = false, err = [];
1713                no_error = true;
1714                for (var i = 0; i < elems.length; i++) {
1715                    if (elems[i].getAttribute('required') === null) continue;
1716                    if (!found && elems[i] !== elem) return true;
1717                    found = true;
1718                    elems[i].className = elems[i].className.replace(/ ?_has_error ?/g, '');
1719                    if (!elems[i].checked) {
1720                        no_error = false;
1721                        elems[i].className = elems[i].className + ' _has_error';
1722                        err.push("Checking %s is required".replace("%s", elems[i].value));
1723                    }
1724                }
1725                if (!no_error) {
1726                    tooltip = create_tooltip(elem, err.join('<br/>'));
1727                }
1728            } else if (elem.tagName == 'SELECT') {
1729                var selected = true;
1730                if (elem.multiple) {
1731                    selected = false;
1732                    for (var i = 0; i < elem.options.length; i++) {
1733                        if (elem.options[i].selected) {
1734                            selected = true;
1735                            break;
1736                        }
1737                    }
1738                } else {
1739                    for (var i = 0; i < elem.options.length; i++) {
1740                        if (elem.options[i].selected
1741                            && (!elem.options[i].value
1742                            || (elem.options[i].value.match(/\n/g)))
1743                        ) {
1744                            selected = false;
1745                        }
1746                    }
1747                }
1748                if (!selected) {
1749                    elem.className = elem.className + ' _has_error';
1750                    no_error = false;
1751                    tooltip = create_tooltip(elem, "Please select an option.");
1752                }
1753            } else if (value === undefined || value === null || value === '') {
1754                elem.className = elem.className + ' _has_error';
1755                no_error = false;
1756                tooltip = create_tooltip(elem, "This field is required.");
1757            }
1758        }
1759        if (no_error && elem.name == 'email') {
1760            if (!value.match(/^[\+_a-z0-9-'&=]+(\.[\+_a-z0-9-']+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,})$/i)) {
1761                elem.className = elem.className + ' _has_error';
1762                no_error = false;
1763                tooltip = create_tooltip(elem, "Enter a valid email address.");
1764            }
1765        }
1766        if (no_error && (elem.id == 'phone')) {
1767            if (elem.value.trim() && typeof iti != 'undefined' && !iti.isValidNumber()) {
1768                elem.className = elem.className + ' _has_error';
1769                no_error = false;
1770                tooltip = create_tooltip(elem, "Enter a valid phone number.");
1771            }
1772        }
1773        if (no_error && /date_field/.test(elem.className)) {
1774            if (!value.match(/^\d\d\d\d-\d\d-\d\d$/)) {
1775                elem.className = elem.className + ' _has_error';
1776                no_error = false;
1777                tooltip = create_tooltip(elem, "Enter a valid date.");
1778            }
1779        }
1780
1781        if (no_error && elem.name === 'sms_consent') {
1782            const showError = !!elem.attributes.required && !elem.checked;
1783            if (showError) {
1784                elem.className = elem.className + ' _has_error';
1785                no_error = false;
1786                tooltip = create_tooltip(elem, "Please check this box to continue");
1787            } else {
1788                elem.className = elem.className.replace(/ ?_has_error ?/g, '');
1789            }
1790        }
1791        tooltip ? resize_tooltip(tooltip) : false;
1792        if (!no_error && elem.hasAttribute('id')) {
1793            elem.setAttribute('aria-invalid', 'true');
1794            elem.setAttribute('aria-describedby', `${elem.id}-error`);
1795        }
1796        return no_error;
1797    };
1798    var needs_validate = function(el) {
1799        if(el.getAttribute('required') !== null){
1800            return true;
1801        }
1802        if((el.name === 'email' || el.name === 'phone' || el.id === 'sms_consent') && el.value !== ""){
1803            return true;
1804        }
1805
1806        return false;
1807    };
1808    var validate_email_or_phone_required = function() {
1809        var emailInput = form_to_submit.querySelector('input[name="email"]');
1810        var phoneInput = form_to_submit.querySelector('input[name="phone"]');
1811        if (!emailInput && !phoneInput) {
1812            return true;
1813        }
1814        var hasEmailValue = emailInput && emailInput.value.trim() !== '';
1815        var hasPhoneValue = phoneInput && phoneInput.value.trim() !== '';
1816        if (hasEmailValue || hasPhoneValue) {
1817            return true;
1818        }
1819        var errorField = emailInput || phoneInput;
1820        errorField.className = errorField.className.replace(/ ?_has_error ?/g, '') + ' _has_error';
1821        var tooltip = create_tooltip(
1822            errorField,
1823            "Forms must have an email field or a phone field present"
1824        );
1825        resize_tooltip(tooltip);
1826        errorField.setAttribute('aria-invalid', 'true');
1827        if (errorField.hasAttribute('id')) {
1828            errorField.setAttribute('aria-describedby', errorField.id + '-error');
1829        }
1830        return false;
1831    };
1832    var validate_form = function(e) {
1833        var err = form_to_submit.querySelector('._form_error'), no_error = true;
1834        if (!submitted) {
1835            submitted = true;
1836            for (var i = 0, len = allInputs.length; i < len; i++) {
1837                var input = allInputs[i];
1838                if (needs_validate(input)) {
1839                    if (input.type == 'text' || input.type == 'number' || input.type == 'time' || input.type == 'tel') {
1840                        addEvent(input, 'blur', function() {
1841                            this.value = this.value.trim();
1842                            validate_field(this, true);
1843                        });
1844                        addEvent(input, 'input', function() {
1845                            validate_field(this, true);
1846                        });
1847                    } else if (input.type == 'radio' || input.type == 'checkbox') {
1848                        (function(el) {
1849                            function getElementsArray(name){
1850                                const value =  form_to_submit.elements[name];
1851                                if (Array.isArray(value)){
1852                                    return value;
1853                                }
1854                                return [value];
1855                            }
1856                            var radios = getElementsArray(el.name);
1857                            for (var i = 0; i < radios.length; i++) {
1858                                addEvent(radios[i], 'change', function() {
1859                                    validate_field(el, true);
1860                                });
1861                            }
1862                        })(input);
1863                    } else if (input.tagName == 'SELECT') {
1864                        addEvent(input, 'change', function() {
1865                            validate_field(this, true);
1866                        });
1867                    } else if (input.type == 'textarea'){
1868                        addEvent(input, 'input', function() {
1869                            validate_field(this, true);
1870                        });
1871                    }
1872                }
1873            }
1874        }
1875        remove_tooltips();
1876        for (var i = 0, len = allInputs.length; i < len; i++) {
1877            var elem = allInputs[i];
1878            if (needs_validate(elem)) {
1879                if (elem.tagName.toLowerCase() !== "select") {
1880                    elem.value = elem.value.trim();
1881                }
1882                validate_field(elem) ? true : no_error = false;
1883            }
1884        }
1885        if (!validate_email_or_phone_required()) {
1886            no_error = false;
1887        }
1888        if (!no_error && e) {
1889            e.preventDefault();
1890        }
1891        if (!no_error) {
1892            const firstFocusableError = form_to_submit.querySelector('._has_error:not([disabled])');
1893            if (firstFocusableError && typeof firstFocusableError.focus === 'function') {
1894                firstFocusableError.focus();
1895            }
1896        }
1897        resize_tooltips();
1898        return no_error;
1899    };
1900    addEvent(window, 'resize', resize_tooltips);
1901    addEvent(window, 'scroll', resize_tooltips);
1902    var initializePhoneInput = function(inputPhone) {
1903
1904        const stylesheetLink = document.createElement('link');
1905        stylesheetLink.rel = 'stylesheet';
1906        stylesheetLink.href = 'https://cdn.jsdelivr.net/npm/[email protected]/build/css/intlTelInput.css';
1907        document.head.appendChild(stylesheetLink);
1908
1909        window._load_script('https://cdn.jsdelivr.net/npm/[email protected]/build/js/intlTelInput.min.js', function() {
1910            inputPhone.setAttribute("name", "phone-iti");
1911            iti = intlTelInput(inputPhone, {
1912                loadUtils: () => import('https://cdn.jsdelivr.net/npm/[email protected]/build/js/utils.js'),
1913                hiddenInput: (telInputName) => ({
1914                    phone: 'phone'
1915                }),
1916                separateDialCode: true,
1917                autoPlaceholder: 'aggressive',
1918                initialCountry: "us",
1919            });
1920        }, false);
1921    }
1922    var inputPhone = form_to_submit.querySelector('input[name="phone"]');
1923    if(inputPhone) {
1924        initializePhoneInput(inputPhone);
1925    }
1926
1927    var _form_serialize = function(form){if(!form||form.nodeName!=="FORM"){return }var i,j,q=[];for(i=0;i<form.elements.length;i++){if(form.elements[i].name===""){continue}switch(form.elements[i].nodeName){case"INPUT":switch(form.elements[i].type){case"tel":q.push(form.elements[i].name+"="+encodeURIComponent(form.elements[i].previousSibling.querySelector('div.iti__selected-dial-code').innerText)+encodeURIComponent(" ")+encodeURIComponent(form.elements[i].value));break;case"text":case"number":case"date":case"time":case"hidden":case"password":case"button":case"reset":case"submit":q.push(form.elements[i].name+"="+encodeURIComponent(form.elements[i].value));break;case"checkbox":case"radio":if(form.elements[i].checked){q.push(form.elements[i].name+"="+encodeURIComponent(form.elements[i].value))}break;case"file":break}break;case"TEXTAREA":q.push(form.elements[i].name+"="+encodeURIComponent(form.elements[i].value));break;case"SELECT":switch(form.elements[i].type){case"select-one":q.push(form.elements[i].name+"="+encodeURIComponent(form.elements[i].value));break;case"select-multiple":for(j=0;j<form.elements[i].options.length;j++){if(form.elements[i].options[j].selected){q.push(form.elements[i].name+"="+encodeURIComponent(form.elements[i].options[j].value))}}break}break;case"BUTTON":switch(form.elements[i].type){case"reset":case"submit":case"button":q.push(form.elements[i].name+"="+encodeURIComponent(form.elements[i].value));break}break}}return q.join("&")};
1928
1929    const formSupportsPost = false;
1930    var form_submit = function(e) {
1931
1932        e.preventDefault();
1933        if(form_to_submit.querySelector('input[name="phone"]') && typeof iti != 'undefined') {
1934            form_to_submit.querySelector('input[name="phone"]').value = iti.getNumber();
1935        }
1936        if (validate_form()) {
1937            // use this trick to get the submit button & disable it using plain javascript
1938            var submitButton = e.target.querySelector('#_form_14_submit');
1939            submitButton.disabled = true;
1940            submitButton.classList.add('processing');
1941                    var serialized = _form_serialize(document.getElementById('_form_14_')).replace(/%0A/g, '\\n');
1942            var err = form_to_submit.querySelector('._form_error');
1943            err ? err.parentNode.removeChild(err) : false;
1944            async function submitForm() {
1945                var formData = new FormData();
1946                const searchParams = new URLSearchParams(serialized);
1947                searchParams.forEach((value, key) => {
1948                    if (key !== 'hideButton') {
1949                        formData.append(key, value);
1950                    }
1951                });
1952                let request = {
1953                    headers: {
1954                        "Accept": "application/json"
1955                    },
1956                    body: formData,
1957                    method: "POST"
1958                };
1959
1960                let pageUrlParams = new URLSearchParams(window.location.search);
1961                if (pageUrlParams.has('t')) {
1962                    request.headers.Authorization = 'Bearer ' + pageUrlParams.get('t');
1963                }
1964                const response = await fetch('https://flyingshapes.activehosted.com/proc.php?jsonp=true', request);
1965
1966                return response.json();
1967            }
1968            if (formSupportsPost) {
1969                submitForm().then((data) => {
1970                    eval(data.js);
1971                }).catch(() => {
1972                    _show_error("14", "Sorry, your submission failed. Please try again.");
1973                });
1974            } else {
1975                _load_script('https://flyingshapes.activehosted.com/proc.php?' + serialized + '&jsonp=true', null, true);
1976            }
1977        }
1978        return false;
1979    };
1980    addEvent(form_to_submit, 'submit', form_submit);
1981})();
1982
1983</script>
1983					</div>
1984					<p class="fs-lightbox__legal">Our <a href="https://www.flyingshapes.com/privacy/">Privacy Policy</a> applies.</p>
1985				</div>
1986			</div>
1987		</dialog>
1988				<dialog class="fs-lightbox" id="fs-lightbox-trial" data-lightbox-panel="trial" aria-labelledby="fs-lightbox-title-trial">
1989			<div class="fs-lightbox__panel">
1990				<button type="button" class="fs-lightbox__close" data-lightbox-close aria-label="Close">
1991					<span aria-hidden="true">&times;</span>
1992				</button>
1993				<div class="fs-lightbox__body">
1994					<h2 id="fs-lightbox-title-trial" class="fs-lightbox__title">Request Trial Version</h2>
1995											<p class="fs-lightbox__desc">Take full advantage of our free trial and discover a completely new way of turning your design ideas into 3D models.</p>
1996										<div class="fs-lightbox__form" data-ac-form="trial" data-fs-form-slot="trial">
1997						<form method="POST" action="https://flyingshapes.activehosted.com/proc.php" id="_form_28_" class="_form _form_28 _inline-form  _dark" novalidate data-styles-version="5">
1998  <input type="hidden" name="u" value="28" />
1999  <input type="hidden" name="f" value="28" />
2000  <input type="hidden" name="s" />
2001  <input type="hidden" name="c" value="0" />
2002  <input type="hidden" name="m" value="0" />
2003  <input type="hidden" name="act" value="sub" />
2004  <input type="hidden" name="v" value="2" />
2005  <input type="hidden" name="or" value="bf58d73a-8ed6-4c48-a28b-f0ddb818b734" />
2006  <div class="_form-content">
2007    <div class="_form_element _x98082402 _full_width " >
2008      <label for="fullname" class="_form-label">
2009      </label>
2010      <div class="_field-wrapper">
2011        <input type="text" id="fullname" name="fullname" placeholder="How may we call you?" required/>
2012      </div>
2013    </div>
2014    <div class="_form_element _x05723213 _full_width " >
2015      <label for="email" class="_form-label">
2016      </label>
2017      <div class="_field-wrapper">
2018        <input type="text" id="email" name="email" placeholder="" required/>
2019      </div>
2020    </div>
2021    <div class="_form_element _x75804092 _full_width " >
2022      <label for="phone" class="_form-label">
2023      </label>
2024      <div class="_field-wrapper">
2025        <input type="text" id="phone" name="phone" placeholder="Type your phone number" />
2026      </div>
2027    </div>
2028    <div class="_form_element _x81693921 _full_width " >
2029      <fieldset class="_form-fieldset">
2030        <div class="_row">
2031          <legend for="field[34][]" class="_form-label">
2032          </legend>
2033        </div>
2034        <input data-autofill="false" type="hidden" id="field[34][]" name="field[34][]" value="~|">
2035        <div class="_row _checkbox-radio">
2036          <input id="field_34Subscribe to our Newsletter" type="checkbox" name="field[34][]"
2037          value="Subscribe to our Newsletter"                                                                                                                 >
2038          <span>
2039            <label for="field_34Subscribe to our Newsletter">
2040              Subscribe to our Newsletter
2041            </label>
2042          </span>
2043        </div>
2044      </fieldset>
2045    </div>
2046    <div class="_button-wrapper _full_width">
2047      <button id="_form_28_submit" class="_submit" type="submit">
2048        send
2049      </button>
2050    </div>
2051    <div class="_clear-element">
2052    </div>
2053  </div>
2054  <div class="_form-thank-you" style="display:none;">
2055  </div>
2056</form>
2056<script>
2057window.cfields = {"34":"requestnewsletter"};
2058window._show_thank_you = function(id, message, trackcmp_url, email) {
2059    var form = document.getElementById('_form_' + id + '_'), thank_you = form.querySelector('._form-thank-you');
2060    form.querySelector('._form-content').style.display = 'none';
2061    thank_you.innerHTML = message;
2062    thank_you.style.display = 'block';
2063    const vgoAlias = typeof visitorGlobalObjectAlias === 'undefined' ? 'vgo' : visitorGlobalObjectAlias;
2064    var visitorObject = window[vgoAlias];
2065    if (email && typeof visitorObject !== 'undefined') {
2066        visitorObject('setEmail', email);
2067        visitorObject('update');
2068    } else if (typeof(trackcmp_url) != 'undefined' && trackcmp_url) {
2069        // Site tracking URL to use after inline form submission.
2070        _load_script(trackcmp_url);
2071    }
2072    if (typeof window._form_callback !== 'undefined') window._form_callback(id);
2073    thank_you.setAttribute('tabindex', '-1');
2074    thank_you.focus();
2075};
2076window._show_unsubscribe = function(id, message, trackcmp_url, email) {
2077    var form = document.getElementById('_form_' + id + '_'), unsub = form.querySelector('._form-thank-you');
2078    var branding = form.querySelector('._form-branding');
2079    if (branding) {
2080        branding.style.display = 'none';
2081    }
2082    form.querySelector('._form-content').style.display = 'none';
2083    unsub.style.display = 'block';
2084    form.insertAdjacentHTML('afterend', message)
2085    const vgoAlias = typeof visitorGlobalObjectAlias === 'undefined' ? 'vgo' : visitorGlobalObjectAlias;
2086    var visitorObject = window[vgoAlias];
2087    if (email && typeof visitorObject !== 'undefined') {
2088        visitorObject('setEmail', email);
2089        visitorObject('update');
2090    } else if (typeof(trackcmp_url) != 'undefined' && trackcmp_url) {
2091        // Site tracking URL to use after inline form submission.
2092        _load_script(trackcmp_url);
2093    }
2094    if (typeof window._form_callback !== 'undefined') window._form_callback(id);
2095};
2096window._show_error = function(id, message, html) {
2097    var form = document.getElementById('_form_' + id + '_'),
2098        err = document.createElement('div'),
2099        button = form.querySelector('button[type="submit"]'),
2100        old_error = form.querySelector('._form_error');
2101    if (old_error) old_error.parentNode.removeChild(old_error);
2102    err.innerHTML = message;
2103    err.className = '_error-inner _form_error _no_arrow';
2104    var wrapper = document.createElement('div');
2105    wrapper.className = '_form-inner _show_be_error';
2106    wrapper.appendChild(err);
2107    button.parentNode.insertBefore(wrapper, button);
2108    var submitButton = form.querySelector('[id^="_form"][id$="_submit"]');
2109    submitButton.disabled = false;
2110    submitButton.classList.remove('processing');
2111    if (html) {
2112        var div = document.createElement('div');
2113        div.className = '_error-html';
2114        div.innerHTML = html;
2115        err.appendChild(div);
2116    }
2117};
2118window._show_pc_confirmation = function(id, header, detail, show, email) {
2119    var form = document.getElementById('_form_' + id + '_'), pc_confirmation = form.querySelector('._form-pc-confirmation');
2120    if (pc_confirmation.style.display === 'none') {
2121        form.querySelector('._form-content').style.display = 'none';
2122        pc_confirmation.innerHTML = "<div class='_form-title'>" + header + "</div>" + "<p>" + detail + "</p>" +
2123        "<button class='_submit' id='hideButton'>Manage preferences</button>";
2124        pc_confirmation.style.display = 'block';
2125        var mp = document.querySelector('input[name="mp"]');
2126        mp.value = '0';
2127    } else {
2128        form.querySelector('._form-content').style.display = 'inline';
2129        pc_confirmation.style.display = 'none';
2130    }
2131
2132    var hideButton = document.getElementById('hideButton');
2133    // Add event listener to the button
2134    hideButton.addEventListener('click', function() {
2135        var submitButton = document.querySelector('#_form_28_submit');
2136        submitButton.disabled = false;
2137        submitButton.classList.remove('processing');
2138        var mp = document.querySelector('input[name="mp"]');
2139        mp.value = '1';
2140        const cacheBuster = new URL(window.location.href);
2141        cacheBuster.searchParams.set('v', new Date().getTime());
2142        window.location.href = cacheBuster.toString();
2143    });
2144
2145    const vgoAlias = typeof visitorGlobalObjectAlias === 'undefined' ? 'vgo' : visitorGlobalObjectAlias;
2146    var visitorObject = window[vgoAlias];
2147    if (email && typeof visitorObject !== 'undefined') {
2148        visitorObject('setEmail', email);
2149        visitorObject('update');
2150    } else if (typeof(trackcmp_url) != 'undefined' && trackcmp_url) {
2151        // Site tracking URL to use after inline form submission.
2152        _load_script(trackcmp_url);
2153    }
2154    if (typeof window._form_callback !== 'undefined') window._form_callback(id);
2155};
2156window._load_script = function(url, callback, isSubmit) {
2157    var head = document.querySelector('head'), script = document.createElement('script'), r = false;
2158    var submitButton = document.querySelector('#_form_28_submit');
2159    script.charset = 'utf-8';
2160    script.src = url;
2161    if (callback) {
2162        script.onload = script.onreadystatechange = function() {
2163            if (!r && (!this.readyState || this.readyState == 'complete')) {
2164                r = true;
2165                callback();
2166            }
2167        };
2168    }
2169    script.onerror = function() {
2170        if (isSubmit) {
2171            if (script.src.length > 10000) {
2172                _show_error("28", "Sorry, your submission failed. Please shorten your responses and try again.");
2173            } else {
2174                _show_error("28", "Sorry, your submission failed. Please try again.");
2175            }
2176            submitButton.disabled = false;
2177            submitButton.classList.remove('processing');
2178        }
2179    }
2180
2181    head.appendChild(script);
2182};
2183(function() {
2184    var iti;
2185    if (window.location.search.search("excludeform") !== -1) return false;
2186    var getCookie = function(name) {
2187        var match = document.cookie.match(new RegExp('(^|; )' + name + '=([^;]+)'));
2188        return match ? match[2] : localStorage.getItem(name);
2189    }
2190    var setCookie = function(name, value) {
2191        var now = new Date();
2192        var time = now.getTime();
2193        var expireTime = time + 1000 * 60 * 60 * 24 * 365;
2194        now.setTime(expireTime);
2195        document.cookie = name + '=' + value + '; expires=' + now + ';path=/; Secure; SameSite=Lax;';
2196        localStorage.setItem(name, value);
2197    }
2198    var addEvent = function(element, event, func) {
2199        if (element.addEventListener) {
2200            element.addEventListener(event, func);
2201        } else {
2202            var oldFunc = element['on' + event];
2203            element['on' + event] = function() {
2204                oldFunc.apply(this, arguments);
2205                func.apply(this, arguments);
2206            };
2207        }
2208    }
2209    var _removed = false;
2210        var form_to_submit = document.getElementById('_form_28_');
2211    var allInputs = form_to_submit.querySelectorAll('input, select, textarea'), tooltips = [], submitted = false;
2212
2213    var getUrlParam = function(name) {
2214        if (name.toLowerCase() !== 'email') {
2215            var params = new URLSearchParams(window.location.search);
2216            return params.get(name) || false;
2217        }
2218        // email is a special case because a plus is valid in the email address
2219        var qString = window.location.search;
2220        if (!qString) {
2221            return false;
2222        }
2223        var parameters = qString.substr(1).split('&');
2224        for (var i = 0; i < parameters.length; i++) {
2225            var parameter = parameters[i].split('=');
2226            if (parameter[0].toLowerCase() === 'email') {
2227                return parameter[1] === undefined ? true : decodeURIComponent(parameter[1]);
2228            }
2229        }
2230        return false;
2231    };
2232
2233    var acctDateFormat = "%B-%d-%Y";
2234    var getNormalizedDate = function(date, acctFormat) {
2235        var decodedDate = decodeURIComponent(date);
2236        if (acctFormat && acctFormat.match(/(%d|%e).*%m/gi) !== null) {
2237            return decodedDate.replace(/(\d{2}).*(\d{2}).*(\d{4})/g, '$3-$2-$1');
2238        } else if (Date.parse(decodedDate)) {
2239            var dateObj = new Date(decodedDate);
2240            var year = dateObj.getFullYear();
2241            var month = dateObj.getMonth() + 1;
2242            var day = dateObj.getDate();
2243            return `${year}-${month < 10 ? `0${month}` : month}-${day < 10 ? `0${day}` : day}`;
2244        }
2245        return false;
2246    };
2247
2248    var getNormalizedTime = function(time) {
2249        var hour, minutes;
2250        var decodedTime = decodeURIComponent(time);
2251        var timeParts = Array.from(decodedTime.matchAll(/(\d{1,2}):(\d{1,2})\W*([AaPp][Mm])?/gm))[0];
2252        if (timeParts[3]) { // 12 hour format
2253            var isPM = timeParts[3].toLowerCase() === 'pm';
2254            if (isPM) {
2255                hour = parseInt(timeParts[1]) === 12 ? '12' : `${parseInt(timeParts[1]) + 12}`;
2256            } else {
2257                hour = parseInt(timeParts[1]) === 12 ? '0' : timeParts[1];
2258            }
2259        } else { // 24 hour format
2260            hour = timeParts[1];
2261        }
2262        var normalizedHour = parseInt(hour) < 10 ? `0${parseInt(hour)}` : hour;
2263        var minutes = timeParts[2];
2264        return `${normalizedHour}:${minutes}`;
2265    };
2266
2267    for (var i = 0; i < allInputs.length; i++) {
2268        var regexStr = "field\\[(\\d+)\\]";
2269        var results = new RegExp(regexStr).exec(allInputs[i].name);
2270        if (results != undefined) {
2271            allInputs[i].dataset.name = allInputs[i].name.match(/\[time\]$/)
2272                ? `${window.cfields[results[1]]}_time`
2273                : window.cfields[results[1]];
2274        } else {
2275            allInputs[i].dataset.name = allInputs[i].name;
2276        }
2277        var fieldVal = getUrlParam(allInputs[i].dataset.name);
2278
2279        if (fieldVal) {
2280            if (allInputs[i].dataset.autofill === "false") {
2281                continue;
2282            }
2283            if (allInputs[i].type == "radio" || allInputs[i].type == "checkbox") {
2284                if (allInputs[i].value == fieldVal) {
2285                    allInputs[i].checked = true;
2286                }
2287            } else if (allInputs[i].type == "date") {
2288                allInputs[i].value = getNormalizedDate(fieldVal, acctDateFormat);
2289            } else if (allInputs[i].type == "time") {
2290                allInputs[i].value = getNormalizedTime(fieldVal);
2291            } else {
2292                allInputs[i].value = fieldVal;
2293            }
2294        }
2295    }
2296
2297    var remove_tooltips = function() {
2298        for (var i = 0; i < tooltips.length; i++) {
2299            tooltips[i].tip.parentNode.removeChild(tooltips[i].tip);
2300        }
2301        tooltips = [];
2302    };
2303    var remove_tooltip = function(elem) {
2304        for (var i = 0; i < tooltips.length; i++) {
2305            if (tooltips[i].elem === elem) {
2306                tooltips[i].tip.parentNode.removeChild(tooltips[i].tip);
2307                tooltips.splice(i, 1);
2308                return;
2309            }
2310        }
2311    };
2312    var create_tooltip = function(elem, text) {
2313        var tooltip = document.createElement('div'),
2314            arrow = document.createElement('div'),
2315            inner = document.createElement('div'), new_tooltip = {};
2316        tooltip.id = `${elem.id}-error`;
2317        tooltip.setAttribute('role', 'alert')
2318        if (elem.type != 'radio' && (elem.type != 'checkbox' || elem.name === 'sms_consent')) {
2319            tooltip.className = '_error';
2320            arrow.className = '_error-arrow';
2321            inner.className = '_error-inner';
2322            inner.innerHTML = text;
2323            tooltip.appendChild(arrow);
2324            tooltip.appendChild(inner);
2325            elem.parentNode.appendChild(tooltip);
2326        } else {
2327            tooltip.className = '_error-inner _no_arrow';
2328            tooltip.innerHTML = text;
2329            elem.parentNode.insertBefore(tooltip, elem);
2330            new_tooltip.no_arrow = true;
2331        }
2332        new_tooltip.tip = tooltip;
2333        new_tooltip.elem = elem;
2334        tooltips.push(new_tooltip);
2335        return new_tooltip;
2336    };
2337    var resize_tooltip = function(tooltip) {
2338        var rect = tooltip.elem.getBoundingClientRect();
2339        var doc = document.documentElement,
2340            scrollPosition = rect.top - ((window.pageYOffset || doc.scrollTop)  - (doc.clientTop || 0));
2341        if (scrollPosition < 40) {
2342            tooltip.tip.className = tooltip.tip.className.replace(/ ?(_above|_below) ?/g, '') + ' _below';
2343        } else {
2344            tooltip.tip.className = tooltip.tip.className.replace(/ ?(_above|_below) ?/g, '') + ' _above';
2345        }
2346    };
2347    var resize_tooltips = function() {
2348        if (_removed) return;
2349        for (var i = 0; i < tooltips.length; i++) {
2350            if (!tooltips[i].no_arrow) resize_tooltip(tooltips[i]);
2351        }
2352    };
2353    var validate_field = function(elem, remove) {
2354        var tooltip = null, value = elem.value, no_error = true;
2355        remove ? remove_tooltip(elem) : false;
2356        elem.removeAttribute('aria-invalid');
2357        elem.removeAttribute('aria-describedby');
2358        if (elem.type != 'checkbox') elem.className = elem.className.replace(/ ?_has_error ?/g, '');
2359        if (elem.getAttribute('required') !== null) {
2360            if (elem.type == 'radio' || (elem.type == 'checkbox' && /any/.test(elem.className))) {
2361                var elems = form_to_submit.elements[elem.name];
2362                if (!(elems instanceof NodeList || elems instanceof HTMLCollection) || elems.length <= 1) {
2363                    no_error = elem.checked;
2364                }
2365                else {
2366                    no_error = false;
2367                    for (var i = 0; i < elems.length; i++) {
2368                        if (elems[i].checked) no_error = true;
2369                    }
2370                }
2371                if (!no_error) {
2372                    tooltip = create_tooltip(elem, "Please select an option.");
2373                }
2374            } else if (elem.type =='checkbox') {
2375                var elems = form_to_submit.elements[elem.name], found = false, err = [];
2376                no_error = true;
2377                for (var i = 0; i < elems.length; i++) {
2378                    if (elems[i].getAttribute('required') === null) continue;
2379                    if (!found && elems[i] !== elem) return true;
2380                    found = true;
2381                    elems[i].className = elems[i].className.replace(/ ?_has_error ?/g, '');
2382                    if (!elems[i].checked) {
2383                        no_error = false;
2384                        elems[i].className = elems[i].className + ' _has_error';
2385                        err.push("Checking %s is required".replace("%s", elems[i].value));
2386                    }
2387                }
2388                if (!no_error) {
2389                    tooltip = create_tooltip(elem, err.join('<br/>'));
2390                }
2391            } else if (elem.tagName == 'SELECT') {
2392                var selected = true;
2393                if (elem.multiple) {
2394                    selected = false;
2395                    for (var i = 0; i < elem.options.length; i++) {
2396                        if (elem.options[i].selected) {
2397                            selected = true;
2398                            break;
2399                        }
2400                    }
2401                } else {
2402                    for (var i = 0; i < elem.options.length; i++) {
2403                        if (elem.options[i].selected
2404                            && (!elem.options[i].value
2405                            || (elem.options[i].value.match(/\n/g)))
2406                        ) {
2407                            selected = false;
2408                        }
2409                    }
2410                }
2411                if (!selected) {
2412                    elem.className = elem.className + ' _has_error';
2413                    no_error = false;
2414                    tooltip = create_tooltip(elem, "Please select an option.");
2415                }
2416            } else if (value === undefined || value === null || value === '') {
2417                elem.className = elem.className + ' _has_error';
2418                no_error = false;
2419                tooltip = create_tooltip(elem, "This field is required.");
2420            }
2421        }
2422        if (no_error && elem.name == 'email') {
2423            if (!value.match(/^[\+_a-z0-9-'&=]+(\.[\+_a-z0-9-']+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,})$/i)) {
2424                elem.className = elem.className + ' _has_error';
2425                no_error = false;
2426                tooltip = create_tooltip(elem, "Enter a valid email address.");
2427            }
2428        }
2429        if (no_error && (elem.id == 'phone')) {
2430            if (elem.value.trim() && typeof iti != 'undefined' && !iti.isValidNumber()) {
2431                elem.className = elem.className + ' _has_error';
2432                no_error = false;
2433                tooltip = create_tooltip(elem, "Enter a valid phone number.");
2434            }
2435        }
2436        if (no_error && /date_field/.test(elem.className)) {
2437            if (!value.match(/^\d\d\d\d-\d\d-\d\d$/)) {
2438                elem.className = elem.className + ' _has_error';
2439                no_error = false;
2440                tooltip = create_tooltip(elem, "Enter a valid date.");
2441            }
2442        }
2443
2444        if (no_error && elem.name === 'sms_consent') {
2445            const showError = !!elem.attributes.required && !elem.checked;
2446            if (showError) {
2447                elem.className = elem.className + ' _has_error';
2448                no_error = false;
2449                tooltip = create_tooltip(elem, "Please check this box to continue");
2450            } else {
2451                elem.className = elem.className.replace(/ ?_has_error ?/g, '');
2452            }
2453        }
2454        tooltip ? resize_tooltip(tooltip) : false;
2455        if (!no_error && elem.hasAttribute('id')) {
2456            elem.setAttribute('aria-invalid', 'true');
2457            elem.setAttribute('aria-describedby', `${elem.id}-error`);
2458        }
2459        return no_error;
2460    };
2461    var needs_validate = function(el) {
2462        if(el.getAttribute('required') !== null){
2463            return true;
2464        }
2465        if((el.name === 'email' || el.name === 'phone' || el.id === 'sms_consent') && el.value !== ""){
2466            return true;
2467        }
2468
2469        return false;
2470    };
2471    var validate_email_or_phone_required = function() {
2472        var emailInput = form_to_submit.querySelector('input[name="email"]');
2473        var phoneInput = form_to_submit.querySelector('input[name="phone"]');
2474        if (!emailInput && !phoneInput) {
2475            return true;
2476        }
2477        var hasEmailValue = emailInput && emailInput.value.trim() !== '';
2478        var hasPhoneValue = phoneInput && phoneInput.value.trim() !== '';
2479        if (hasEmailValue || hasPhoneValue) {
2480            return true;
2481        }
2482        var errorField = emailInput || phoneInput;
2483        errorField.className = errorField.className.replace(/ ?_has_error ?/g, '') + ' _has_error';
2484        var tooltip = create_tooltip(
2485            errorField,
2486            "Forms must have an email field or a phone field present"
2487        );
2488        resize_tooltip(tooltip);
2489        errorField.setAttribute('aria-invalid', 'true');
2490        if (errorField.hasAttribute('id')) {
2491            errorField.setAttribute('aria-describedby', errorField.id + '-error');
2492        }
2493        return false;
2494    };
2495    var validate_form = function(e) {
2496        var err = form_to_submit.querySelector('._form_error'), no_error = true;
2497        if (!submitted) {
2498            submitted = true;
2499            for (var i = 0, len = allInputs.length; i < len; i++) {
2500                var input = allInputs[i];
2501                if (needs_validate(input)) {
2502                    if (input.type == 'text' || input.type == 'number' || input.type == 'time' || input.type == 'tel') {
2503                        addEvent(input, 'blur', function() {
2504                            this.value = this.value.trim();
2505                            validate_field(this, true);
2506                        });
2507                        addEvent(input, 'input', function() {
2508                            validate_field(this, true);
2509                        });
2510                    } else if (input.type == 'radio' || input.type == 'checkbox') {
2511                        (function(el) {
2512                            function getElementsArray(name){
2513                                const value =  form_to_submit.elements[name];
2514                                if (Array.isArray(value)){
2515                                    return value;
2516                                }
2517                                return [value];
2518                            }
2519                            var radios = getElementsArray(el.name);
2520                            for (var i = 0; i < radios.length; i++) {
2521                                addEvent(radios[i], 'change', function() {
2522                                    validate_field(el, true);
2523                                });
2524                            }
2525                        })(input);
2526                    } else if (input.tagName == 'SELECT') {
2527                        addEvent(input, 'change', function() {
2528                            validate_field(this, true);
2529                        });
2530                    } else if (input.type == 'textarea'){
2531                        addEvent(input, 'input', function() {
2532                            validate_field(this, true);
2533                        });
2534                    }
2535                }
2536            }
2537        }
2538        remove_tooltips();
2539        for (var i = 0, len = allInputs.length; i < len; i++) {
2540            var elem = allInputs[i];
2541            if (needs_validate(elem)) {
2542                if (elem.tagName.toLowerCase() !== "select") {
2543                    elem.value = elem.value.trim();
2544                }
2545                validate_field(elem) ? true : no_error = false;
2546            }
2547        }
2548        if (!validate_email_or_phone_required()) {
2549            no_error = false;
2550        }
2551        if (!no_error && e) {
2552            e.preventDefault();
2553        }
2554        if (!no_error) {
2555            const firstFocusableError = form_to_submit.querySelector('._has_error:not([disabled])');
2556            if (firstFocusableError && typeof firstFocusableError.focus === 'function') {
2557                firstFocusableError.focus();
2558            }
2559        }
2560        resize_tooltips();
2561        return no_error;
2562    };
2563    addEvent(window, 'resize', resize_tooltips);
2564    addEvent(window, 'scroll', resize_tooltips);
2565    var initializePhoneInput = function(inputPhone) {
2566
2567        const stylesheetLink = document.createElement('link');
2568        stylesheetLink.rel = 'stylesheet';
2569        stylesheetLink.href = 'https://cdn.jsdelivr.net/npm/[email protected]/build/css/intlTelInput.css';
2570        document.head.appendChild(stylesheetLink);
2571
2572        window._load_script('https://cdn.jsdelivr.net/npm/[email protected]/build/js/intlTelInput.min.js', function() {
2573            inputPhone.setAttribute("name", "phone-iti");
2574            iti = intlTelInput(inputPhone, {
2575                loadUtils: () => import('https://cdn.jsdelivr.net/npm/[email protected]/build/js/utils.js'),
2576                hiddenInput: (telInputName) => ({
2577                    phone: 'phone'
2578                }),
2579                separateDialCode: true,
2580                autoPlaceholder: 'aggressive',
2581                initialCountry: "us",
2582            });
2583        }, false);
2584    }
2585    var inputPhone = form_to_submit.querySelector('input[name="phone"]');
2586    if(inputPhone) {
2587        initializePhoneInput(inputPhone);
2588    }
2589
2590    var _form_serialize = function(form){if(!form||form.nodeName!=="FORM"){return }var i,j,q=[];for(i=0;i<form.elements.length;i++){if(form.elements[i].name===""){continue}switch(form.elements[i].nodeName){case"INPUT":switch(form.elements[i].type){case"tel":q.push(form.elements[i].name+"="+encodeURIComponent(form.elements[i].previousSibling.querySelector('div.iti__selected-dial-code').innerText)+encodeURIComponent(" ")+encodeURIComponent(form.elements[i].value));break;case"text":case"number":case"date":case"time":case"hidden":case"password":case"button":case"reset":case"submit":q.push(form.elements[i].name+"="+encodeURIComponent(form.elements[i].value));break;case"checkbox":case"radio":if(form.elements[i].checked){q.push(form.elements[i].name+"="+encodeURIComponent(form.elements[i].value))}break;case"file":break}break;case"TEXTAREA":q.push(form.elements[i].name+"="+encodeURIComponent(form.elements[i].value));break;case"SELECT":switch(form.elements[i].type){case"select-one":q.push(form.elements[i].name+"="+encodeURIComponent(form.elements[i].value));break;case"select-multiple":for(j=0;j<form.elements[i].options.length;j++){if(form.elements[i].options[j].selected){q.push(form.elements[i].name+"="+encodeURIComponent(form.elements[i].options[j].value))}}break}break;case"BUTTON":switch(form.elements[i].type){case"reset":case"submit":case"button":q.push(form.elements[i].name+"="+encodeURIComponent(form.elements[i].value));break}break}}return q.join("&")};
2591
2592    const formSupportsPost = false;
2593    var form_submit = function(e) {
2594
2595        e.preventDefault();
2596        if(form_to_submit.querySelector('input[name="phone"]') && typeof iti != 'undefined') {
2597            form_to_submit.querySelector('input[name="phone"]').value = iti.getNumber();
2598        }
2599        if (validate_form()) {
2600            // use this trick to get the submit button & disable it using plain javascript
2601            var submitButton = e.target.querySelector('#_form_28_submit');
2602            submitButton.disabled = true;
2603            submitButton.classList.add('processing');
2604                    var serialized = _form_serialize(document.getElementById('_form_28_')).replace(/%0A/g, '\\n');
2605            var err = form_to_submit.querySelector('._form_error');
2606            err ? err.parentNode.removeChild(err) : false;
2607            async function submitForm() {
2608                var formData = new FormData();
2609                const searchParams = new URLSearchParams(serialized);
2610                searchParams.forEach((value, key) => {
2611                    if (key !== 'hideButton') {
2612                        formData.append(key, value);
2613                    }
2614                });
2615                let request = {
2616                    headers: {
2617                        "Accept": "application/json"
2618                    },
2619                    body: formData,
2620                    method: "POST"
2621                };
2622
2623                let pageUrlParams = new URLSearchParams(window.location.search);
2624                if (pageUrlParams.has('t')) {
2625                    request.headers.Authorization = 'Bearer ' + pageUrlParams.get('t');
2626                }
2627                const response = await fetch('https://flyingshapes.activehosted.com/proc.php?jsonp=true', request);
2628
2629                return response.json();
2630            }
2631            if (formSupportsPost) {
2632                submitForm().then((data) => {
2633                    eval(data.js);
2634                }).catch(() => {
2635                    _show_error("28", "Sorry, your submission failed. Please try again.");
2636                });
2637            } else {
2638                _load_script('https://flyingshapes.activehosted.com/proc.php?' + serialized + '&jsonp=true', null, true);
2639            }
2640        }
2641        return false;
2642    };
2643    addEvent(form_to_submit, 'submit', form_submit);
2644})();
2645
2646</script>
2646					</div>
2647					<p class="fs-lightbox__legal">Our <a href="https://www.flyingshapes.com/privacy/">Privacy Policy</a> applies.</p>
2648				</div>
2649			</div>
2650		</dialog>
2651			<dialog class="fs-lightbox fs-lightbox--media" id="fs-lightbox-media" aria-label="Portfolio video">
2652		<div class="fs-lightbox__panel fs-lightbox__panel--media">
2653			<button type="button" class="fs-lightbox__close" data-lightbox-close aria-label="Close">
2654				<span aria-hidden="true">&times;</span>
2655			</button>
2656			<video class="fs-lightbox__video" controls playsinline></video>
2657		</div>
2658	</dialog>
2659	
2659<script type="speculationrules">
2660{"prefetch":[{"source":"document","where":{"and":[{"href_matches":"/*"},{"not":{"href_matches":["/wp-*.php","/wp-admin/*","/wp-content/uploads/*","/wp-content/*","/wp-content/plugins/*","/wp-content/themes/flyingshapes/*","/*\\?(.+)"]}},{"not":{"selector_matches":"a[rel~=\"nofollow\"]"}},{"not":{"selector_matches":".no-prefetch, .no-prefetch a"}}]},"eagerness":"conservative"}]}
2661</script>
vendor: 1 bytes, line 2661
2661
2662<script data-wp-strategy="defer" defer id="flyingshapes-lightbox-js" src="https://www.flyingshapes.com/wp-content/themes/flyingshapes/assets/js/lightbox.js?ver=1789129308"></script>
vendor: 1 bytes, line 2662
2662
2663<script data-wp-strategy="defer" defer id="flyingshapes-nav-js" src="https://www.flyingshapes.com/wp-content/themes/flyingshapes/assets/js/nav.js?ver=1788530440"></script>
vendor: 1 bytes, line 2663
2663
2664<script id="googlesitekit-events-provider-content-events-js-before">
2665window._googlesitekit = window._googlesitekit || {};
2666window._googlesitekit.contentEvents = {"postID":24,"isSinglePost":false,"hasVimeoEmbed":false};
2667//# sourceURL=googlesitekit-events-provider-content-events-js-before
2668</script>
vendor: 1 bytes, line 2668
2668
2669<script id="googlesitekit-events-provider-content-events-js" src="https://www.flyingshapes.com/wp-content/plugins/google-site-kit/dist/assets/js/googlesitekit-events-provider-content-events-c7172f3fd0e4d5ad62ef.js" defer></script>
vendor: 1 bytes, line 2669
2669
2670<script id="wp-emoji-settings" type="application/json">
2671{"baseUrl":"https://s.w.org/images/core/emoji/17.0.2/72x72/","ext":".png","svgUrl":"https://s.w.org/images/core/emoji/17.0.2/svg/","svgExt":".svg","source":{"concatemoji":"https://www.flyingshapes.com/wp-includes/js/wp-emoji-release.min.js?ver=7.1.2"}}
2672</script>
vendor: 1 bytes, line 2672
2672
2673<script type="module">
2674/*! This file is auto-generated */
2675var e="script#wp-emoji-settings",t=document.querySelector(e);if(!(t instanceof HTMLScriptElement))throw new Error("Element missing: "+e);const r=JSON.parse(t.text),s=(window._wpemojiSettings=r,"wpEmojiSettingsSupports"),o=["flag","emoji"];function i(e){try{var t={supportTests:e,timestamp:(new Date).valueOf()};sessionStorage.setItem(s,JSON.stringify(t))}catch(e){}}function c(e,t,n){e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(t,0,0);t=new Uint32Array(e.getImageData(0,0,e.canvas.width,e.canvas.height).data);e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(n,0,0);const r=new Uint32Array(e.getImageData(0,0,e.canvas.width,e.canvas.height).data);return t.every((e,t)=>e===r[t])}function p(e,t){e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(t,0,0);var n=e.getImageData(16,16,1,1);for(let e=0;e<n.data.length;e++)if(0!==n.data[e])return!1;return!0}function u(e,t,n,r){switch(t){case"flag":return n(e,"\ud83c\udff3\ufe0f\u200d\u26a7\ufe0f","\ud83c\udff3\ufe0f\u200b\u26a7\ufe0f")?!1:!n(e,"\ud83c\udde8\ud83c\uddf6","\ud83c\udde8\u200b\ud83c\uddf6")&&!n(e,"\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc65\udb40\udc6e\udb40\udc67\udb40\udc7f","\ud83c\udff4\u200b\udb40\udc67\u200b\udb40\udc62\u200b\udb40\udc65\u200b\udb40\udc6e\u200b\udb40\udc67\u200b\udb40\udc7f");case"emoji":return!r(e,"\ud83e\u1fac8")}return!1}function f(e,t,n,r){let a;const s=(a="undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?new OffscreenCanvas(300,150):document.createElement("canvas")).getContext("2d",{willReadFrequently:!0}),o=(s.textBaseline="top",s.font="600 32px Arial",{});return e.forEach(e=>{o[e]=t(s,e,n,r)}),o}function a(e){var t=document.createElement("script");t.src=e,t.defer=!0,document.head.appendChild(t)}r.supports={everything:!0,everythingExceptFlag:!0},new Promise(t=>{let n=function(){try{var e=JSON.parse(sessionStorage.getItem(s));if("object"==typeof e&&"number"==typeof e.timestamp&&(new Date).valueOf()<e.timestamp+604800&&"object"==typeof e.supportTests)return e.supportTests}catch(e){}return null}();if(!n){if("undefined"!=typeof Worker&&"undefined"!=typeof OffscreenCanvas&&"undefined"!=typeof URL&&URL.createObjectURL&&"undefined"!=typeof Blob)try{var e="postMessage("+f.toString()+"("+[JSON.stringify(o),u.toString(),c.toString(),p.toString()].join(",")+"));",r=new Blob([e],{type:"text/javascript"});const a=new Worker(URL.createObjectURL(r),{name:"wpTestEmojiSupports"});return void(a.onmessage=e=>{i(n=e.data),a.terminate(),t(n)})}catch(e){}i(n=f(o,u,c,p))}t(n)}).then(e=>{for(const n in e)r.supports[n]=e[n],r.supports.everything=r.supports.everything&&r.supports[n],"flag"!==n&&(r.supports.everythingExceptFlag=r.supports.everythingExceptFlag&&r.supports[n]);var t;r.supports.everythingExceptFlag=r.supports.everythingExceptFlag&&!r.supports.flag,r.supports.everything||((t=r.source||{}).concatemoji?a(t.concatemoji):t.wpemoji&&t.twemoji&&(a(t.twemoji),a(t.wpemoji)))});
2676//# sourceURL=https://www.flyingshapes.com/wp-includes/js/wp-emoji-loader.min.js
2677</script>
2677
2678</body>
2679</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.