@neurodyn/core-ar 0.3.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -472,6 +472,11 @@ function getFetch(options) {
472
472
  function getRuntimeConfig(options) {
473
473
  return options.runtimeConfig ?? getCoreArWidgetRuntimeConfig();
474
474
  }
475
+ function getBrandHeaders(runtimeConfig) {
476
+ return {
477
+ 'x-app-type': runtimeConfig.brand
478
+ };
479
+ }
475
480
  function getRuntimeUrl(apiOrigin, pathname, params = {}) {
476
481
  const url = new URL(pathname, apiOrigin);
477
482
  for (const [name, value] of Object.entries(params))if (value) url.searchParams.set(name, value);
@@ -527,12 +532,13 @@ function parseWidgetSession(value) {
527
532
  return data;
528
533
  }
529
534
  async function activateCoreWidget(publicKey, options = {}) {
530
- const { apiOrigin } = getRuntimeConfig(options);
531
- const response = await runtimeFetch(getRuntimeUrl(apiOrigin, '/public/widget/activate-core', {
535
+ const runtimeConfig = getRuntimeConfig(options);
536
+ const response = await runtimeFetch(getRuntimeUrl(runtimeConfig.apiOrigin, '/public/widget/activate-core', {
532
537
  mode: options.mode
533
538
  }), {
534
539
  cache: 'no-store',
535
540
  headers: {
541
+ ...getBrandHeaders(runtimeConfig),
536
542
  'x-api-key': publicKey
537
543
  },
538
544
  method: 'POST'
@@ -546,8 +552,8 @@ async function activateCoreWidget(publicKey, options = {}) {
546
552
  };
547
553
  }
548
554
  async function refreshWidgetSession(publicKey, previousToken, options = {}) {
549
- const { apiOrigin } = getRuntimeConfig(options);
550
- const response = await runtimeFetch(`${apiOrigin}/public/widget/token`, {
555
+ const runtimeConfig = getRuntimeConfig(options);
556
+ const response = await runtimeFetch(`${runtimeConfig.apiOrigin}/public/widget/token`, {
551
557
  body: JSON.stringify({
552
558
  token: previousToken,
553
559
  ...options.mode ? {
@@ -556,6 +562,7 @@ async function refreshWidgetSession(publicKey, previousToken, options = {}) {
556
562
  }),
557
563
  cache: 'no-store',
558
564
  headers: {
565
+ ...getBrandHeaders(runtimeConfig),
559
566
  'Content-Type': 'application/json',
560
567
  'x-api-key': publicKey
561
568
  },
@@ -565,12 +572,13 @@ async function refreshWidgetSession(publicKey, previousToken, options = {}) {
565
572
  return parseWidgetSession(await parseSuccessJson(response));
566
573
  }
567
574
  async function fetchWidgetObject(objectId, sessionToken, options = {}) {
568
- const { apiOrigin } = getRuntimeConfig(options);
569
- const response = await runtimeFetch(getRuntimeUrl(apiOrigin, `/public/objects/by-tinuuid/${encodeURIComponent(objectId)}`, {
575
+ const runtimeConfig = getRuntimeConfig(options);
576
+ const response = await runtimeFetch(getRuntimeUrl(runtimeConfig.apiOrigin, `/public/objects/by-tinuuid/${encodeURIComponent(objectId)}`, {
570
577
  variantId: options.variantId
571
578
  }), {
572
579
  cache: 'no-store',
573
580
  headers: {
581
+ ...getBrandHeaders(runtimeConfig),
574
582
  'x-widget-session-token': sessionToken
575
583
  },
576
584
  method: 'GET'
@@ -581,8 +589,8 @@ async function fetchWidgetObject(objectId, sessionToken, options = {}) {
581
589
  return data;
582
590
  }
583
591
  async function sendWidgetEvent(event, sessionToken, objectUuid, options = {}) {
584
- const { apiOrigin } = getRuntimeConfig(options);
585
- const response = await runtimeFetch(`${apiOrigin}/public/widget/events`, {
592
+ const runtimeConfig = getRuntimeConfig(options);
593
+ const response = await runtimeFetch(`${runtimeConfig.apiOrigin}/public/widget/events`, {
586
594
  body: JSON.stringify({
587
595
  event,
588
596
  ...objectUuid ? {
@@ -595,6 +603,7 @@ async function sendWidgetEvent(event, sessionToken, objectUuid, options = {}) {
595
603
  }),
596
604
  cache: 'no-store',
597
605
  headers: {
606
+ ...getBrandHeaders(runtimeConfig),
598
607
  'Content-Type': 'application/json',
599
608
  'x-widget-session-token': sessionToken
600
609
  },
@@ -613,6 +622,7 @@ async function fetchPublicObject(objectId, signal, runtimeConfig) {
613
622
  tinuuid: objectId
614
623
  }),
615
624
  headers: {
625
+ ...getBrandHeaders(resolvedConfig),
616
626
  'Content-Type': 'application/json'
617
627
  },
618
628
  method: 'POST'
@@ -627,12 +637,13 @@ async function fetchPublicObject(objectId, signal, runtimeConfig) {
627
637
  return data;
628
638
  }
629
639
  async function incrementObjectViews(objectId, runtimeConfig) {
630
- const { apiOrigin, fetchImpl } = runtimeConfig ?? getCoreArWidgetRuntimeConfig();
631
- await fetchImpl(`${apiOrigin}/catalog/object/incr-views`, {
640
+ const resolvedConfig = runtimeConfig ?? getCoreArWidgetRuntimeConfig();
641
+ await resolvedConfig.fetchImpl(`${resolvedConfig.apiOrigin}/catalog/object/incr-views`, {
632
642
  body: JSON.stringify({
633
643
  tinuuid: objectId
634
644
  }),
635
645
  headers: {
646
+ ...getBrandHeaders(resolvedConfig),
636
647
  'Content-Type': 'application/json'
637
648
  },
638
649
  method: 'POST'
@@ -666,6 +677,7 @@ async function initializeAdvancedArTrigger(trigger, options = {}) {
666
677
  let createdImage;
667
678
  let closeOwnedQr;
668
679
  let handlingUnsupportedClick = false;
680
+ let openingWebAr = false;
669
681
  let qrRevision = 0;
670
682
  if (!trigger.querySelector('img')) {
671
683
  createdImage = document.createElement('img');
@@ -690,6 +702,18 @@ async function initializeAdvancedArTrigger(trigger, options = {}) {
690
702
  }).catch(()=>void 0);
691
703
  };
692
704
  const handleMobileClick = async (event)=>{
705
+ if (options.webAr?.isAvailable()) {
706
+ event.preventDefault();
707
+ if (openingWebAr) return;
708
+ openingWebAr = true;
709
+ let opened = false;
710
+ try {
711
+ opened = await options.webAr.open().catch(()=>false);
712
+ } finally{
713
+ openingWebAr = false;
714
+ }
715
+ if (opened || !initialization.isCurrent()) return;
716
+ }
693
717
  if (isUnsupportedFetchInAr()) {
694
718
  event.preventDefault();
695
719
  if (handlingUnsupportedClick) return;
@@ -837,6 +861,7 @@ function initializeModalTrigger(trigger, options) {
837
861
  hid: trigger.dataset.objectHid,
838
862
  initialWidgetSessionToken: widgetSessionToken,
839
863
  lang: options.lang,
864
+ launchAr: options.launchAr,
840
865
  maxCameraOrbit: trigger.dataset.maxCameraOrbit,
841
866
  minCameraOrbit: trigger.dataset.minCameraOrbit,
842
867
  mode: options.mode,
@@ -890,6 +915,7 @@ async function initializeNativeArAnchor(link, options = {}) {
890
915
  const mobile = isMobile();
891
916
  let createdImage;
892
917
  let closeOwnedQr;
918
+ let openingWebAr = false;
893
919
  let qrRevision = 0;
894
920
  link.rel = 'ar';
895
921
  if (!link.querySelector('img')) {
@@ -913,10 +939,25 @@ async function initializeNativeArAnchor(link, options = {}) {
913
939
  closeOwnedQr = cleanup;
914
940
  }).catch(()=>void 0);
915
941
  };
916
- const handleMobileClick = ()=>{
942
+ const trackNativeLaunch = ()=>{
917
943
  runSafely(options.trackView ?? (()=>incrementObjectViews(objectId, options.runtimeConfig)));
918
944
  runSafely(()=>options.onAction?.('ar_launched'));
919
945
  };
946
+ const handleMobileClick = async (event)=>{
947
+ if (!options.webAr?.isAvailable()) return void trackNativeLaunch();
948
+ event.preventDefault();
949
+ if (openingWebAr) return;
950
+ openingWebAr = true;
951
+ let opened = false;
952
+ try {
953
+ opened = await options.webAr.open().catch(()=>false);
954
+ } finally{
955
+ openingWebAr = false;
956
+ }
957
+ if (opened || !initialization.isCurrent()) return;
958
+ trackNativeLaunch();
959
+ openNativeLink(nativeLink);
960
+ };
920
961
  if (mobile) {
921
962
  link.href = nativeLink;
922
963
  link.addEventListener('click', handleMobileClick);
@@ -936,6 +977,76 @@ async function initializeNativeArAnchor(link, options = {}) {
936
977
  else link.setAttribute('rel', originalRel);
937
978
  });
938
979
  }
980
+ function isCoreArPublicHost(hostname = globalThis.location?.hostname ?? '') {
981
+ const host = hostname.toLowerCase();
982
+ return [
983
+ 'vizbl.com',
984
+ 'vizbl.us',
985
+ 'arizo.ru'
986
+ ].some((domain)=>host === domain || host.endsWith(`.${domain}`));
987
+ }
988
+ const WEB_AR_TAP_WINDOW_MS = 3000;
989
+ const web_ar_dialog_DIALOG_EXIT_MS = 300;
990
+ let web_ar_dialog_pendingLoad;
991
+ async function importWebArDialog() {
992
+ const { ArDialog, prepareArSessionInPage } = await import("@neurodyn/react-ar");
993
+ const { createElement } = await import("react");
994
+ const { createRoot } = await import("react-dom/client");
995
+ return {
996
+ open: ({ onClose, ...props })=>{
997
+ const container = document.createElement('div');
998
+ container.setAttribute('data-core-ar-web-ar', '');
999
+ document.body.appendChild(container);
1000
+ const root = createRoot(container);
1001
+ let closed = false;
1002
+ const render = (open)=>root.render(createElement(ArDialog, {
1003
+ ...props,
1004
+ onOpenChange: (next)=>{
1005
+ if (!next) close();
1006
+ },
1007
+ open
1008
+ }));
1009
+ function close() {
1010
+ if (closed) return;
1011
+ closed = true;
1012
+ render(false);
1013
+ setTimeout(()=>{
1014
+ root.unmount();
1015
+ container.remove();
1016
+ }, web_ar_dialog_DIALOG_EXIT_MS);
1017
+ onClose?.();
1018
+ }
1019
+ render(true);
1020
+ return close;
1021
+ },
1022
+ prepare: prepareArSessionInPage
1023
+ };
1024
+ }
1025
+ function loadWebArDialog() {
1026
+ if (web_ar_dialog_pendingLoad) return web_ar_dialog_pendingLoad;
1027
+ const promise = importWebArDialog();
1028
+ web_ar_dialog_pendingLoad = promise;
1029
+ promise.catch(()=>{
1030
+ if (web_ar_dialog_pendingLoad === promise) web_ar_dialog_pendingLoad = void 0;
1031
+ });
1032
+ return promise;
1033
+ }
1034
+ async function prepareWebArDialog(tinuuid) {
1035
+ const dialog = await loadWebArDialog();
1036
+ return await dialog.prepare(tinuuid) ? dialog : null;
1037
+ }
1038
+ function withinTapWindow(promise, windowMs = WEB_AR_TAP_WINDOW_MS) {
1039
+ return new Promise((resolve, reject)=>{
1040
+ const timer = setTimeout(()=>resolve(null), windowMs);
1041
+ promise.then((value)=>{
1042
+ clearTimeout(timer);
1043
+ resolve(value);
1044
+ }, (error)=>{
1045
+ clearTimeout(timer);
1046
+ reject(error);
1047
+ });
1048
+ });
1049
+ }
939
1050
  const CORE_AR_WIDGET_TYPES = [
940
1051
  'advanced-ar',
941
1052
  'ar-one-click',
@@ -1136,6 +1247,7 @@ class CoreArWidgetElement extends HTMLElementBase {
1136
1247
  abortController;
1137
1248
  actionResetTimer;
1138
1249
  cleanup;
1250
+ closeWebAr;
1139
1251
  customLabelNodes = null;
1140
1252
  initializationRevision = 0;
1141
1253
  object;
@@ -1209,12 +1321,12 @@ class CoreArWidgetElement extends HTMLElementBase {
1209
1321
  this.renderTrigger(renderType);
1210
1322
  try {
1211
1323
  const runtimeConfig = this.resolveRuntimeConfig();
1212
- if (!publicKey) throw new CoreArWidgetComponentError('MISSING_API_KEY');
1324
+ if (!publicKey && !isCoreArPublicHost()) throw new CoreArWidgetComponentError('MISSING_API_KEY');
1213
1325
  if (!objectId) throw new CoreArWidgetComponentError('MISSING_OBJECT_ID');
1214
1326
  if (!isCoreArWidgetType(rawType)) throw new CoreArWidgetComponentError('INVALID_TYPE');
1215
1327
  if ('ar-viewer' === rawType && sizeType && 'cm' !== sizeType && 'inch' !== sizeType) throw new CoreArWidgetComponentError('INVALID_SIZE_TYPE');
1216
1328
  const mode = BACKEND_WIDGET_MODES[rawType];
1217
- const session = await this.ensureSession(publicKey, runtimeConfig, mode, abortController.signal);
1329
+ const session = publicKey ? await this.ensureSession(publicKey, runtimeConfig, mode, abortController.signal) : void 0;
1218
1330
  this.assertCurrent(revision, abortController.signal);
1219
1331
  this.variantId = variantId;
1220
1332
  this.widgetMode = mode;
@@ -1227,7 +1339,7 @@ class CoreArWidgetElement extends HTMLElementBase {
1227
1339
  assertPolicy(rawType, object);
1228
1340
  this.object = object;
1229
1341
  } else {
1230
- object = isMobile() ? await this.fetchObjectWithSession(objectId, publicKey, session, runtimeConfig, abortController.signal, variantId) : await fetchPublicObject(objectId, abortController.signal, runtimeConfig);
1342
+ object = isMobile() && session ? await this.fetchObjectWithSession(objectId, publicKey, session, runtimeConfig, abortController.signal, variantId) : await fetchPublicObject(objectId, abortController.signal, runtimeConfig);
1231
1343
  this.assertCurrent(revision, abortController.signal);
1232
1344
  const material = getSelectedMaterial(object, variantId);
1233
1345
  assertPolicy(rawType, object);
@@ -1241,7 +1353,10 @@ class CoreArWidgetElement extends HTMLElementBase {
1241
1353
  cleanup();
1242
1354
  throw error;
1243
1355
  }
1244
- this.cleanup = cleanup;
1356
+ this.cleanup = ()=>{
1357
+ cleanup();
1358
+ this.closeWebAr?.();
1359
+ };
1245
1360
  this.setState('ready');
1246
1361
  this.dispatchWidgetEvent('core-ar-ready', {
1247
1362
  objectId,
@@ -1383,14 +1498,23 @@ class CoreArWidgetElement extends HTMLElementBase {
1383
1498
  }
1384
1499
  async initializeTrigger(type, object, runtimeConfig, signal, publicKey, session) {
1385
1500
  if (!this.trigger) throw new CoreArWidgetComponentError('INITIALIZATION_FAILED');
1501
+ const mode = BACKEND_WIDGET_MODES[type];
1386
1502
  if ('ar-viewer' === type) return initializeModalTrigger(this.trigger, {
1387
1503
  apiKey: publicKey,
1388
- getWidgetSessionToken: async ()=>{
1389
- const currentSession = await this.ensureSession(publicKey, runtimeConfig, session.mode);
1504
+ getWidgetSessionToken: publicKey ? async ()=>{
1505
+ const currentSession = await this.ensureSession(publicKey, runtimeConfig, mode);
1390
1506
  return currentSession.token;
1391
- },
1507
+ } : void 0,
1392
1508
  lang: 'arizo' === runtimeConfig.brand ? 'ru' : 'en',
1393
- mode: session.mode,
1509
+ launchAr: canOpenWebAr() ? (target)=>this.openWebAr({
1510
+ apiBaseUrl: target.apiBaseUrl ?? runtimeConfig.apiOrigin,
1511
+ apiKey: target.apiKey ?? publicKey,
1512
+ hid: target.hid,
1513
+ language: target.lang,
1514
+ name: target.name,
1515
+ tinuuid: target.tinuuid
1516
+ }, ()=>target.widgetSessionToken, ()=>!signal.aborted) : void 0,
1517
+ mode,
1394
1518
  modelViewerOrigin: runtimeConfig.modelViewerOrigin,
1395
1519
  onAction: (action)=>this.handleAction(action, runtimeConfig),
1396
1520
  onClose: ()=>{
@@ -1402,12 +1526,12 @@ class CoreArWidgetElement extends HTMLElementBase {
1402
1526
  viewer: {
1403
1527
  apiBaseUrl: runtimeConfig.apiOrigin
1404
1528
  },
1405
- widgetSessionToken: session.token
1529
+ widgetSessionToken: session?.token
1406
1530
  });
1407
1531
  if (!object) throw new CoreArWidgetComponentError('INITIALIZATION_FAILED');
1408
1532
  const options = {
1409
1533
  getDesktopQrUrl: async ()=>{
1410
- const currentSession = await this.ensureSession(publicKey, runtimeConfig, session.mode);
1534
+ const currentSession = publicKey ? await this.ensureSession(publicKey, runtimeConfig, mode) : void 0;
1411
1535
  return createModalViewerUrl({
1412
1536
  apiKey: publicKey,
1413
1537
  cameraOrbit: this.trigger?.dataset.cameraOrbit,
@@ -1416,18 +1540,19 @@ class CoreArWidgetElement extends HTMLElementBase {
1416
1540
  lang: 'arizo' === runtimeConfig.brand ? 'ru' : 'en',
1417
1541
  maxCameraOrbit: this.trigger?.dataset.maxCameraOrbit,
1418
1542
  minCameraOrbit: this.trigger?.dataset.minCameraOrbit,
1419
- mode: currentSession.mode,
1543
+ mode,
1420
1544
  modelViewerOrigin: runtimeConfig.modelViewerOrigin,
1421
1545
  sizeType: resolveSizeType(this.trigger?.dataset.sizeType),
1422
1546
  tinuuid: this.trigger?.dataset.objectTinuuid ?? '',
1423
- widgetSessionToken: currentSession.token
1547
+ widgetSessionToken: currentSession?.token
1424
1548
  });
1425
1549
  },
1426
1550
  object,
1427
1551
  onAction: (action)=>this.handleAction(action, runtimeConfig),
1428
1552
  runtimeConfig,
1429
1553
  signal,
1430
- trackView: ()=>this.trackEvent('ar_launched', runtimeConfig)
1554
+ trackView: ()=>publicKey ? this.trackEvent('ar_launched', runtimeConfig) : incrementObjectViews(this.getAttribute('object-id') ?? '', runtimeConfig),
1555
+ webAr: this.createWebArLauncher(object, publicKey, runtimeConfig, mode, signal)
1431
1556
  };
1432
1557
  if ('ar-one-click' === type) {
1433
1558
  if (!(this.trigger instanceof HTMLAnchorElement)) throw new CoreArWidgetComponentError('INITIALIZATION_FAILED');
@@ -1435,6 +1560,57 @@ class CoreArWidgetElement extends HTMLElementBase {
1435
1560
  }
1436
1561
  return initializeAdvancedArTrigger(this.trigger, options);
1437
1562
  }
1563
+ createWebArLauncher(object, publicKey, runtimeConfig, mode, signal) {
1564
+ const isCurrent = ()=>!signal.aborted;
1565
+ return {
1566
+ isAvailable: canOpenWebAr,
1567
+ open: async ()=>{
1568
+ this.setState('loading');
1569
+ const opened = await this.openWebAr({
1570
+ apiBaseUrl: runtimeConfig.apiOrigin,
1571
+ apiKey: publicKey || void 0,
1572
+ hid: this.variantId,
1573
+ language: 'arizo' === runtimeConfig.brand ? 'ru' : 'en',
1574
+ name: 'string' == typeof object.name ? object.name : void 0,
1575
+ onClose: ()=>{
1576
+ if (isCurrent()) this.setState('ready');
1577
+ },
1578
+ tinuuid: this.trigger?.dataset.objectTinuuid ?? object.tinuuid
1579
+ }, async ()=>publicKey ? (await this.ensureSession(publicKey, runtimeConfig, mode)).token : void 0, isCurrent);
1580
+ if (isCurrent()) this.setState(opened ? 'opening' : 'ready');
1581
+ return opened;
1582
+ }
1583
+ };
1584
+ }
1585
+ async openWebAr(options, getWidgetSessionToken, isCurrent) {
1586
+ const tinuuid = options.tinuuid?.trim();
1587
+ if (!tinuuid) return false;
1588
+ const ready = await withinTapWindow(Promise.all([
1589
+ prepareWebArDialog(tinuuid),
1590
+ Promise.resolve().then(getWidgetSessionToken)
1591
+ ])).catch(()=>null);
1592
+ const [dialog, token] = ready ?? [];
1593
+ if (!dialog || !this.isConnected || !isCurrent()) return false;
1594
+ this.closeWebAr?.();
1595
+ let publicViewTracked = false;
1596
+ const close = dialog.open({
1597
+ ...options,
1598
+ initialWidgetSessionToken: token,
1599
+ onAnalyticsEvent: (event)=>{
1600
+ if (isCurrent() && !options.apiKey && !token && !publicViewTracked && 'ar_session_started' === event.name) {
1601
+ publicViewTracked = true;
1602
+ incrementObjectViews(tinuuid, this.resolveRuntimeConfig()).catch(()=>void 0);
1603
+ }
1604
+ return options.onAnalyticsEvent?.(event);
1605
+ },
1606
+ onClose: ()=>{
1607
+ if (this.closeWebAr === close) this.closeWebAr = void 0;
1608
+ options.onClose?.();
1609
+ }
1610
+ });
1611
+ this.closeWebAr = close;
1612
+ return true;
1613
+ }
1438
1614
  handleAction(action, runtimeConfig) {
1439
1615
  this.setState('opening');
1440
1616
  if (('interacted' === action || 'widget_opened' === action) && 'ar-viewer' !== this.getAttribute('type')) this.trackEvent(action, runtimeConfig);
@@ -1481,6 +1657,9 @@ class CoreArWidgetElement extends HTMLElementBase {
1481
1657
  }));
1482
1658
  }
1483
1659
  }
1660
+ function canOpenWebAr() {
1661
+ return isMobile() && !isIOS();
1662
+ }
1484
1663
  function registerBrandedCoreWidget(brand) {
1485
1664
  if ("u" < typeof customElements) return;
1486
1665
  const tagName = CORE_AR_WIDGET_TAG_NAMES[brand];
@@ -0,0 +1,139 @@
1
+ <svg width="1000" height="1000" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 264 264" aria-hidden="true" xmlns:c2pa="http://c2pa.org/manifest">
2
+ <style>
3
+ .camera-intro__k,.camera-intro__move,.camera-intro__drop,.camera-intro__finger{transform-box:view-box;transform-origin:0 0;animation-duration:10.6s;animation-iteration-count:infinite;animation-timing-function:linear;animation-fill-mode:both}
4
+ .camera-intro__move{transform-origin:132px 196px;animation-name:camera-intro-move}
5
+ .camera-intro__drop{transform-origin:132px 196px;animation-name:camera-intro-drop}
6
+ .camera-intro__stand{transform-box:fill-box;transform-origin:center}
7
+ .camera-intro__finger{animation-name:camera-intro-finger}
8
+ .camera-intro__ring{transform-box:fill-box;transform-origin:center;animation:camera-intro-ring 10.6s infinite both}
9
+ @keyframes camera-intro-drop{0%,28.30%{opacity:0;transform:translateY(-14px) scale(.92);animation-timing-function:cubic-bezier(.34,1.56,.64,1)}33.02%,100%{opacity:1;transform:none}}
10
+ .camera-intro__top{animation-name:camera-intro-top}@keyframes camera-intro-top{0%,39.15%{transform:translate(113.63px,177.63px) rotate(8.79deg) skewX(-16.1deg) scale(29.32,-17.72)}39.82%{transform:translate(113.61px,177.61px) rotate(8.86deg) skewX(-16.21deg) scale(29.31,-17.73)}40.50%{transform:translate(113.54px,177.54px) rotate(9.1deg) skewX(-16.56deg) scale(29.28,-17.75)}41.17%{transform:translate(113.4px,177.39px) rotate(9.57deg) skewX(-17.26deg) scale(29.2,-17.79)}41.85%{transform:translate(113.17px,177.14px) rotate(10.38deg) skewX(-18.42deg) scale(29.07,-17.87)}42.52%{transform:translate(112.8px,176.71px) rotate(11.77deg) skewX(-20.24deg) scale(28.82,-18.03)}43.19%{transform:translate(112.24px,175.96px) rotate(14.22deg) skewX(-23.02deg) scale(28.34,-18.34)}43.87%{transform:translate(111.51px,174.67px) rotate(18.43deg) skewX(-26.57deg) scale(27.39,-18.97)}44.54%{transform:translate(111.03px,173.36px) rotate(22.99deg) skewX(-28.85deg) scale(26.26,-19.79)}45.22%{transform:translate(110.86px,172.54px) rotate(25.97deg) skewX(-29.64deg) scale(25.51,-20.37)}45.89%{transform:translate(110.81px,172.06px) rotate(27.79deg) skewX(-29.9deg) scale(25.05,-20.75)}46.56%{transform:translate(110.79px,171.78px) rotate(28.91deg) skewX(-29.98deg) scale(24.77,-20.98)}47.24%{transform:translate(110.79px,171.61px) rotate(29.57deg) skewX(-30deg) scale(24.6,-21.12)}47.91%{transform:translate(110.79px,171.53px) rotate(29.9deg) skewX(-30deg) scale(24.52,-21.19)}48.58%,100%{transform:translate(110.79px,171.51px) rotate(30deg) skewX(-30deg) scale(24.49,-21.21)}}
11
+ .camera-intro__front{animation-name:camera-intro-front}@keyframes camera-intro-front{0%,39.15%{transform:translate(113.63px,202.12px) rotate(8.79deg) skewX(8.79deg) scale(29.32,-24.21)}39.82%{transform:translate(113.61px,202.1px) rotate(8.86deg) skewX(8.86deg) scale(29.31,-24.2)}40.50%{transform:translate(113.54px,202.03px) rotate(9.1deg) skewX(9.1deg) scale(29.28,-24.19)}41.17%{transform:translate(113.4px,201.89px) rotate(9.57deg) skewX(9.57deg) scale(29.2,-24.15)}41.85%{transform:translate(113.17px,201.63px) rotate(10.38deg) skewX(10.38deg) scale(29.07,-24.09)}42.52%{transform:translate(112.8px,201.21px) rotate(11.77deg) skewX(11.77deg) scale(28.82,-23.98)}43.19%{transform:translate(112.24px,200.45px) rotate(14.22deg) skewX(14.22deg) scale(28.34,-23.74)}43.87%{transform:translate(111.51px,199.17px) rotate(18.43deg) skewX(18.43deg) scale(27.39,-23.24)}44.54%{transform:translate(111.03px,197.85px) rotate(22.99deg) skewX(22.99deg) scale(26.26,-22.55)}45.22%{transform:translate(110.86px,197.03px) rotate(25.97deg) skewX(25.97deg) scale(25.51,-22.02)}45.89%{transform:translate(110.81px,196.56px) rotate(27.79deg) skewX(27.79deg) scale(25.05,-21.67)}46.56%{transform:translate(110.79px,196.27px) rotate(28.91deg) skewX(28.91deg) scale(24.77,-21.44)}47.24%{transform:translate(110.79px,196.11px) rotate(29.57deg) skewX(29.57deg) scale(24.6,-21.31)}47.91%{transform:translate(110.79px,196.02px) rotate(29.9deg) skewX(29.9deg) scale(24.52,-21.23)}48.58%,100%{transform:translate(110.79px,196px) rotate(30deg) skewX(30deg) scale(24.49,-21.21)}}
12
+ .camera-intro__right{animation-name:camera-intro-right}@keyframes camera-intro-right{0%,39.15%{transform:translate(142.61px,206.61px) rotate(-65.1deg) skewX(-65.1deg) scale(18.44,-10.31)}39.82%{transform:translate(142.57px,206.62px) rotate(-64.93deg) skewX(-64.93deg) scale(18.46,-10.38)}40.50%{transform:translate(142.44px,206.66px) rotate(-64.34deg) skewX(-64.34deg) scale(18.52,-10.61)}41.17%{transform:translate(142.2px,206.74px) rotate(-63.17deg) skewX(-63.17deg) scale(18.63,-11.05)}41.85%{transform:translate(141.76px,206.87px) rotate(-61.2deg) skewX(-61.2deg) scale(18.84,-11.8)}42.52%{transform:translate(141.02px,207.09px) rotate(-57.99deg) skewX(-57.99deg) scale(19.21,-12.99)}43.19%{transform:translate(139.71px,207.41px) rotate(-52.76deg) skewX(-52.76deg) scale(19.92,-14.82)}43.87%{transform:translate(137.49px,207.83px) rotate(-45deg) skewX(-45deg) scale(21.21,-17.32)}44.54%{transform:translate(135.21px,208.11px) rotate(-38.16deg) skewX(-38.16deg) scale(22.59,-19.26)}45.22%{transform:translate(133.79px,208.2px) rotate(-34.39deg) skewX(-34.39deg) scale(23.44,-20.21)}45.89%{transform:translate(132.97px,208.23px) rotate(-32.31deg) skewX(-32.31deg) scale(23.93,-20.7)}46.56%{transform:translate(132.47px,208.24px) rotate(-31.12deg) skewX(-31.12deg) scale(24.22,-20.97)}47.24%{transform:translate(132.19px,208.25px) rotate(-30.44deg) skewX(-30.44deg) scale(24.39,-21.12)}47.91%{transform:translate(132.04px,208.25px) rotate(-30.1deg) skewX(-30.1deg) scale(24.47,-21.19)}48.58%,100%{transform:translate(132px,208.25px) rotate(-30deg) skewX(-30deg) scale(24.49,-21.21)}}
13
+ .camera-intro__e0{animation-name:camera-intro-e0}@keyframes camera-intro-e0{0%,39.15%{transform:translate(121.39px,160.9px) rotate(8.79deg) scaleX(29.32)}39.82%{transform:translate(121.43px,160.89px) rotate(8.86deg) scaleX(29.31)}40.50%{transform:translate(121.56px,160.85px) rotate(9.1deg) scaleX(29.28)}41.17%{transform:translate(121.8px,160.76px) rotate(9.57deg) scaleX(29.2)}41.85%{transform:translate(122.24px,160.63px) rotate(10.38deg) scaleX(29.07)}42.52%{transform:translate(122.98px,160.42px) rotate(11.77deg) scaleX(28.82)}43.19%{transform:translate(124.29px,160.09px) rotate(14.22deg) scaleX(28.34)}43.87%{transform:translate(126.51px,159.67px) rotate(18.43deg) scaleX(27.39)}44.54%{transform:translate(128.79px,159.4px) rotate(22.99deg) scaleX(26.26)}45.22%{transform:translate(130.21px,159.3px) rotate(25.97deg) scaleX(25.51)}45.89%{transform:translate(131.03px,159.27px) rotate(27.79deg) scaleX(25.05)}46.56%{transform:translate(131.53px,159.26px) rotate(28.91deg) scaleX(24.77)}47.24%{transform:translate(131.81px,159.26px) rotate(29.57deg) scaleX(24.6)}47.91%{transform:translate(131.96px,159.26px) rotate(29.9deg) scaleX(24.52)}48.58%,100%{transform:translate(132px,159.26px) rotate(30deg) scaleX(24.49)}}
14
+ .camera-intro__e1{animation-name:camera-intro-e1}@keyframes camera-intro-e1{0%,39.15%{transform:translate(150.37px,165.38px) rotate(114.9deg) scaleX(18.44)}39.82%{transform:translate(150.39px,165.4px) rotate(115.07deg) scaleX(18.46)}40.50%{transform:translate(150.46px,165.47px) rotate(115.66deg) scaleX(18.52)}41.17%{transform:translate(150.6px,165.62px) rotate(116.83deg) scaleX(18.63)}41.85%{transform:translate(150.83px,165.87px) rotate(118.8deg) scaleX(18.84)}42.52%{transform:translate(151.2px,166.3px) rotate(122.01deg) scaleX(19.21)}43.19%{transform:translate(151.76px,167.06px) rotate(127.24deg) scaleX(19.92)}43.87%{transform:translate(152.49px,168.34px) rotate(135deg) scaleX(21.21)}44.54%{transform:translate(152.97px,169.65px) rotate(141.84deg) scaleX(22.59)}45.22%{transform:translate(153.14px,170.47px) rotate(145.61deg) scaleX(23.44)}45.89%{transform:translate(153.19px,170.95px) rotate(147.69deg) scaleX(23.93)}46.56%{transform:translate(153.21px,171.23px) rotate(148.88deg) scaleX(24.22)}47.24%{transform:translate(153.21px,171.4px) rotate(149.56deg) scaleX(24.39)}47.91%{transform:translate(153.21px,171.48px) rotate(149.9deg) scaleX(24.47)}48.58%,100%{transform:translate(153.21px,171.51px) rotate(150deg) scaleX(24.49)}}
15
+ .camera-intro__e2{animation-name:camera-intro-e2}@keyframes camera-intro-e2{0%,39.15%{transform:translate(142.61px,182.11px) rotate(-171.21deg) scaleX(29.32)}39.82%{transform:translate(142.57px,182.12px) rotate(-171.14deg) scaleX(29.31)}40.50%{transform:translate(142.44px,182.17px) rotate(-170.9deg) scaleX(29.28)}41.17%{transform:translate(142.2px,182.25px) rotate(-170.43deg) scaleX(29.2)}41.85%{transform:translate(141.76px,182.38px) rotate(-169.62deg) scaleX(29.07)}42.52%{transform:translate(141.02px,182.59px) rotate(-168.23deg) scaleX(28.82)}43.19%{transform:translate(139.71px,182.92px) rotate(-165.78deg) scaleX(28.34)}43.87%{transform:translate(137.49px,183.34px) rotate(-161.57deg) scaleX(27.39)}44.54%{transform:translate(135.21px,183.61px) rotate(-157.01deg) scaleX(26.26)}45.22%{transform:translate(133.79px,183.71px) rotate(-154.03deg) scaleX(25.51)}45.89%{transform:translate(132.97px,183.74px) rotate(-152.21deg) scaleX(25.05)}46.56%{transform:translate(132.47px,183.75px) rotate(-151.09deg) scaleX(24.77)}47.24%{transform:translate(132.19px,183.75px) rotate(-150.43deg) scaleX(24.6)}47.91%{transform:translate(132.04px,183.75px) rotate(-150.1deg) scaleX(24.52)}48.58%,100%{transform:translate(132px,183.75px) rotate(-150deg) scaleX(24.49)}}
16
+ .camera-intro__e3{animation-name:camera-intro-e3}@keyframes camera-intro-e3{0%,39.15%{transform:translate(113.63px,177.63px) rotate(-65.1deg) scaleX(18.44)}39.82%{transform:translate(113.61px,177.61px) rotate(-64.93deg) scaleX(18.46)}40.50%{transform:translate(113.54px,177.54px) rotate(-64.34deg) scaleX(18.52)}41.17%{transform:translate(113.4px,177.39px) rotate(-63.17deg) scaleX(18.63)}41.85%{transform:translate(113.17px,177.14px) rotate(-61.2deg) scaleX(18.84)}42.52%{transform:translate(112.8px,176.71px) rotate(-57.99deg) scaleX(19.21)}43.19%{transform:translate(112.24px,175.96px) rotate(-52.76deg) scaleX(19.92)}43.87%{transform:translate(111.51px,174.67px) rotate(-45deg) scaleX(21.21)}44.54%{transform:translate(111.03px,173.36px) rotate(-38.16deg) scaleX(22.59)}45.22%{transform:translate(110.86px,172.54px) rotate(-34.39deg) scaleX(23.44)}45.89%{transform:translate(110.81px,172.06px) rotate(-32.31deg) scaleX(23.93)}46.56%{transform:translate(110.79px,171.78px) rotate(-31.12deg) scaleX(24.22)}47.24%{transform:translate(110.79px,171.61px) rotate(-30.44deg) scaleX(24.39)}47.91%{transform:translate(110.79px,171.53px) rotate(-30.1deg) scaleX(24.47)}48.58%,100%{transform:translate(110.79px,171.51px) rotate(-30deg) scaleX(24.49)}}
17
+ .camera-intro__e4{animation-name:camera-intro-e4}@keyframes camera-intro-e4{0%,39.15%{transform:translate(113.63px,177.63px) rotate(90deg) scaleX(24.49)}39.82%{transform:translate(113.61px,177.61px) rotate(90deg) scaleX(24.49)}40.50%{transform:translate(113.54px,177.54px) rotate(90deg) scaleX(24.49)}41.17%{transform:translate(113.4px,177.39px) rotate(90deg) scaleX(24.49)}41.85%{transform:translate(113.17px,177.14px) rotate(90deg) scaleX(24.49)}42.52%{transform:translate(112.8px,176.71px) rotate(90deg) scaleX(24.49)}43.19%{transform:translate(112.24px,175.96px) rotate(90deg) scaleX(24.49)}43.87%{transform:translate(111.51px,174.67px) rotate(90deg) scaleX(24.49)}44.54%{transform:translate(111.03px,173.36px) rotate(90deg) scaleX(24.49)}45.22%{transform:translate(110.86px,172.54px) rotate(90deg) scaleX(24.49)}45.89%{transform:translate(110.81px,172.06px) rotate(90deg) scaleX(24.49)}46.56%{transform:translate(110.79px,171.78px) rotate(90deg) scaleX(24.49)}47.24%{transform:translate(110.79px,171.61px) rotate(90deg) scaleX(24.49)}47.91%{transform:translate(110.79px,171.53px) rotate(90deg) scaleX(24.49)}48.58%,100%{transform:translate(110.79px,171.51px) rotate(90deg) scaleX(24.49)}}
18
+ .camera-intro__e5{animation-name:camera-intro-e5}@keyframes camera-intro-e5{0%,39.15%{transform:translate(142.61px,182.11px) rotate(90deg) scaleX(24.49)}39.82%{transform:translate(142.57px,182.12px) rotate(90deg) scaleX(24.49)}40.50%{transform:translate(142.44px,182.17px) rotate(90deg) scaleX(24.49)}41.17%{transform:translate(142.2px,182.25px) rotate(90deg) scaleX(24.49)}41.85%{transform:translate(141.76px,182.38px) rotate(90deg) scaleX(24.49)}42.52%{transform:translate(141.02px,182.59px) rotate(90deg) scaleX(24.49)}43.19%{transform:translate(139.71px,182.92px) rotate(90deg) scaleX(24.49)}43.87%{transform:translate(137.49px,183.34px) rotate(90deg) scaleX(24.49)}44.54%{transform:translate(135.21px,183.61px) rotate(90deg) scaleX(24.49)}45.22%{transform:translate(133.79px,183.71px) rotate(90deg) scaleX(24.49)}45.89%{transform:translate(132.97px,183.74px) rotate(90deg) scaleX(24.49)}46.56%{transform:translate(132.47px,183.75px) rotate(90deg) scaleX(24.49)}47.24%{transform:translate(132.19px,183.75px) rotate(90deg) scaleX(24.49)}47.91%{transform:translate(132.04px,183.75px) rotate(90deg) scaleX(24.49)}48.58%,100%{transform:translate(132px,183.75px) rotate(90deg) scaleX(24.49)}}
19
+ .camera-intro__e6{animation-name:camera-intro-e6}@keyframes camera-intro-e6{0%,39.15%{transform:translate(150.37px,165.38px) rotate(90deg) scaleX(24.49)}39.82%{transform:translate(150.39px,165.4px) rotate(90deg) scaleX(24.49)}40.50%{transform:translate(150.46px,165.47px) rotate(90deg) scaleX(24.49)}41.17%{transform:translate(150.6px,165.62px) rotate(90deg) scaleX(24.49)}41.85%{transform:translate(150.83px,165.87px) rotate(90deg) scaleX(24.49)}42.52%{transform:translate(151.2px,166.3px) rotate(90deg) scaleX(24.49)}43.19%{transform:translate(151.76px,167.06px) rotate(90deg) scaleX(24.49)}43.87%{transform:translate(152.49px,168.34px) rotate(90deg) scaleX(24.49)}44.54%{transform:translate(152.97px,169.65px) rotate(90deg) scaleX(24.49)}45.22%{transform:translate(153.14px,170.47px) rotate(90deg) scaleX(24.49)}45.89%{transform:translate(153.19px,170.95px) rotate(90deg) scaleX(24.49)}46.56%{transform:translate(153.21px,171.23px) rotate(90deg) scaleX(24.49)}47.24%{transform:translate(153.21px,171.4px) rotate(90deg) scaleX(24.49)}47.91%{transform:translate(153.21px,171.48px) rotate(90deg) scaleX(24.49)}48.58%,100%{transform:translate(153.21px,171.51px) rotate(90deg) scaleX(24.49)}}
20
+ .camera-intro__e7{animation-name:camera-intro-e7}@keyframes camera-intro-e7{0%,39.15%{transform:translate(113.63px,202.12px) rotate(8.79deg) scaleX(29.32)}39.82%{transform:translate(113.61px,202.1px) rotate(8.86deg) scaleX(29.31)}40.50%{transform:translate(113.54px,202.03px) rotate(9.1deg) scaleX(29.28)}41.17%{transform:translate(113.4px,201.89px) rotate(9.57deg) scaleX(29.2)}41.85%{transform:translate(113.17px,201.63px) rotate(10.38deg) scaleX(29.07)}42.52%{transform:translate(112.8px,201.21px) rotate(11.77deg) scaleX(28.82)}43.19%{transform:translate(112.24px,200.45px) rotate(14.22deg) scaleX(28.34)}43.87%{transform:translate(111.51px,199.17px) rotate(18.43deg) scaleX(27.39)}44.54%{transform:translate(111.03px,197.85px) rotate(22.99deg) scaleX(26.26)}45.22%{transform:translate(110.86px,197.03px) rotate(25.97deg) scaleX(25.51)}45.89%{transform:translate(110.81px,196.56px) rotate(27.79deg) scaleX(25.05)}46.56%{transform:translate(110.79px,196.27px) rotate(28.91deg) scaleX(24.77)}47.24%{transform:translate(110.79px,196.11px) rotate(29.57deg) scaleX(24.6)}47.91%{transform:translate(110.79px,196.02px) rotate(29.9deg) scaleX(24.52)}48.58%,100%{transform:translate(110.79px,196px) rotate(30deg) scaleX(24.49)}}
21
+ .camera-intro__e8{animation-name:camera-intro-e8}@keyframes camera-intro-e8{0%,39.15%{transform:translate(142.61px,206.61px) rotate(-65.1deg) scaleX(18.44)}39.82%{transform:translate(142.57px,206.62px) rotate(-64.93deg) scaleX(18.46)}40.50%{transform:translate(142.44px,206.66px) rotate(-64.34deg) scaleX(18.52)}41.17%{transform:translate(142.2px,206.74px) rotate(-63.17deg) scaleX(18.63)}41.85%{transform:translate(141.76px,206.87px) rotate(-61.2deg) scaleX(18.84)}42.52%{transform:translate(141.02px,207.09px) rotate(-57.99deg) scaleX(19.21)}43.19%{transform:translate(139.71px,207.41px) rotate(-52.76deg) scaleX(19.92)}43.87%{transform:translate(137.49px,207.83px) rotate(-45deg) scaleX(21.21)}44.54%{transform:translate(135.21px,208.11px) rotate(-38.16deg) scaleX(22.59)}45.22%{transform:translate(133.79px,208.2px) rotate(-34.39deg) scaleX(23.44)}45.89%{transform:translate(132.97px,208.23px) rotate(-32.31deg) scaleX(23.93)}46.56%{transform:translate(132.47px,208.24px) rotate(-31.12deg) scaleX(24.22)}47.24%{transform:translate(132.19px,208.25px) rotate(-30.44deg) scaleX(24.39)}47.91%{transform:translate(132.04px,208.25px) rotate(-30.1deg) scaleX(24.47)}48.58%,100%{transform:translate(132px,208.25px) rotate(-30deg) scaleX(24.49)}}
22
+ .camera-intro__vTbl{animation-name:camera-intro-vTbl}@keyframes camera-intro-vTbl{0%,39.15%{transform:translate(121.39px,160.9px)}39.82%{transform:translate(121.43px,160.89px)}40.50%{transform:translate(121.56px,160.85px)}41.17%{transform:translate(121.8px,160.76px)}41.85%{transform:translate(122.24px,160.63px)}42.52%{transform:translate(122.98px,160.42px)}43.19%{transform:translate(124.29px,160.09px)}43.87%{transform:translate(126.51px,159.67px)}44.54%{transform:translate(128.79px,159.4px)}45.22%{transform:translate(130.21px,159.3px)}45.89%{transform:translate(131.03px,159.27px)}46.56%{transform:translate(131.53px,159.26px)}47.24%{transform:translate(131.81px,159.26px)}47.91%{transform:translate(131.96px,159.26px)}48.58%,100%{transform:translate(132px,159.26px)}}
23
+ .camera-intro__vTbr{animation-name:camera-intro-vTbr}@keyframes camera-intro-vTbr{0%,39.15%{transform:translate(150.37px,165.38px)}39.82%{transform:translate(150.39px,165.4px)}40.50%{transform:translate(150.46px,165.47px)}41.17%{transform:translate(150.6px,165.62px)}41.85%{transform:translate(150.83px,165.87px)}42.52%{transform:translate(151.2px,166.3px)}43.19%{transform:translate(151.76px,167.06px)}43.87%{transform:translate(152.49px,168.34px)}44.54%{transform:translate(152.97px,169.65px)}45.22%{transform:translate(153.14px,170.47px)}45.89%{transform:translate(153.19px,170.95px)}46.56%{transform:translate(153.21px,171.23px)}47.24%{transform:translate(153.21px,171.4px)}47.91%{transform:translate(153.21px,171.48px)}48.58%,100%{transform:translate(153.21px,171.51px)}}
24
+ .camera-intro__vTfl{animation-name:camera-intro-vTfl}@keyframes camera-intro-vTfl{0%,39.15%{transform:translate(113.63px,177.63px)}39.82%{transform:translate(113.61px,177.61px)}40.50%{transform:translate(113.54px,177.54px)}41.17%{transform:translate(113.4px,177.39px)}41.85%{transform:translate(113.17px,177.14px)}42.52%{transform:translate(112.8px,176.71px)}43.19%{transform:translate(112.24px,175.96px)}43.87%{transform:translate(111.51px,174.67px)}44.54%{transform:translate(111.03px,173.36px)}45.22%{transform:translate(110.86px,172.54px)}45.89%{transform:translate(110.81px,172.06px)}46.56%{transform:translate(110.79px,171.78px)}47.24%{transform:translate(110.79px,171.61px)}47.91%{transform:translate(110.79px,171.53px)}48.58%,100%{transform:translate(110.79px,171.51px)}}
25
+ .camera-intro__vTfr{animation-name:camera-intro-vTfr}@keyframes camera-intro-vTfr{0%,39.15%{transform:translate(142.61px,182.11px)}39.82%{transform:translate(142.57px,182.12px)}40.50%{transform:translate(142.44px,182.17px)}41.17%{transform:translate(142.2px,182.25px)}41.85%{transform:translate(141.76px,182.38px)}42.52%{transform:translate(141.02px,182.59px)}43.19%{transform:translate(139.71px,182.92px)}43.87%{transform:translate(137.49px,183.34px)}44.54%{transform:translate(135.21px,183.61px)}45.22%{transform:translate(133.79px,183.71px)}45.89%{transform:translate(132.97px,183.74px)}46.56%{transform:translate(132.47px,183.75px)}47.24%{transform:translate(132.19px,183.75px)}47.91%{transform:translate(132.04px,183.75px)}48.58%,100%{transform:translate(132px,183.75px)}}
26
+ .camera-intro__vBfl{animation-name:camera-intro-vBfl}@keyframes camera-intro-vBfl{0%,39.15%{transform:translate(113.63px,202.12px)}39.82%{transform:translate(113.61px,202.1px)}40.50%{transform:translate(113.54px,202.03px)}41.17%{transform:translate(113.4px,201.89px)}41.85%{transform:translate(113.17px,201.63px)}42.52%{transform:translate(112.8px,201.21px)}43.19%{transform:translate(112.24px,200.45px)}43.87%{transform:translate(111.51px,199.17px)}44.54%{transform:translate(111.03px,197.85px)}45.22%{transform:translate(110.86px,197.03px)}45.89%{transform:translate(110.81px,196.56px)}46.56%{transform:translate(110.79px,196.27px)}47.24%{transform:translate(110.79px,196.11px)}47.91%{transform:translate(110.79px,196.02px)}48.58%,100%{transform:translate(110.79px,196px)}}
27
+ .camera-intro__vBfr{animation-name:camera-intro-vBfr}@keyframes camera-intro-vBfr{0%,39.15%{transform:translate(142.61px,206.61px)}39.82%{transform:translate(142.57px,206.62px)}40.50%{transform:translate(142.44px,206.66px)}41.17%{transform:translate(142.2px,206.74px)}41.85%{transform:translate(141.76px,206.87px)}42.52%{transform:translate(141.02px,207.09px)}43.19%{transform:translate(139.71px,207.41px)}43.87%{transform:translate(137.49px,207.83px)}44.54%{transform:translate(135.21px,208.11px)}45.22%{transform:translate(133.79px,208.2px)}45.89%{transform:translate(132.97px,208.23px)}46.56%{transform:translate(132.47px,208.24px)}47.24%{transform:translate(132.19px,208.25px)}47.91%{transform:translate(132.04px,208.25px)}48.58%,100%{transform:translate(132px,208.25px)}}
28
+ .camera-intro__vBbr{animation-name:camera-intro-vBbr}@keyframes camera-intro-vBbr{0%,39.15%{transform:translate(150.37px,189.88px)}39.82%{transform:translate(150.39px,189.9px)}40.50%{transform:translate(150.46px,189.97px)}41.17%{transform:translate(150.6px,190.11px)}41.85%{transform:translate(150.83px,190.37px)}42.52%{transform:translate(151.2px,190.79px)}43.19%{transform:translate(151.76px,191.55px)}43.87%{transform:translate(152.49px,192.83px)}44.54%{transform:translate(152.97px,194.15px)}45.22%{transform:translate(153.14px,194.97px)}45.89%{transform:translate(153.19px,195.44px)}46.56%{transform:translate(153.21px,195.73px)}47.24%{transform:translate(153.21px,195.89px)}47.91%{transform:translate(153.21px,195.98px)}48.58%,100%{transform:translate(153.21px,196px)}}
29
+ @keyframes camera-intro-move{0%,55.66%{transform:none;animation-timing-function:cubic-bezier(.7,0,.3,1)}65.09%,100%{transform:translate(0px,-53.59px) scale(0.85)}}
30
+ @keyframes camera-intro-finger{0%,36.79%{opacity:0;transform:translate(150px,230px);animation-timing-function:cubic-bezier(.34,1.56,.64,1)}39.15%{opacity:1;transform:translate(150px,224px);animation-timing-function:cubic-bezier(.7,0,.3,1)}48.58%{opacity:1;transform:translate(114px,224px);animation-timing-function:cubic-bezier(.5,0,.75,0)}51.42%{opacity:0;transform:translate(114px,230px)}53.30%{opacity:0;transform:translate(132px,189.75px);animation-timing-function:cubic-bezier(.34,1.56,.64,1)}55.66%{opacity:1;transform:translate(132px,183.75px);animation-timing-function:cubic-bezier(.7,0,.3,1)}65.09%{opacity:1;transform:translate(132px,132px);animation-timing-function:cubic-bezier(.5,0,.75,0)}67.92%,100%{opacity:0;transform:translate(132px,138px)}}
31
+ @keyframes camera-intro-ring{0%,36.79%{transform:scale(.4);animation-timing-function:cubic-bezier(.34,1.56,.64,1)}39.15%,48.58%{transform:scale(1);animation-timing-function:ease-out}51.42%{transform:scale(1.6)}53.30%{transform:scale(.4);animation-timing-function:cubic-bezier(.34,1.56,.64,1)}55.66%,65.09%{transform:scale(1);animation-timing-function:ease-out}67.92%,100%{transform:scale(1.6)}}
32
+ .camera-intro__pan{transform-box:view-box;animation:camera-intro-pan 10.6s infinite both}
33
+ @keyframes camera-intro-pan{0%,7.55%{transform:translate(0,0);animation-timing-function:cubic-bezier(.45,0,.55,1)}12.26%{transform:translate(0,-16px);animation-timing-function:cubic-bezier(.45,0,.55,1)}17.45%{transform:translate(-10px,-16px);animation-timing-function:cubic-bezier(.45,0,.55,1)}23.11%{transform:translate(10px,-16px);animation-timing-function:cubic-bezier(.45,0,.55,1)}27.36%,100%{transform:translate(0,0)}}
34
+ .camera-intro__d104{animation:camera-intro-d104 10.6s infinite both}@keyframes camera-intro-d104{0%,20.75%{opacity:0}22.17%,32.08%{opacity:1}36.79%,100%{opacity:0}}
35
+ .camera-intro__d112{animation:camera-intro-d112 10.6s infinite both}@keyframes camera-intro-d112{0%,19.81%{opacity:0}21.23%,32.08%{opacity:1}36.79%,100%{opacity:0}}
36
+ .camera-intro__d120{animation:camera-intro-d120 10.6s infinite both}@keyframes camera-intro-d120{0%,18.87%{opacity:0}20.28%,32.08%{opacity:1}36.79%,100%{opacity:0}}
37
+ .camera-intro__d128{animation:camera-intro-d128 10.6s infinite both}@keyframes camera-intro-d128{0%,17.92%{opacity:0}19.34%,32.08%{opacity:1}36.79%,100%{opacity:0}}
38
+ .camera-intro__d136{animation:camera-intro-d136 10.6s infinite both}@keyframes camera-intro-d136{0%,12.74%{opacity:0}14.15%,32.08%{opacity:1}36.79%,100%{opacity:0}}
39
+ .camera-intro__d144{animation:camera-intro-d144 10.6s infinite both}@keyframes camera-intro-d144{0%,13.68%{opacity:0}15.09%,32.08%{opacity:1}36.79%,100%{opacity:0}}
40
+ .camera-intro__d152{animation:camera-intro-d152 10.6s infinite both}@keyframes camera-intro-d152{0%,14.62%{opacity:0}16.04%,32.08%{opacity:1}36.79%,100%{opacity:0}}
41
+ .camera-intro__d160{animation:camera-intro-d160 10.6s infinite both}@keyframes camera-intro-d160{0%,15.57%{opacity:0}16.98%,32.08%{opacity:1}36.79%,100%{opacity:0}}
42
+
43
+ .camera-intro__bg{animation:camera-intro-bg 10.6s infinite both}
44
+ @keyframes camera-intro-bg{0%,59.43%{opacity:1}66.04%,100%{opacity:0}}
45
+ .camera-intro__stand{animation:camera-intro-standfade 10.6s infinite both}
46
+ @keyframes camera-intro-standfade{0%,30.19%{opacity:0;transform:scale(.6);animation-timing-function:cubic-bezier(.34,1.56,.64,1)}33.96%,60.38%{opacity:1;transform:none}65.09%,100%{opacity:0;transform:none}}
47
+ .camera-intro__faces{animation:camera-intro-faces 10.6s infinite both}
48
+ @keyframes camera-intro-faces{0%,69.81%{opacity:1}73.11%,100%{opacity:0}}
49
+ .camera-intro__wire{animation:camera-intro-wire 10.6s infinite both}
50
+ @keyframes camera-intro-wire{0%,69.81%{opacity:1}69.91%,100%{opacity:0}}
51
+ .camera-intro__logo{animation:camera-intro-logo 10.6s infinite both}
52
+ @keyframes camera-intro-logo{0%,69.81%{opacity:0}69.91%,100%{opacity:1}}
53
+ .camera-intro__lw{animation:camera-intro-lw 10.6s infinite both}
54
+ @keyframes camera-intro-lw{0%,78.30%{stroke-width:1.7px;animation-timing-function:cubic-bezier(.34,1.56,.64,1)}81.60%,100%{stroke-width:4.37px}}
55
+ .camera-intro__spin{transform-box:view-box;transform-origin:132px 132px;animation:camera-intro-spin 10.6s infinite both}
56
+ @keyframes camera-intro-spin{0%,71.70%{transform:rotate(0deg);animation-timing-function:cubic-bezier(.5,0,.9,.6)}74.06%{transform:rotate(30deg) scale(.86);animation-timing-function:cubic-bezier(.2,.5,.4,1.25)}76.60%,100%{transform:rotate(60deg) scale(1)}}
57
+ .camera-intro__orbit{stroke-dasharray:1;transform-box:view-box;transform-origin:132px 132px;transform:rotate(-90deg);animation:camera-intro-orbit 10.6s infinite both}
58
+ @keyframes camera-intro-orbit{0%,72.55%{stroke-dashoffset:1;opacity:0}72.64%{stroke-dashoffset:1;opacity:1;animation-timing-function:cubic-bezier(.45,0,.3,1)}77.36%,78.77%{stroke-dashoffset:0;opacity:1}80.66%,100%{stroke-dashoffset:0;opacity:0}}
59
+ .camera-intro__disc{transform-box:view-box;transform-origin:132px 132px;animation:camera-intro-disc 10.6s infinite both}
60
+ @keyframes camera-intro-disc{0%,76.89%{transform:scale(0);animation-timing-function:cubic-bezier(.34,1.56,.64,1)}80.66%,100%{transform:none}}
61
+ .camera-intro__hub{transform-box:view-box;transform-origin:132px 132px;animation:camera-intro-hub 10.6s infinite both}
62
+ @keyframes camera-intro-hub{0%,79.72%{transform:scale(0);animation-timing-function:cubic-bezier(.34,1.56,.64,1)}83.02%,100%{transform:none}}
63
+ .camera-intro__all{animation:camera-intro-all 10.6s infinite both}
64
+ @keyframes camera-intro-all{0%,2.83%{opacity:0}7.55%,92.45%{opacity:1}97.17%,100%{opacity:0}}
65
+
66
+ @media (prefers-reduced-motion:reduce){
67
+ .camera-intro__k,.camera-intro__move,.camera-intro__drop,.camera-intro__finger,.camera-intro__stand,.camera-intro__ring,.camera-intro__bg,.camera-intro__all,.camera-intro__pan,.camera-intro__dot,.camera-intro__faces,.camera-intro__wire,.camera-intro__logo,.camera-intro__lw,.camera-intro__spin,.camera-intro__orbit,.camera-intro__disc,.camera-intro__hub{animation:none}
68
+ .camera-intro__bg,.camera-intro__all,.camera-intro__drop,.camera-intro__stand,.camera-intro__faces,.camera-intro__wire{opacity:1;transform:none}
69
+ .camera-intro__move,.camera-intro__pan{transform:none}
70
+ .camera-intro__finger,.camera-intro__dot,.camera-intro__logo,.camera-intro__disc,.camera-intro__orbit{opacity:0}
71
+ .camera-intro__top{transform:translate(110.79px,171.51px) rotate(30deg) skewX(-30deg) scale(24.49,-21.21)}
72
+ .camera-intro__front{transform:translate(110.79px,196px) rotate(30deg) skewX(30deg) scale(24.49,-21.21)}
73
+ .camera-intro__right{transform:translate(132px,208.25px) rotate(-30deg) skewX(-30deg) scale(24.49,-21.21)}
74
+ .camera-intro__e0{transform:translate(132px,159.26px) rotate(30deg) scaleX(24.49)}
75
+ .camera-intro__e1{transform:translate(153.21px,171.51px) rotate(150deg) scaleX(24.49)}
76
+ .camera-intro__e2{transform:translate(132px,183.75px) rotate(-150deg) scaleX(24.49)}
77
+ .camera-intro__e3{transform:translate(110.79px,171.51px) rotate(-30deg) scaleX(24.49)}
78
+ .camera-intro__e4{transform:translate(110.79px,171.51px) rotate(90deg) scaleX(24.49)}
79
+ .camera-intro__e5{transform:translate(132px,183.75px) rotate(90deg) scaleX(24.49)}
80
+ .camera-intro__e6{transform:translate(153.21px,171.51px) rotate(90deg) scaleX(24.49)}
81
+ .camera-intro__e7{transform:translate(110.79px,196px) rotate(30deg) scaleX(24.49)}
82
+ .camera-intro__e8{transform:translate(132px,208.25px) rotate(-30deg) scaleX(24.49)}
83
+ .camera-intro__vTbl{transform:translate(132px,159.26px)}
84
+ .camera-intro__vTbr{transform:translate(153.21px,171.51px)}
85
+ .camera-intro__vTfl{transform:translate(110.79px,171.51px)}
86
+ .camera-intro__vTfr{transform:translate(132px,183.75px)}
87
+ .camera-intro__vBfl{transform:translate(110.79px,196px)}
88
+ .camera-intro__vBfr{transform:translate(132px,208.25px)}
89
+ .camera-intro__vBbr{transform:translate(153.21px,196px)}
90
+ }
91
+ </style>
92
+ <defs>
93
+ <clipPath id="camera-intro-scr"><rect x="87" y="31" width="90" height="202" rx="13"/></clipPath>
94
+ <linearGradient id="camera-intro-gw" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#4B4D58"/><stop offset="1" stop-color="#3B3C45"/></linearGradient>
95
+ <linearGradient id="camera-intro-gfl" x1="0" y1="150" x2="0" y2="233" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#34353D"/><stop offset="1" stop-color="#1F2025"/></linearGradient>
96
+ <linearGradient id="camera-intro-gc" x1="0" y1="31" x2="0" y2="92" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#202127"/><stop offset="1" stop-color="#33343C"/></linearGradient>
97
+ <linearGradient id="camera-intro-gl" x1="87" y1="0" x2="177" y2="0" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#26272D"/><stop offset=".2" stop-color="#35363E" stop-opacity="0"/><stop offset=".8" stop-color="#35363E" stop-opacity="0"/><stop offset="1" stop-color="#26272D"/></linearGradient>
98
+ <linearGradient id="camera-intro-gwin" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#8A8EA0"/><stop offset="1" stop-color="#666979"/></linearGradient>
99
+ <linearGradient id="camera-intro-glt" x1="0" y1="150" x2="0" y2="200" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fff" stop-opacity=".1"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient>
100
+ <linearGradient id="camera-intro-gt" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#7A7B86"/><stop offset="1" stop-color="#666772"/></linearGradient>
101
+ <linearGradient id="camera-intro-gf" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#55565F"/><stop offset="1" stop-color="#43444C"/></linearGradient>
102
+ <linearGradient id="camera-intro-gr" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#3D3E46"/><stop offset="1" stop-color="#2E2F35"/></linearGradient>
103
+ <radialGradient id="camera-intro-sh"><stop offset="0" stop-color="#000" stop-opacity=".5"/><stop offset="1" stop-color="#000" stop-opacity="0"/></radialGradient>
104
+ <linearGradient id="camera-intro-o" x1="107.37" y1="156.63" x2="156.63" y2="107.37" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#E2335C"/><stop offset=".5" stop-color="#F0622E"/><stop offset="1" stop-color="#F8A43C"/></linearGradient>
105
+ </defs>
106
+ <rect x="83" y="27" width="98" height="210" rx="17" fill="#121317" stroke="#E9EAEE" stroke-width="2.5"/>
107
+ <path d="M81.5 70V84M81.5 92V106M182.5 80V102" stroke="#E9EAEE" stroke-width="2" stroke-linecap="round"/>
108
+ <rect x="87" y="31" width="90" height="202" rx="13" fill="#1B1C21"/>
109
+ <g clip-path="url(#camera-intro-scr)"><g class="camera-intro__all">
110
+ <g class="camera-intro__bg">
111
+ <g class="camera-intro__pan">
112
+ <path d="M100 92L-45.66 -40H309.66L164 92Z" fill="url(#camera-intro-gc)"/><path d="M100 92L-45.66 -40V300L100 150ZM164 92L309.66 -40V300L164 150Z" fill="#2C2D34"/><path d="M100 150L-65.52 300H329.52L164 150Z" fill="url(#camera-intro-gfl)"/>
113
+ <path d="M100 92H164V150H100Z" fill="url(#camera-intro-gw)"/>
114
+ <rect x="116" y="102" width="32" height="30" rx="2" fill="url(#camera-intro-gwin)"/>
115
+ <path d="M116 150H148L175.59 200H88.41Z" fill="url(#camera-intro-glt)"/>
116
+ <g fill="#5B6BFF"><g class="camera-intro__dot camera-intro__d104"><circle cx="92.41" cy="162" r="0.96"/><circle cx="78.9" cy="176" r="1.27"/><circle cx="61.52" cy="194" r="1.67"/><circle cx="40.28" cy="216" r="2.15"/><circle cx="15.17" cy="242" r="2.72"/></g><g class="camera-intro__dot camera-intro__d112"><circle cx="103.72" cy="162" r="0.96"/><circle cx="94.07" cy="176" r="1.27"/><circle cx="81.66" cy="194" r="1.67"/><circle cx="66.48" cy="216" r="2.15"/><circle cx="48.55" cy="242" r="2.72"/></g><g class="camera-intro__dot camera-intro__d120"><circle cx="115.03" cy="162" r="0.96"/><circle cx="109.24" cy="176" r="1.27"/><circle cx="101.79" cy="194" r="1.67"/><circle cx="92.69" cy="216" r="2.15"/><circle cx="81.93" cy="242" r="2.72"/></g><g class="camera-intro__dot camera-intro__d128"><circle cx="126.34" cy="162" r="0.96"/><circle cx="124.41" cy="176" r="1.27"/><circle cx="121.93" cy="194" r="1.67"/><circle cx="118.9" cy="216" r="2.15"/><circle cx="115.31" cy="242" r="2.72"/></g><g class="camera-intro__dot camera-intro__d136"><circle cx="137.66" cy="162" r="0.96"/><circle cx="139.59" cy="176" r="1.27"/><circle cx="142.07" cy="194" r="1.67"/><circle cx="145.1" cy="216" r="2.15"/><circle cx="148.69" cy="242" r="2.72"/></g><g class="camera-intro__dot camera-intro__d144"><circle cx="148.97" cy="162" r="0.96"/><circle cx="154.76" cy="176" r="1.27"/><circle cx="162.21" cy="194" r="1.67"/><circle cx="171.31" cy="216" r="2.15"/><circle cx="182.07" cy="242" r="2.72"/></g><g class="camera-intro__dot camera-intro__d152"><circle cx="160.28" cy="162" r="0.96"/><circle cx="169.93" cy="176" r="1.27"/><circle cx="182.34" cy="194" r="1.67"/><circle cx="197.52" cy="216" r="2.15"/><circle cx="215.45" cy="242" r="2.72"/></g><g class="camera-intro__dot camera-intro__d160"><circle cx="171.59" cy="162" r="0.96"/><circle cx="185.1" cy="176" r="1.27"/><circle cx="202.48" cy="194" r="1.67"/><circle cx="223.72" cy="216" r="2.15"/><circle cx="248.83" cy="242" r="2.72"/></g></g>
117
+ </g>
118
+ <rect x="87" y="31" width="90" height="202" fill="url(#camera-intro-gl)"/>
119
+ </g>
120
+ <circle class="camera-intro__disc" cx="132" cy="132" r="35.19" fill="url(#camera-intro-o)"/>
121
+ <circle class="camera-intro__orbit" pathLength="1" cx="132" cy="132" r="35.19" fill="none" stroke="#fff" stroke-opacity=".6" stroke-width="1.5" stroke-linecap="round"/>
122
+ <g class="camera-intro__drop"><g class="camera-intro__move">
123
+ <g class="camera-intro__stand"><ellipse cx="132" cy="199" rx="29.93" ry="18.85" fill="url(#camera-intro-sh)"/>
124
+ <ellipse cx="132" cy="196" rx="27.21" ry="15.71" fill="none" stroke="#fff" stroke-opacity=".5" stroke-width="1.5"/></g>
125
+ <g class="camera-intro__faces"><path class="camera-intro__k camera-intro__top" d="M0 0H1V1H0Z" fill="url(#camera-intro-gt)"/><path class="camera-intro__k camera-intro__front" d="M0 0H1V1H0Z" fill="url(#camera-intro-gf)"/><path class="camera-intro__k camera-intro__right" d="M0 0H1V1H0Z" fill="url(#camera-intro-gr)"/></g>
126
+ <g class="camera-intro__wire"><g stroke="#F4F5F8" stroke-width="2" fill="none"><path class="camera-intro__k camera-intro__e0" d="M0 0H1"/><path class="camera-intro__k camera-intro__e1" d="M0 0H1"/><path class="camera-intro__k camera-intro__e2" d="M0 0H1"/><path class="camera-intro__k camera-intro__e3" d="M0 0H1"/><path class="camera-intro__k camera-intro__e4" d="M0 0H1"/><path class="camera-intro__k camera-intro__e5" d="M0 0H1"/><path class="camera-intro__k camera-intro__e6" d="M0 0H1"/><path class="camera-intro__k camera-intro__e7" d="M0 0H1"/><path class="camera-intro__k camera-intro__e8" d="M0 0H1"/></g><g fill="#F4F5F8"><circle class="camera-intro__k camera-intro__vTbl" r="1"/><circle class="camera-intro__k camera-intro__vTbr" r="1"/><circle class="camera-intro__k camera-intro__vTfl" r="1"/><circle class="camera-intro__k camera-intro__vTfr" r="1"/><circle class="camera-intro__k camera-intro__vBfl" r="1"/><circle class="camera-intro__k camera-intro__vBfr" r="1"/><circle class="camera-intro__k camera-intro__vBbr" r="1"/></g></g>
127
+ </g></g>
128
+ <g class="camera-intro__logo" fill="none" stroke="#F4F5F8" stroke-linejoin="round" stroke-linecap="round">
129
+ <path class="camera-intro__lw" d="M132 152.82L113.97 142.41L113.97 121.59L132 111.18L150.03 121.59L150.03 142.41Z"/>
130
+ <g class="camera-intro__spin"><path class="camera-intro__lw" d="M132 132L113.97 121.59M132 132L150.03 121.59M132 132L132 152.82"/></g>
131
+ <circle class="camera-intro__hub" cx="132" cy="132" r="6.04" fill="url(#camera-intro-o)" stroke-width="4.37"/>
132
+ </g>
133
+ <g class="camera-intro__finger">
134
+ <circle class="camera-intro__ring" r="8" fill="#fff" stroke="#5B6BFF" stroke-opacity=".7" stroke-width="1.75"/>
135
+ <circle r="5" fill="#5B6BFF"/>
136
+ </g>
137
+ </g></g>
138
+ <rect x="119" y="36" width="26" height="8" rx="4" fill="#000"/>
139
+ </svg>